diff --git a/.gitignore b/.gitignore index 20f4f5fec..8334e0bdf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,138 +1,56 @@ -# installation +# Installation *.o *.cxx *.h.gch *.so -*.pbs.e* -*.pbs.o* *.pyc -*/*.o -*/*.cxx -*/*.h.gch -*/*.so +*.o +*.cxx +*.h.gch +*.so *~ -*/*~ -*/*.pbs.e* -*/*.pbs.o* -*/*.pyc -build build/* -dist dist/* openmoc/openmoc.py openmoc/openmoc_wrap.cpp - -openmoc/mic/openmoc_mic.py -openmoc/mic/openmoc_mic_wrap.cpp - -openmoc/intel/single/openmoc_intel_single_wrap.cpp -openmoc/intel/single/openmoc_intel_single.py -openmoc/intel/double/openmoc_intel_double_wrap.cpp -openmoc/intel/double/openmoc_intel_double.py - -openmoc/gnu/single/openmoc_gnu_single_wrap.cpp -openmoc/gnu/single/openmoc_gnu_single.py -openmoc/gnu/double/openmoc_gnu_double_wrap.cpp -openmoc/gnu/double/openmoc_gnu_double.py - -openmoc/bgq/single/openmoc_bgq_single_wrap.cpp -openmoc/bgq/single/openmoc_bgq_double.py -openmoc/bgq/double/openmoc_bgq_double_wrap.cpp -openmoc/bgq/double/openmoc_bgq_double.py - openmoc/cuda/openmoc_cuda.py openmoc/cuda/openmoc_cuda_wrap.cpp -openmoc/cuda/single/openmoc_cuda_single_wrap.cpp -openmoc/cuda/single/openmoc_cuda_single.py -openmoc/cuda/double/openmoc_cuda_double_wrap.cpp -openmoc/cuda/double/openmoc_cuda_double.py +# TORQUE log files +*.pbs.e* +*.pbs.o* # output files log -log/* -*/log -*/log/* tracks -tracks/* -*/tracks -*/tracks/* plots -plots/* -*/plots -*/plots/* -pin-powers -pin-powers/* -*/pin-powers -*/pin-powers/* -simulation-state* -simulation-state/* -*/simulation-state* -*/simulation-state*/* - +fission-rates +simulation-states *.data -*/*.data *.png -*/*.png - +*.ppm openmoc-*-.log -*/openmoc-*-.log -penmp +Openmp */penmp penmoc penmp-report */penmoc */penmp-report -*.egg-info/* -*/*.egg-info/ - -openmoc/intel/single/openmoc_intel_single.py -openmoc/intel/single/openmoc_intel_single_wrap.cpp -openmoc/intel/double/openmoc_intel_double.py -openmoc/intel/double/openmoc_intel_double_wrap.cpp - -openmoc/gnu/single/openmoc_gnu_single.py -openmoc/gnu/single/openmoc_gnu_single_wrap.cpp -openmoc/gnu/double/openmoc_gnu_double.py -openmoc/gnu/doube/openmoc_gnu_double_wrap.cpp - -openmoc/cuda/openmoc_cuda.py -openmoc/cuda/openmoc_cuda_wrap.cpp -openmoc/cuda/single/openmoc_cuda_single.py -openmoc/cuda/single/openmoc_cuda_single_wrap.cpp -openmoc/cuda/double/openmoc_cuda_double.py -openmoc/cuda/double/openmoc_cuda_double_wrap.cpp - +*/*.egg-info/* #Documentation +sphinx/ docs/build docs/build/* docs/doxygen/xml docs/doxyge/xml/* -# BGQ -*.lst - -*.cobaltlog -*/*.cobaltlog -*.error -*/*.error -*.output -*/*.output - -*core* -*/core* - build/* -*/build/ */build/* -.idea* +# PyCharm configuration files .idea/* -.idea/*.xml - -sphinx/ *.DS_Store */*.DS_Store @@ -141,3 +59,34 @@ sphinx/ # *~ *.swp +# C++ Build +profile/obj/* +profile/models/c5g7/c5g7-cmfd +profile/models/c5g7/c5g7-cmfd.o +profile/models/c5g7/c5g7 +profile/models/c5g7/c5g7.o +profile/models/gradients/one-directional/one-directional-gradient +profile/models/gradients/one-directional/one-directional-gradient.o +profile/models/gradients/two-directional/two-directional-gradient +profile/models/gradients/two-directional/two-directional-gradient.o +profile/models/homogeneous/homogeneous-one-group +profile/models/homogeneous/homogeneous-one-group.o + +# IPython Notebook +.ipynb_checkpoints/ + +# OpenMC input/output files +*.xml +statepoint* +summary* + +# Test results error file +results_error.dat +results_test.dat + +# Test build files +openmoc/ +*.log + +# Doxygen +docs/doxygen/html/* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..fd8f19ae4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +language: python +python: + - "2.7" + - "3.4" +addons: + apt: + packages: + - swig +cache: + directories: + +before_install: + # ========== Point apt-get to C++11-compatible compiler ========== + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + - sudo apt-get update -qq + # ============== Handle Python third-party packages ============== + - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then + wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; + else + wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; + fi + - bash miniconda.sh -b -p $HOME/miniconda + - export PATH="$HOME/miniconda/bin:$PATH" + - hash -r + - conda config --set always_yes yes --set changeps1 no + - conda update -q conda + - conda info -a + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py pandas matplotlib pillow + - source activate test-environment + +install: + # ================= Get C++11-compatible compiler ================== + - sudo apt-get install -qq gcc-4.8 g++-4.8 + - sudo apt-get install swig + - sudo rm /usr/bin/gcc + - sudo rm /usr/bin/g++ + - sudo ln -s /usr/bin/gcc-4.8 /usr/bin/gcc + - sudo ln -s /usr/bin/g++-4.8 /usr/bin/g++ + +script: + - cd tests + - ./travis.sh + - cd .. \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..9f945e2ab --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.8) + +#=============================================================================== +# Regression tests +#=============================================================================== + +# This allows for dashboard configuration +include(CTest) + +# Get a list of all the tests to run +file(GLOB_RECURSE TESTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_*.py) + +# Loop through all the tests +foreach(test ${TESTS}) + + # Get test information + get_filename_component(TEST_NAME ${test} NAME) + get_filename_component(TEST_PATH ${test} PATH) + + add_test(NAME ${TEST_NAME} + WORKING_DIRECTORY ${TEST_PATH} + COMMAND ${PYTHON_EXECUTABLE} ${TEST_NAME} + ) + +endforeach(test) diff --git a/README.rst b/README.rst index 91a7ddfa0..1c0db57d2 100644 --- a/README.rst +++ b/README.rst @@ -1,38 +1,65 @@ -================================================================= -OpenMOC Method of Characteristics Neutral Particle Transport Code -================================================================= - -Welcome to the OpenMOC repository! OpenMOC is a simulation tool for -solving for the flux, power distribution, and multiplication factor -within a nuclear reactor. The code employs the deterministic method -of characteristics using source iteration. The OpenMOC project aims -to provide a simple-to-use Python package bound to a back-end of source -code written in C/C++ and CUDA. It includes support for constructive -solid geometry and 2D ray tracing for fully heterogeneous multi-group -calculations. Development of OpenMOC began at MIT in 2012 and is -spearheaded by several graduate students in the +======= +OpenMOC +======= + +.. image:: https://api.travis-ci.org/mit-crpg/OpenMOC.svg?branch=develop + :target: https://travis-ci.org/mit-crpg/OpenMOC +.. image:: https://img.shields.io/badge/powered%20by-OpenMOC-blue.svg + :target: https://mit-crpg.github.io/OpenMOC/ +.. image:: https://img.shields.io/badge/license-MIT%20License-brightgreen.svg + :target: https://mit-crpg.github.io/OpenMOC/license.html +.. image:: https://img.shields.io/badge/anucene-Elsevier-lightgray.svg + :target: http://www.sciencedirect.com/science/article/pii/S0306454913006634 + +Welcome to the OpenMOC repository! OpenMOC is a simulation tool for +solving for the flux, power distribution, and multiplication factor +within a nuclear reactor. The code employs the deterministic method +of characteristics, with support for both fixed source and eigenvalue +calculations. The OpenMOC project aims to provide a simple-to-use +Python package bound to a back-end of source code written in C/C++ +and CUDA. It includes support for constructive solid geometry and 2D +ray tracing for fully heterogeneous multi-group calculations. +Development of OpenMOC began at MIT in 2012 and is spearheaded by +several graduate students in the `Nuclear Science & Engineering Department`_. -Complete documentation on the usage of OpenMOC is hosted at -https://mit-crpg.github.io/OpenMOC/. If you would like to -contribute to the OpenMOC project, please `contact`_ the +Complete documentation on OpenMOC is hosted at +https://mit-crpg.github.io/OpenMOC/. If you would like to +contribute to the OpenMOC project, please `contact`_ the development team. +For a guided example, see a demonstration `IPython Notebook`_. + ------------ Installation ------------ -Detailed `installation instructions`_ can be found in the +Detailed `installation instructions`_ can be found in the User's Guide. --------------- Troubleshooting --------------- -If you run into problems installing or running OpenMOC, -first review the `FAQ`_ in the User's Guide. If you are -unable to find a solution to your problem there, please -`contact`_ one of the developers. +Join the OpenMOC `users group`_ to ask questions and discuss +methods and simulation workflows. + +-------------- +Citing OpenMOC +-------------- + +Please cite OpenMOC in your publications if it helps your research: + +.. code-block:: latex + + @article{openmoc2014, + author = {Boyd, William and Shaner, Samuel and Li, Lulu and Forget, Benoit and Smith, Kord}, + journal = {Annals of Nuclear Energy}, + title = {The OpenMOC Method of Characteristics Neutral Particle Transport Code}, + volume = {68}, + pages = {43--52}, + year = {2014} + } ------- License @@ -41,7 +68,8 @@ License OpenMOC is approved for distribution under the MIT/X license_. .. _installation instructions: https://mit-crpg.github.io/OpenMOC/usersguide/install.html -.. _FAQ: https://mit-crpg.github.io/OpenMOC/FAQ .. _license: https://mit-crpg.github.io/OpenMOC/license.html -.. _contact: https://mit-crpg.github.io/OpenMOC/developers.html .. _Nuclear Science & Engineering Department: http://web.mit.edu/nse/ +.. _IPython Notebook: https://gist.github.com/wbinventor/8c5d2ffbb86f11735610 +.. _contact: https://mit-crpg.github.io/OpenMOC/developers.html +.. _users group: https://groups.google.com/forum/#!forum/openmoc-users diff --git a/config.py b/config.py index 7561fb309..9ab675565 100644 --- a/config.py +++ b/config.py @@ -53,18 +53,11 @@ class configuration: # User Options ############################################################################# - # Only supports GCC as the default compiler right now ?????? # Default C++ compiler for the main openmoc module is GCC cc = 'gcc' # Default floating point for the main openmoc module is single precision - fp = 'double' - - # Supported C++ compilers: 'gcc', 'icpc', 'bgxlc', 'nvcc', 'all' - cpp_compilers = list() - - # Supported floating point precision levels: 'single', 'double', 'all' - fp_precision = list() + fp = 'single' # Compile using ccache (for developers needing fast recompilation) with_ccache = False @@ -75,17 +68,9 @@ class configuration: # Compile code with debug symbols (ie, -g, -pg) profile_mode = False - # Build the openmoc.cuda and/or openmoc.cuda/single and/or openmoc.cuda.double - # modules (depending on what precision levels are set for fp_precision) + # Build the openmoc.cuda module with_cuda = False - # Compile with PAPI instrumentation - with_papi = False - - # Compile with NumPy typemaps and the C API to allow users to pass NumPy - # arrays to/from the C++ source code - with_numpy = True - # The vector length used for the VectorizedSolver class. This will used # as a hint for the Intel compiler to issue SIMD (ie, SSE, AVX, etc) vector # instructions. This is accomplished by adding "dummy" energy groups such @@ -102,15 +87,8 @@ class configuration: # on which flags are specified at compile time. extensions = list() - # List of the packages to install - only openmoc is guaranteed to be built - # while the others will be built based on which flags are specified - # at compile time - packages = ['openmoc', 'openmoc.compatible', 'openmoc.intel', 'openmoc.gnu', - 'openmoc.bgq', 'openmoc.cuda', 'openmoc.intel.double', - 'openmoc.intel.single', 'openmoc.gnu.double', - 'openmoc.gnu.single', 'openmoc.bgq.single', - 'openmoc.bgq.double', 'openmoc.cuda.double', - 'openmoc.cuda.single'] + # List of the possible packages to install based on runtime options + packages = ['openmoc', 'openmoc.cuda'] ############################################################################# @@ -127,7 +105,8 @@ class configuration: 'src/log.cpp', 'src/Material.cpp', 'src/Point.cpp', - 'src/Quadrature.cpp', + 'src/PolarQuad.cpp', + 'src/ExpEvaluator.cpp', 'src/Solver.cpp', 'src/CPUSolver.cpp', 'src/Surface.cpp', @@ -135,7 +114,32 @@ class configuration: 'src/Track.cpp', 'src/TrackGenerator.cpp', 'src/Universe.cpp', - 'src/Cmfd.cpp'] + 'src/Vector.cpp', + 'src/Matrix.cpp', + 'src/Cmfd.cpp', + 'src/linalg.cpp'] + + sources['clang'] = ['openmoc/openmoc_wrap.cpp', + 'src/Cell.cpp', + 'src/Geometry.cpp', + 'src/LocalCoords.cpp', + 'src/log.cpp', + 'src/Material.cpp', + 'src/Point.cpp', + 'src/PolarQuad.cpp', + 'src/ExpEvaluator.cpp', + 'src/Solver.cpp', + 'src/CPUSolver.cpp', + 'src/Surface.cpp', + 'src/Timer.cpp', + 'src/Track.cpp', + 'src/TrackGenerator.cpp', + 'src/Universe.cpp', + 'src/Cmfd.cpp', + 'src/Vector.cpp', + 'src/Matrix.cpp', + 'src/linalg.cpp'] + sources['icpc'] = ['openmoc/openmoc_wrap.cpp', 'src/Cell.cpp', @@ -144,7 +148,8 @@ class configuration: 'src/log.cpp', 'src/Material.cpp', 'src/Point.cpp', - 'src/Quadrature.cpp', + 'src/PolarQuad.cpp', + 'src/ExpEvaluator.cpp', 'src/Solver.cpp', 'src/CPUSolver.cpp', 'src/VectorizedSolver.cpp', @@ -153,7 +158,11 @@ class configuration: 'src/Track.cpp', 'src/TrackGenerator.cpp', 'src/Universe.cpp', - 'src/Cmfd.cpp'] + 'src/Cmfd.cpp', + 'src/Vector.cpp', + 'src/Matrix.cpp', + 'src/linalg.cpp'] + sources['bgxlc'] = ['openmoc/openmoc_wrap.cpp', 'src/Cell.cpp', @@ -162,7 +171,8 @@ class configuration: 'src/log.cpp', 'src/Material.cpp', 'src/Point.cpp', - 'src/Quadrature.cpp', + 'src/PolarQuad.cpp', + 'src/ExpEvaluator.cpp', 'src/Solver.cpp', 'src/CPUSolver.cpp', 'src/Surface.cpp', @@ -170,9 +180,14 @@ class configuration: 'src/Track.cpp', 'src/TrackGenerator.cpp', 'src/Universe.cpp', - 'src/Cmfd.cpp'] + 'src/Cmfd.cpp', + 'src/Vector.cpp', + 'src/Matrix.cpp', + 'src/linalg.cpp'] + sources['nvcc'] = ['openmoc/cuda/openmoc_cuda_wrap.cpp', + 'src/accel/cuda/GPUExpEvaluator.cu', 'src/accel/cuda/GPUQuery.cu', 'src/accel/cuda/clone.cu', 'src/accel/cuda/GPUSolver.cu'] @@ -186,16 +201,23 @@ class configuration: compiler_flags = dict() compiler_flags['gcc'] = ['-c', '-O3', '-ffast-math', '-fopenmp', - '-std=c++0x', '-fpic'] - compiler_flags['icpc'] =['-c', '-O3', '-fast', '--ccache-skip', '-openmp', - '-xhost', '-std=c++0x', '-fpic', '--ccache-skip', - '-openmp-report', '-vec-report'] + '-std=c++11', '-fpic'] + compiler_flags['clang'] = ['-c', '-O3', '-ffast-math', '-std=c++11', + '-fopenmp', '-fvectorize', '-fpic', + '-Qunused-arguments', + '-Wno-deprecated-register', + '-Wno-parentheses-equality'] + compiler_flags['icpc'] =['-c', '-O3', '-fast', '--ccache-skip', + '-openmp', '-xhost', '-std=c++11', + '--ccache-skip', '-fpic', + '-openmp-report', '-vec-report'] compiler_flags['bgxlc'] = ['-c', '-O2', '-qarch=qp', '-qreport', '-qsimd=auto', '-qtune=qp', '-qunroll=auto', '-qsmp=omp', '-qpic'] - compiler_flags['nvcc'] = ['-c', '-O3', '--compiler-options', '-fpic', - '-gencode=arch=compute_20,code=sm_20', - '-gencode=arch=compute_30,code=sm_30'] + compiler_flags['nvcc'] = ['--relocatable-device-code', 'true', + '-c', '-O3', '-std=c++11', + '--compiler-options', '-fpic', + '-arch=compute_20'] ############################################################################# @@ -205,13 +227,20 @@ class configuration: # A dictionary of the linker flags to use for each compiler type linker_flags = dict() - if (get_platform()[:6] == 'macosx'): + if ('macosx' in get_platform()): linker_flags['gcc'] = ['-fopenmp', '-dynamiclib', '-lpython2.7', '-Wl,-install_name,' + get_openmoc_object_name()] else: linker_flags['gcc'] = ['-fopenmp', '-shared', '-Wl,-soname,' + get_openmoc_object_name()] + if ('macosx' in get_platform()): + linker_flags['clang'] = ['-fopenmp', '-dynamiclib', '-lpython2.7', + '-Wl,-install_name,' + get_openmoc_object_name()] + else: + linker_flags['clang'] = ['-fopenmp', '-shared', + '-Wl,-soname,' + get_openmoc_object_name()] + linker_flags['icpc'] = [ '-openmp', '-shared', '-Xlinker', '-soname=' + get_openmoc_object_name()] linker_flags['bgxlc'] = ['-qmkshrobj', '-shared', @@ -228,10 +257,11 @@ class configuration: shared_libraries = dict() shared_libraries['gcc'] = ['stdc++', 'gomp', 'dl','pthread', 'm'] + shared_libraries['clang'] = ['stdc++', 'gomp', 'dl','pthread', 'm'] shared_libraries['icpc'] = ['stdc++', 'iomp5', 'pthread', 'irc', 'imf','rt', 'mkl_rt','m',] shared_libraries['bgxlc'] = ['stdc++', 'pthread', 'm', 'xlsmp', 'rt'] - shared_libraries['nvcc'] = ['cudart'] + shared_libraries['nvcc'] = ['cudadevrt', 'cudart'] ############################################################################# @@ -245,9 +275,10 @@ class configuration: usr_lib = sys.exec_prefix + '/lib' library_directories['gcc'] = [usr_lib] + library_directories['clang'] = [usr_lib] library_directories['icpc'] = [usr_lib] library_directories['bgxlc'] = [usr_lib] - library_directories['nvcc'] = [usr_lib, '/usr/local/cuda-5.5/lib64'] + library_directories['nvcc'] = [usr_lib, '/usr/local/cuda/lib64'] ############################################################################# @@ -259,9 +290,10 @@ class configuration: include_directories = dict() include_directories['gcc'] = list() + include_directories['clang'] = list() include_directories['icpc'] = list() include_directories['bgxlc'] = list() - include_directories['nvcc'] = ['/usr/local/cuda-5.5/include'] + include_directories['nvcc'] = ['/usr/local/cuda/include'] ########################################################################### @@ -285,19 +317,26 @@ class configuration: macros = dict() macros['gcc'] = dict() + macros['clang'] = dict() macros['icpc'] = dict() macros['bgxlc'] = dict() macros['nvcc'] = dict() macros['gcc']['single']= [('FP_PRECISION', 'float'), ('SINGLE', None), - ('GNU', None), + ('GCC', None), ('VEC_LENGTH', vector_length), ('VEC_ALIGNMENT', vector_alignment)] + macros['clang']['single']= [('FP_PRECISION', 'float'), + ('SINGLE', None), + ('CLANG', None), + ('VEC_LENGTH', vector_length), + ('VEC_ALIGNMENT', vector_alignment)] + macros['icpc']['single']= [('FP_PRECISION', 'float'), ('SINGLE', None), - ('INTEL', None), + ('ICPC', None), ('MKL_ILP64', None), ('VEC_LENGTH', vector_length), ('VEC_ALIGNMENT', vector_alignment)] @@ -311,18 +350,24 @@ class configuration: macros['nvcc']['single'] = [('FP_PRECISION', 'float'), ('SINGLE', None), - ('CUDA', None), + ('NVCC', None), ('CCACHE_CC', 'nvcc')] macros['gcc']['double'] = [('FP_PRECISION', 'double'), ('DOUBLE', None), - ('GNU', None), + ('GCC', None), ('VEC_LENGTH', vector_length), ('VEC_ALIGNMENT', vector_alignment)] + macros['clang']['double'] = [('FP_PRECISION', 'double'), + ('DOUBLE', None), + ('CLANG', None), + ('VEC_LENGTH', vector_length), + ('VEC_ALIGNMENT', vector_alignment)] + macros['icpc']['double'] = [('FP_PRECISION', 'double'), ('DOUBLE', None), - ('INTEL', None), + ('ICPC', None), ('MKL_ILP64', None), ('VEC_LENGTH', vector_length), ('VEC_ALIGNMENT', vector_alignment)] @@ -336,9 +381,14 @@ class configuration: macros['nvcc']['double'] = [('FP_PRECISION', 'double'), ('DOUBLE', None), - ('CUDA', None), + ('NVCC', None), ('CCACHE_CC', 'nvcc')] + # define OPENMP and SWIG (for log output) + for compiler in macros: + for precision in macros[compiler]: + macros[compiler][precision].append(('OPENMP', None)) + macros[compiler][precision].append(('SWIG', None)) def setup_extension_modules(self): @@ -348,14 +398,6 @@ def setup_extension_modules(self): Python package based on the user-defined flags defined at compile time. """ - # If the user selected 'all' compilers, enumerate them - if self.cpp_compilers == ['all']: - self.cpp_compilers = ['gcc', 'icpc', 'nvcc'] - - # If the user selected 'all' FP precision levels, enumerate them - if self.fp_precision == ['all']: - self.fp_precision = ['double', 'single'] - # If the user wishes to compile using debug mode, append the debugging # flag to all lists of compiler flags for all distribution types if self.debug_mode: @@ -369,26 +411,25 @@ def setup_extension_modules(self): self.compiler_flags[k].append('-pg') self.compiler_flags[k].append('-g') - # If the user passed in the --no-numpy flag, tell SWIG not to embed - # NumPy typemaps in the source code - if not self.with_numpy: - self.swig_flags.append('-DNO_NUMPY') - - # Otherwise, obtain the NumPy include directory - else: - try: - numpy_include = numpy.get_include() - - except AttributeError: - numpy_include = numpy.get_numpy_include() + # Obtain the NumPy include directory + try: + numpy_include = numpy.get_include() + except AttributeError: + numpy_include = numpy.get_numpy_include() - # Add the NumPy include directory to the include directories - # list for each type of compiler - for cc in self.include_directories.keys(): - self.include_directories[cc].append(numpy_include) + # Add the NumPy include directory to the include directories + # list for each type of compiler + for cc in self.include_directories.keys(): + self.include_directories[cc].append(numpy_include) # The main openmoc extension (defaults are gcc and single precision) + self.swig_flags += ['-D' + self.fp.upper()] + if self.fp == 'double': + self.swig_flags += ['-DFP_PRECISION=double'] + else: + self.swig_flags += ['-DFP_PRECISION=float'] + self.extensions.append( Extension(name = '_openmoc', sources = copy.deepcopy(self.sources[self.cc]), @@ -403,8 +444,6 @@ def setup_extension_modules(self): # time (--with-cuda) if self.with_cuda: - self.cpp_compilers.append('nvcc') - self.extensions.append( Extension(name = '_openmoc_cuda', sources = copy.deepcopy(self.sources['nvcc']), @@ -415,65 +454,3 @@ def setup_extension_modules(self): define_macros = self.macros['nvcc'][self.fp], swig_opts = self.swig_flags + ['-DNVCC'], export_symbols = ['init_openmoc'])) - - # Remove the main SWIG configuration file for builds of other - # extensions (ie, openmoc.cuda.single, openmoc.cuda.double) - self.sources['nvcc'].remove('openmoc/cuda/openmoc_cuda_wrap.cpp') - - # Loop over the compilers and floating point precision levels to create - # extension modules for each (ie, openmoc.intel.double, - # openmoc.cuda.single, etc) - for fp in self.fp_precision: - for cc in self.cpp_compilers: - - # Build the filename for the SWIG configuration file and the - # extension name depending on the compiler and floating - # point precision - - # For openmoc.cuda.* modules - if cc == 'nvcc': - ext_name = '_openmoc_cuda_' + fp - swig_wrap_file = 'openmoc/cuda/' + fp - swig_wrap_file += '/openmoc_cuda_' + fp + '_wrap.cpp' - self.sources['nvcc'].append(swig_wrap_file) - - # For openmoc.gnu.* modules - elif cc == 'gcc': - ext_name = '_openmoc_gnu_' + fp - swig_wrap_file = 'openmoc/gnu/' + fp - swig_wrap_file += '/openmoc_gnu_' + fp + '_wrap.cpp' - self.sources['gcc'].append(swig_wrap_file) - - # For openmoc.intel.* modules - elif cc == 'icpc': - ext_name = '_openmoc_intel_' + fp - swig_wrap_file = 'openmoc/intel/' + fp - swig_wrap_file += '/openmoc_intel_' + fp + '_wrap.cpp' - self.sources['icpc'].append(swig_wrap_file) - - # For openmoc.intel.* modules - elif cc == 'bgxlc': - ext_name = '_openmoc_bgq_' + fp - swig_wrap_file = 'openmoc/bgq/' + fp - swig_wrap_file += '/openmoc_bgq_' + fp + '_wrap.cpp' - self.sources['bgxlc'].append(swig_wrap_file) - - # If an unsupported compiler, throw error - else: - raise NameError('Compiler ' + str(cc) + ' is not supported') - - # Create the extension module and append it to the list of all - # extension modules - self.extensions.append( - Extension(name = ext_name, - sources = copy.deepcopy(self.sources[cc]), - library_dirs = self.library_directories[cc], - libraries = self.shared_libraries[cc], - extra_link_args = self.linker_flags[cc], - include_dirs = self.include_directories[cc], - define_macros = self.macros[cc][fp], - swig_opts = self.swig_flags + ['-D' + cc.upper()])) - - # Clean up - remove the SWIG-generated wrap file from this - # extension for the next extension - self.sources[cc].remove(swig_wrap_file) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..8909256f3 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,131 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + sed -i -e 's/div.body/div.content/' $(BUILDDIR)/html/_static/basic.css + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyne.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyne.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/pyne" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyne" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile new file mode 100644 index 000000000..3afc04ce1 --- /dev/null +++ b/docs/doxygen/Doxyfile @@ -0,0 +1,1792 @@ +# Doxyfile 1.8.1.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "An open source method of characteristics neutron transport code." + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = ../img/openmoc-logo-api.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../../src/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cu *.cpp *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = ../doxygen/html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = no + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES \ No newline at end of file diff --git a/docs/doxygen/doxy2swig.py b/docs/doxygen/doxy2swig.py new file mode 100755 index 000000000..e4c8a6169 --- /dev/null +++ b/docs/doxygen/doxy2swig.py @@ -0,0 +1,778 @@ +#!/usr/bin/env python +"""doxy2swig.py [options] index.xml output.i + +Doxygen XML to SWIG docstring converter (improved version). + +Converts Doxygen generated XML files into a file containing docstrings +for use by SWIG. + +index.xml is your doxygen generated XML file and output.i is where the +output will be written (the file will be clobbered). +""" +# +# The current version of this code is hosted on a github repository: +# https://github.com/m7thon/doxy2swig +# +# This code is implemented using Mark Pilgrim's code as a guideline: +# http://www.faqs.org/docs/diveintopython/kgp_divein.html +# +# Original Author: Prabhu Ramachandran +# Modified by: Michael Thon (June 2015) +# License: BSD style +# +# Thanks: +# Johan Hake: the include_function_definition feature +# Bill Spotz: bug reports and testing. +# Sebastian Henschel: Misc. enhancements. +# +# Changes: +# June 2015 (Michael Thon): +# - class documentation: +# -c: add constructor call signatures and a "Constructors" section +# collecting the respective docs (e.g. for python) +# -a: add "Attributes" section collecting the documentation for member +# variables (e.g. for python) +# - overloaded functions: +# -o: collect all documentation into one "Overloaded function" section +# - option to include function definition / signature renamed to -f +# - formatting: +# + included function signatures slightly reformatted +# + option (-t) to turn off/on type information for funciton signatures +# + lists (incl. nested and ordered) +# + attempt to produce docstrings that render nicely as markdown +# + translate code, emphasis, bold, linebreak, hruler, blockquote, +# verbatim, heading tags to markdown +# + new text-wrapping and option -w to specify the text width +# + +from xml.dom import minidom +import re +import textwrap +import sys +import os.path + + +def my_open_read(source): + if hasattr(source, "read"): + return source + else: + try: + return open(source, encoding='utf-8') + except TypeError: + return open(source) + +def my_open_write(dest): + if hasattr(dest, "write"): + return dest + else: + try: + return open(dest, 'w', encoding='utf-8') + except TypeError: + return open(dest, 'w') + +# MARK: Text handling: +def shift(txt, indent = ' ', prepend = ''): + """Return a list corresponding to the lines of text in the `txt` list + indented by `indent`. Prepend instead the string given in `prepend` to the + beginning of the first line. Note that if len(prepend) > len(indent), then + `prepend` will be truncated (doing better is tricky!). This preserves a + special '' entry at the end of `txt` (see `do_para` for the meaning). + """ + if type(indent) is int: + indent = indent * ' ' + special_end = txt[-1:] == [''] + lines = ''.join(txt).splitlines(True) + for i in range(1,len(lines)): + if lines[i].strip() or indent.strip(): + lines[i] = indent + lines[i] + if not lines: + return prepend + prepend = prepend[:len(indent)] + indent = indent[len(prepend):] + lines[0] = prepend + indent + lines[0] + ret = [''.join(lines)] + if special_end: + ret.append('') + return ret + +class Doxy2SWIG: + """Converts Doxygen generated XML files into a file containing + docstrings that can be used by SWIG-1.3.x that have support for + feature("docstring"). Once the data is parsed it is stored in + self.pieces. + + """ + + def __init__(self, src): + """Initialize the instance given a source object. `src` can + be a file or filename. If you do not want to include function + definitions from doxygen then set + `include_function_definition` to `False`. This is handy since + this allows you to use the swig generated function definition + using %feature("autodoc", [0,1]). + + """ + + # options: + self.with_function_signature = True + self.with_type_info = True + self.with_constructor_list = False + self.with_attribute_list = True + self.with_overloaded_functions = True + self.textwidth = 90 + self.quiet = False + + # state: + self.indent = 0 + self.listitem = '' + self.pieces = [] + + f = my_open_read(src) + self.my_dir = os.path.dirname(f.name) + self.xmldoc = minidom.parse(f).documentElement + f.close() + + self.pieces.append('\n// File: %s\n' % + os.path.basename(f.name)) + + self.space_re = re.compile(r'\s+') + self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') + self.multi = 0 + self.ignores = ['inheritancegraph', 'param', 'listofallmembers', + 'innerclass', 'name', 'declname', 'incdepgraph', + 'invincdepgraph', 'programlisting', 'type', + 'references', 'referencedby', 'location', + 'collaborationgraph', 'reimplements', + 'reimplementedby', 'derivedcompoundref', + 'basecompoundref', + 'argsstring', 'definition', 'exceptions'] + #self.generics = [] + + def generate(self): + """Parses the file set in the initialization. The resulting + data is stored in `self.pieces`. + + """ + self.parse(self.xmldoc) + + def write(self, fname): + o = my_open_write(fname) + o.write(''.join(self.pieces)) + o.write('\n') + o.close() + + def parse(self, node): + """Parse a given node. This function in turn calls the + `parse_` functions which handle the respective + nodes. + + """ + pm = getattr(self, "parse_%s" % node.__class__.__name__) + pm(node) + + def parse_Document(self, node): + self.parse(node.documentElement) + + def parse_Text(self, node): + txt = node.data + if txt == ' ': + # this can happen when two tags follow in a text, e.g., + # " ... $..." etc. + # here we want to keep the space. + self.add_text(txt) + return + txt = txt.replace('\\', r'\\') + txt = txt.replace('"', r'\"') + # ignore pure whitespace + m = self.space_re.match(txt) + if m and len(m.group()) == len(txt): + pass + else: + self.add_text(txt) + + def parse_Comment(self, node): + """Parse a `COMMENT_NODE`. This does nothing for now.""" + return + + def parse_Element(self, node): + """Parse an `ELEMENT_NODE`. This calls specific + `do_` handers for different elements. If no handler + is available the `subnode_parse` method is called. All + tagNames specified in `self.ignores` are simply ignored. + + """ + name = node.tagName + ignores = self.ignores + if name in ignores: + return + attr = "do_%s" % name + if hasattr(self, attr): + handlerMethod = getattr(self, attr) + handlerMethod(node) + else: + self.subnode_parse(node) + #if name not in self.generics: self.generics.append(name) + +# MARK: Special format parsing + def subnode_parse(self, node, pieces=None, indent=0, ignore=[], restrict=None): + """Parse the subnodes of a given node. Subnodes with tags in the + `ignore` list are ignored. If pieces is given, use this as target for + the parse results instead of self.pieces. Indent all lines by the amount + given in `indent`. Note that the initial content in `pieces` is not + indented. The final result is in any case added to self.pieces.""" + if pieces is not None: + old_pieces, self.pieces = self.pieces, pieces + else: + old_pieces = [] + if type(indent) is int: + indent = indent * ' ' + if len(indent) > 0: + pieces = ''.join(self.pieces) + i_piece = pieces[:len(indent)] + if self.pieces[-1:] == ['']: + self.pieces = [pieces[len(indent):]] + [''] + elif self.pieces != []: + self.pieces = [pieces[len(indent):]] + self.indent += len(indent) + for n in node.childNodes: + if restrict is not None: + if n.nodeType == n.ELEMENT_NODE and n.tagName in restrict: + self.parse(n) + elif n.nodeType != n.ELEMENT_NODE or n.tagName not in ignore: + self.parse(n) + if len(indent) > 0: + self.pieces = shift(self.pieces, indent, i_piece) + self.indent -= len(indent) + old_pieces.extend(self.pieces) + self.pieces = old_pieces + + def surround_parse(self, node, pre_char, post_char): + """Parse the subnodes of a given node. Subnodes with tags in the + `ignore` list are ignored. Prepend `pre_char` and append `post_char` to + the output in self.pieces.""" + self.add_text(pre_char) + self.subnode_parse(node) + self.add_text(post_char) + +# MARK: Helper functions + def get_specific_subnodes(self, node, name, recursive=0): + """Given a node and a name, return a list of child `ELEMENT_NODEs`, that + have a `tagName` matching the `name`. Search recursively for `recursive` + levels. + """ + children = [x for x in node.childNodes if x.nodeType == x.ELEMENT_NODE] + ret = [x for x in children if x.tagName == name] + if recursive > 0: + for x in children: + ret.extend(self.get_specific_subnodes(x, name, recursive-1)) + return ret + + def get_specific_nodes(self, node, names): + """Given a node and a sequence of strings in `names`, return a + dictionary containing the names as keys and child + `ELEMENT_NODEs`, that have a `tagName` equal to the name. + + """ + nodes = [(x.tagName, x) for x in node.childNodes + if x.nodeType == x.ELEMENT_NODE and + x.tagName in names] + return dict(nodes) + + def add_text(self, value): + """Adds text corresponding to `value` into `self.pieces`.""" + if isinstance(value, (list, tuple)): + self.pieces.extend(value) + else: + self.pieces.append(value) + + def start_new_paragraph(self): + """Make sure to create an empty line. This is overridden, if the previous + text ends with the special marker ''. In that case, nothing is done. + """ + if self.pieces[-1:] == ['']: # respect special marker + return + elif self.pieces == []: # first paragraph, add '\n', override with '' + self.pieces = ['\n'] + elif self.pieces[-1][-1:] != '\n': # previous line not ended + self.pieces.extend([' \n' ,'\n']) + else: #default + self.pieces.append('\n') + + def add_line_with_subsequent_indent(self, line, indent=4): + """Add line of text and wrap such that subsequent lines are indented + by `indent` spaces. + """ + if isinstance(line, (list, tuple)): + line = ''.join(line) + line = line.strip() + width = self.textwidth-self.indent-indent + wrapped_lines = textwrap.wrap(line[indent:], width=width) + for i in range(len(wrapped_lines)): + if wrapped_lines[i] != '': + wrapped_lines[i] = indent * ' ' + wrapped_lines[i] + self.pieces.append(line[:indent] + '\n'.join(wrapped_lines)[indent:] + ' \n') + + def extract_text(self, node): + """Return the string representation of the node or list of nodes by parsing the + subnodes, but returning the result as a string instead of adding it to `self.pieces`. + Note that this allows extracting text even if the node is in the ignore list. + """ + if not isinstance(node, (list, tuple)): + node = [node] + pieces, self.pieces = self.pieces, [''] + for n in node: + for sn in n.childNodes: + self.parse(sn) + ret = ''.join(self.pieces) + self.pieces = pieces + return ret + + def get_function_signature(self, node): + """Returns the function signature string for memberdef nodes.""" + name = self.extract_text(self.get_specific_subnodes(node, 'name')) + if self.with_type_info: + argsstring = self.extract_text(self.get_specific_subnodes(node, 'argsstring')) + else: + argsstring = [] + param_id = 1 + for n_param in self.get_specific_subnodes(node, 'param'): + declname = self.extract_text(self.get_specific_subnodes(n_param, 'declname')) + if not declname: + declname = 'arg' + str(param_id) + defval = self.extract_text(self.get_specific_subnodes(n_param, 'defval')) + if defval: + defval = '=' + defval + argsstring.append(declname + defval) + param_id = param_id + 1 + argsstring = '(' + ', '.join(argsstring) + ')' + type = self.extract_text(self.get_specific_subnodes(node, 'type')) + function_definition = name + argsstring + if type != '' and type != 'void': + function_definition = function_definition + ' -> ' + type + return function_definition + ' ' + +# MARK: Special parsing tasks (need to be called manually) + def make_constructor_list(self, constructor_nodes, classname): + """Produces the "Constructors" section and the constructor signatures + (since swig does not do so for classes) for class docstrings.""" + if constructor_nodes == []: + return + self.add_text(['\n', 'Constructors', + '\n', '------------']) + for n in constructor_nodes: + self.add_text('\n') + self.add_line_with_subsequent_indent('* ' + self.get_function_signature(n)) + self.subnode_parse(n, pieces = [], indent=4, ignore=['definition', 'name']) + + def make_attribute_list(self, node): + """Produces the "Attributes" section in class docstrings for public + member variables (attributes). + """ + atr_nodes = [] + for n in self.get_specific_subnodes(node, 'memberdef', recursive=2): + if n.attributes['kind'].value == 'variable' and n.attributes['prot'].value == 'public': + atr_nodes.append(n) + if not atr_nodes: + return + self.add_text(['\n', 'Attributes', + '\n', '----------']) + for n in atr_nodes: + name = self.extract_text(self.get_specific_subnodes(n, 'name')) + self.add_text(['\n* ', name,' : ']) + self.add_text([self.extract_text(self.get_specific_subnodes(n, 'type'))]) + self.add_text(' \n') + restrict = ['briefdescription', 'detaileddescription'] + self.subnode_parse(n, pieces=[''], indent=4, restrict=restrict) + + def get_memberdef_nodes_and_signatures(self, node, kind): + """Collects the memberdef nodes and corresponding signatures that + correspond to public function entries that are at most depth 2 deeper + than the current (compounddef) node. Returns a dictionary with + function signatures (what swig expects after the %feature directive) + as keys, and a list of corresponding memberdef nodes as values.""" + sig_dict = {} + sig_prefix = '' + if kind in ('file', 'namespace'): + ns_node = node.getElementsByTagName('innernamespace') + if not ns_node and kind == 'namespace': + ns_node = node.getElementsByTagName('compoundname') + if ns_node: + sig_prefix = self.extract_text(ns_node[0]) + '::' + elif kind in ('class', 'struct'): + # Get the full function name. + cn_node = node.getElementsByTagName('compoundname') + sig_prefix = self.extract_text(cn_node[0]) + '::' + + md_nodes = self.get_specific_subnodes(node, 'memberdef', recursive=2) + for n in md_nodes: + if n.attributes['prot'].value != 'public': + continue + if n.attributes['kind'].value in ['variable', 'typedef']: + continue + if not self.get_specific_subnodes(n, 'definition'): + continue + name = self.extract_text(self.get_specific_subnodes(n, 'name')) + if name[:8] == 'operator': + continue + sig = sig_prefix + name + if sig in sig_dict: + sig_dict[sig].append(n) + else: + sig_dict[sig] = [n] + return sig_dict + + def handle_typical_memberdefs_no_overload(self, signature, memberdef_nodes): + """Produce standard documentation for memberdef_nodes.""" + for n in memberdef_nodes: + self.add_text(['\n', '%feature("docstring") ', signature, ' "', '\n']) + if self.with_function_signature: + self.add_line_with_subsequent_indent(self.get_function_signature(n)) + self.subnode_parse(n, pieces=[], ignore=['definition', 'name']) + self.add_text(['";', '\n']) + + def handle_typical_memberdefs(self, signature, memberdef_nodes): + """Produces docstring entries containing an "Overloaded function" + section with the documentation for each overload, if the function is + overloaded and self.with_overloaded_functions is set. Else, produce + normal documentation. + """ + if len(memberdef_nodes) == 1 or not self.with_overloaded_functions: + self.handle_typical_memberdefs_no_overload(signature, memberdef_nodes) + return + + self.add_text(['\n', '%feature("docstring") ', signature, ' "', '\n']) + if self.with_function_signature: + for n in memberdef_nodes: + self.add_line_with_subsequent_indent(self.get_function_signature(n)) + self.add_text('\n') + self.add_text(['Overloaded function', '\n', + '-------------------']) + for n in memberdef_nodes: + self.add_text('\n') + self.add_line_with_subsequent_indent('* ' + self.get_function_signature(n)) + self.subnode_parse(n, pieces=[], indent=4, ignore=['definition', 'name']) + self.add_text(['";', '\n']) + + +# MARK: Tag handlers + def do_linebreak(self, node): + self.add_text(' ') + + def do_ndash(self, node): + self.add_text('--') + + def do_mdash(self, node): + self.add_text('---') + + def do_emphasis(self, node): + self.surround_parse(node, '*', '*') + + def do_bold(self, node): + self.surround_parse(node, '**', '**') + + def do_computeroutput(self, node): + self.surround_parse(node, '', '') + + def do_heading(self, node): + self.start_new_paragraph() + pieces, self.pieces = self.pieces, [''] + level = int(node.attributes['level'].value) + self.subnode_parse(node) + if level == 1: + self.pieces.insert(0, '\n') + self.add_text(['\n', len(''.join(self.pieces).strip()) * '=']) + elif level == 2: + self.add_text(['\n', len(''.join(self.pieces).strip()) * '-']) + elif level >= 3: + self.pieces.insert(0, level * '#' + ' ') + # make following text have no gap to the heading: + pieces.extend([''.join(self.pieces) + ' \n', '']) + self.pieces = pieces + + def do_verbatim(self, node): + self.start_new_paragraph() + self.subnode_parse(node, pieces=[''], indent=4) + + def do_blockquote(self, node): + self.start_new_paragraph() + self.subnode_parse(node, pieces=[''], indent='> ') + + def do_hruler(self, node): + self.start_new_paragraph() + self.add_text('* * * * * \n') + + def do_includes(self, node): + self.add_text('\nC++ includes: ') + self.subnode_parse(node) + self.add_text('\n') + +# MARK: Para tag handler + def do_para(self, node): + """This is the only place where text wrapping is automatically performed. + Generally, this function parses the node (locally), wraps the text, and + then adds the result to self.pieces. However, it may be convenient to + allow the previous content of self.pieces to be included in the text + wrapping. For this, use the following *convention*: + If self.pieces ends with '', treat the _previous_ entry as part of the + current paragraph. Else, insert new-line and start a new paragraph + and "wrapping context". + Paragraphs always end with ' \n', but if the parsed content ends with + the special symbol '', this is passed on. + """ + if self.pieces[-1:] == ['']: + pieces, self.pieces = self.pieces[:-2], self.pieces[-2:-1] + else: + self.add_text('\n') + pieces, self.pieces = self.pieces, [''] + self.subnode_parse(node) + dont_end_paragraph = self.pieces[-1:] == [''] + # Now do the text wrapping: + width = self.textwidth - self.indent + wrapped_para = [] + for line in ''.join(self.pieces).splitlines(): + keep_markdown_newline = line[-2:] == ' ' + w_line = textwrap.wrap(line, width=width, break_long_words=False) + if w_line == []: + w_line = [''] + if keep_markdown_newline: + w_line[-1] = w_line[-1] + ' ' + for wl in w_line: + wrapped_para.append(wl + '\n') + if wrapped_para: + if wrapped_para[-1][-3:] != ' \n': + wrapped_para[-1] = wrapped_para[-1][:-1] + ' \n' + if dont_end_paragraph: + wrapped_para.append('') + pieces.extend(wrapped_para) + self.pieces = pieces + +# MARK: List tag handlers + def do_itemizedlist(self, node): + if self.listitem == '': + self.start_new_paragraph() + elif self.pieces != [] and self.pieces[-1:] != ['']: + self.add_text('\n') + listitem = self.listitem + if self.listitem in ['*', '-']: + self.listitem = '-' + else: + self.listitem = '*' + self.subnode_parse(node) + self.listitem = listitem + + def do_orderedlist(self, node): + if self.listitem == '': + self.start_new_paragraph() + elif self.pieces != [] and self.pieces[-1:] != ['']: + self.add_text('\n') + listitem = self.listitem + self.listitem = 0 + self.subnode_parse(node) + self.listitem = listitem + + def do_listitem(self, node): + try: + self.listitem = int(self.listitem) + 1 + item = str(self.listitem) + '. ' + except: + item = str(self.listitem) + ' ' + self.subnode_parse(node, item, indent=4) + +# MARK: Parameter list tag handlers + def do_parameterlist(self, node): + self.start_new_paragraph() + text = 'unknown' + for key, val in node.attributes.items(): + if key == 'kind': + if val == 'param': + text = 'Parameters' + elif val == 'exception': + text = 'Exceptions' + elif val == 'retval': + text = 'Returns' + else: + text = val + break + if self.indent == 0: + self.add_text([text, '\n', len(text) * '-', '\n']) + else: + self.add_text([text, ': \n']) + self.subnode_parse(node) + + def do_parameteritem(self, node): + self.subnode_parse(node, pieces=['* ', '']) + + def do_parameternamelist(self, node): + self.subnode_parse(node) + self.add_text([' :', ' \n']) + + def do_parametername(self, node): + if self.pieces != [] and self.pieces != ['* ', '']: + self.add_text(', ') + data = self.extract_text(node) + self.add_text([data]) + + def do_parameterdescription(self, node): + self.subnode_parse(node, pieces=[''], indent=4) + +# MARK: Section tag handler + def do_simplesect(self, node): + kind = node.attributes['kind'].value + if kind in ('date', 'rcs', 'version'): + return + self.start_new_paragraph() + if kind == 'warning': + self.subnode_parse(node, pieces=['**Warning**: ',''], indent=4) + elif kind == 'see': + self.subnode_parse(node, pieces=['See also: ',''], indent=4) + elif kind == 'return': + if self.indent == 0: + pieces = ['Returns', '\n', len('Returns') * '-', '\n', ''] + else: + pieces = ['Returns:', '\n', ''] + self.subnode_parse(node, pieces=pieces) + else: + self.subnode_parse(node, pieces=[kind + ': ',''], indent=4) + +# MARK: %feature("docstring") producing tag handlers + def do_compounddef(self, node): + """This produces %feature("docstring") entries for classes, and handles + class, namespace and file memberdef entries specially to allow for + overloaded functions. For other cases, passes parsing on to standard + handlers (which may produce unexpected results). + """ + kind = node.attributes['kind'].value + if kind in ('class', 'struct'): + prot = node.attributes['prot'].value + if prot != 'public': + return + self.add_text('\n\n') + classdefn = self.extract_text(self.get_specific_subnodes(node, 'compoundname')) + classname = classdefn.split('::')[-1] + self.add_text('%%feature("docstring") %s "\n' % classdefn) + + if self.with_constructor_list: + constructor_nodes = [] + for n in self.get_specific_subnodes(node, 'memberdef', recursive=2): + if n.attributes['prot'].value == 'public': + if self.extract_text(self.get_specific_subnodes(n, 'definition')) == classdefn + '::' + classname: + constructor_nodes.append(n) + for n in constructor_nodes: + self.add_line_with_subsequent_indent(self.get_function_signature(n)) + + names = ('briefdescription','detaileddescription') + sub_dict = self.get_specific_nodes(node, names) + for n in ('briefdescription','detaileddescription'): + if n in sub_dict: + self.parse(sub_dict[n]) + if self.with_constructor_list: + self.make_constructor_list(constructor_nodes, classname) + if self.with_attribute_list: + self.make_attribute_list(node) + + sub_list = self.get_specific_subnodes(node, 'includes') + if sub_list: + self.parse(sub_list[0]) + self.add_text(['";', '\n']) + + names = ['compoundname', 'briefdescription','detaileddescription', 'includes'] + self.subnode_parse(node, ignore = names) + + elif kind in ('file', 'namespace'): + nodes = node.getElementsByTagName('sectiondef') + for n in nodes: + self.parse(n) + + # now explicitely handle possibly overloaded member functions. + if kind in ['class', 'struct','file', 'namespace']: + md_nodes = self.get_memberdef_nodes_and_signatures(node, kind) + for sig in md_nodes: + self.handle_typical_memberdefs(sig, md_nodes[sig]) + + def do_memberdef(self, node): + """Handle cases outside of class, struct, file or namespace. These are + now dealt with by `handle_overloaded_memberfunction`. + Do these even exist??? + """ + prot = node.attributes['prot'].value + id = node.attributes['id'].value + kind = node.attributes['kind'].value + tmp = node.parentNode.parentNode.parentNode + compdef = tmp.getElementsByTagName('compounddef')[0] + cdef_kind = compdef.attributes['kind'].value + if cdef_kind in ('file', 'namespace', 'class', 'struct'): + # These cases are now handled by `handle_typical_memberdefs` + return + if prot != 'public': + return + first = self.get_specific_nodes(node, ('definition', 'name')) + name = self.extract_text(first['name']) + if name[:8] == 'operator': # Don't handle operators yet. + return + if not 'definition' in first or kind in ['variable', 'typedef']: + return + + data = self.extract_text(first['definition']) + self.add_text('\n') + self.add_text(['/* where did this entry come from??? */', '\n']) + self.add_text('%feature("docstring") %s "\n%s' % (data, data)) + + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + self.add_text(['";', '\n']) + +# MARK: Entry tag handlers (dont print anything meaningful) + def do_sectiondef(self, node): + kind = node.attributes['kind'].value + if kind in ('public-func', 'func', 'user-defined', ''): + self.subnode_parse(node) + + def do_header(self, node): + """For a user defined section def a header field is present + which should not be printed as such, so we comment it in the + output.""" + data = self.extract_text(node) + self.add_text('\n/*\n %s \n*/\n' % data) + # If our immediate sibling is a 'description' node then we + # should comment that out also and remove it from the parent + # node's children. + parent = node.parentNode + idx = parent.childNodes.index(node) + if len(parent.childNodes) >= idx + 2: + nd = parent.childNodes[idx + 2] + if nd.nodeName == 'description': + nd = parent.removeChild(nd) + self.add_text('\n/*') + self.subnode_parse(nd) + self.add_text('\n*/\n') + + def do_member(self, node): + kind = node.attributes['kind'].value + refid = node.attributes['refid'].value + if kind == 'function' and refid[:9] == 'namespace': + self.subnode_parse(node) + + def do_doxygenindex(self, node): + self.multi = 1 + comps = node.getElementsByTagName('compound') + for c in comps: + refid = c.attributes['refid'].value + fname = refid + '.xml' + if not os.path.exists(fname): + fname = os.path.join(self.my_dir, fname) + if not self.quiet: + print("parsing file: %s" % fname) + p = Doxy2SWIG(fname) + p.generate() + self.pieces.extend(p.pieces) + +# MARK: main +def main(): + usage = __doc__ + p = Doxy2SWIG('xml/index.xml') + p.generate() + p.write('../../openmoc/docstring.i') + +if __name__ == '__main__': + main() diff --git a/docs/img/alg-SOR-solve.png b/docs/img/alg-SOR-solve.png new file mode 100644 index 000000000..08b33b830 Binary files /dev/null and b/docs/img/alg-SOR-solve.png differ diff --git a/docs/img/alg-cmfd-solve.png b/docs/img/alg-cmfd-solve.png new file mode 100644 index 000000000..558749518 Binary files /dev/null and b/docs/img/alg-cmfd-solve.png differ diff --git a/docs/img/alg-transport-sweep-CMFD.png b/docs/img/alg-transport-sweep-CMFD.png new file mode 100644 index 000000000..c3a9d94e0 Binary files /dev/null and b/docs/img/alg-transport-sweep-CMFD.png differ diff --git a/docs/img/annular_pin_fuel_rings.png b/docs/img/annular_pin_fuel_rings.png new file mode 100644 index 000000000..727805467 Binary files /dev/null and b/docs/img/annular_pin_fuel_rings.png differ diff --git a/docs/img/annular_pin_inner_rings.png b/docs/img/annular_pin_inner_rings.png new file mode 100644 index 000000000..95648fbdc Binary files /dev/null and b/docs/img/annular_pin_inner_rings.png differ diff --git a/docs/img/annular_pin_materials.png b/docs/img/annular_pin_materials.png new file mode 100644 index 000000000..e91e40ab2 Binary files /dev/null and b/docs/img/annular_pin_materials.png differ diff --git a/docs/img/annular_pin_outer_rings.png b/docs/img/annular_pin_outer_rings.png new file mode 100644 index 000000000..ebd9acf7c Binary files /dev/null and b/docs/img/annular_pin_outer_rings.png differ diff --git a/docs/img/c5g7-cmfd-cells.png b/docs/img/c5g7-cmfd-cells.png new file mode 100644 index 000000000..bc867b418 Binary files /dev/null and b/docs/img/c5g7-cmfd-cells.png differ diff --git a/docs/img/c5g7-fsrs.png b/docs/img/c5g7-fsrs.png new file mode 100644 index 000000000..5f15d68f6 Binary files /dev/null and b/docs/img/c5g7-fsrs.png differ diff --git a/docs/img/cells.png b/docs/img/cells.png new file mode 100644 index 000000000..a9184f9ad Binary files /dev/null and b/docs/img/cells.png differ diff --git a/docs/img/cmfd-SOR-solve.png b/docs/img/cmfd-SOR-solve.png new file mode 100644 index 000000000..02427b93a Binary files /dev/null and b/docs/img/cmfd-SOR-solve.png differ diff --git a/docs/img/cmfd-accel-alg-1.png b/docs/img/cmfd-accel-alg-1.png new file mode 100644 index 000000000..7c9f4db17 Binary files /dev/null and b/docs/img/cmfd-accel-alg-1.png differ diff --git a/docs/img/cmfd-accel-alg-2.png b/docs/img/cmfd-accel-alg-2.png new file mode 100644 index 000000000..7c9f4db17 Binary files /dev/null and b/docs/img/cmfd-accel-alg-2.png differ diff --git a/docs/img/cmfd-accel-moc.png b/docs/img/cmfd-accel-moc.png new file mode 100644 index 000000000..2422c3b0c Binary files /dev/null and b/docs/img/cmfd-accel-moc.png differ diff --git a/docs/img/cmfd-example.png b/docs/img/cmfd-example.png new file mode 100644 index 000000000..0ae1f374f Binary files /dev/null and b/docs/img/cmfd-example.png differ diff --git a/docs/img/cmfd-gs.png b/docs/img/cmfd-gs.png new file mode 100644 index 000000000..191542ed2 Binary files /dev/null and b/docs/img/cmfd-gs.png differ diff --git a/docs/img/cmfd-matrix.png b/docs/img/cmfd-matrix.png new file mode 100644 index 000000000..e8f03f551 Binary files /dev/null and b/docs/img/cmfd-matrix.png differ diff --git a/docs/img/cmfd-solve-alg.png b/docs/img/cmfd-solve-alg.png new file mode 100644 index 000000000..f50619703 Binary files /dev/null and b/docs/img/cmfd-solve-alg.png differ diff --git a/docs/img/corner-crossing-2.png b/docs/img/corner-crossing-2.png new file mode 100644 index 000000000..694a72881 Binary files /dev/null and b/docs/img/corner-crossing-2.png differ diff --git a/docs/img/corner-crossing-3.png b/docs/img/corner-crossing-3.png new file mode 100644 index 000000000..04eeeb697 Binary files /dev/null and b/docs/img/corner-crossing-3.png differ diff --git a/docs/img/corner-crossing.png b/docs/img/corner-crossing.png new file mode 100644 index 000000000..d2191b0c7 Binary files /dev/null and b/docs/img/corner-crossing.png differ diff --git a/docs/img/cosine_flux_distribution.png b/docs/img/cosine_flux_distribution.png new file mode 100644 index 000000000..2e675f0c3 Binary files /dev/null and b/docs/img/cosine_flux_distribution.png differ diff --git a/docs/img/cover.odg b/docs/img/cover.odg new file mode 100644 index 000000000..64583ce8a Binary files /dev/null and b/docs/img/cover.odg differ diff --git a/docs/img/cover.png b/docs/img/cover.png new file mode 100644 index 000000000..251a1a0b2 Binary files /dev/null and b/docs/img/cover.png differ diff --git a/docs/img/csg-cells-halfspace-intersection.odg b/docs/img/csg-cells-halfspace-intersection.odg new file mode 100644 index 000000000..cd38a7cf8 Binary files /dev/null and b/docs/img/csg-cells-halfspace-intersection.odg differ diff --git a/docs/img/csg-cells-halfspace-intersection.png b/docs/img/csg-cells-halfspace-intersection.png new file mode 100644 index 000000000..09537a4d5 Binary files /dev/null and b/docs/img/csg-cells-halfspace-intersection.png differ diff --git a/docs/img/csg-halfspace-intersection.odg b/docs/img/csg-halfspace-intersection.odg new file mode 100644 index 000000000..feb042e0a Binary files /dev/null and b/docs/img/csg-halfspace-intersection.odg differ diff --git a/docs/img/csg-halfspace-intersection.png b/docs/img/csg-halfspace-intersection.png new file mode 100644 index 000000000..8fab80a64 Binary files /dev/null and b/docs/img/csg-halfspace-intersection.png differ diff --git a/docs/img/csg-halfspace.odg b/docs/img/csg-halfspace.odg new file mode 100644 index 000000000..8e916486c Binary files /dev/null and b/docs/img/csg-halfspace.odg differ diff --git a/docs/img/csg-halfspace.png b/docs/img/csg-halfspace.png new file mode 100644 index 000000000..0902ef964 Binary files /dev/null and b/docs/img/csg-halfspace.png differ diff --git a/docs/img/csg-lattice-cells.odg b/docs/img/csg-lattice-cells.odg new file mode 100644 index 000000000..ce82812f1 Binary files /dev/null and b/docs/img/csg-lattice-cells.odg differ diff --git a/docs/img/csg-lattice-cells.png b/docs/img/csg-lattice-cells.png new file mode 100644 index 000000000..45e3e29cb Binary files /dev/null and b/docs/img/csg-lattice-cells.png differ diff --git a/docs/img/csg-primitives-hierarchy.odg b/docs/img/csg-primitives-hierarchy.odg new file mode 100644 index 000000000..7bcad002b Binary files /dev/null and b/docs/img/csg-primitives-hierarchy.odg differ diff --git a/docs/img/csg-primitives-hierarchy.png b/docs/img/csg-primitives-hierarchy.png new file mode 100644 index 000000000..8b09376f8 Binary files /dev/null and b/docs/img/csg-primitives-hierarchy.png differ diff --git a/docs/img/csg-tree.png b/docs/img/csg-tree.png new file mode 100644 index 000000000..83c0465b6 Binary files /dev/null and b/docs/img/csg-tree.png differ diff --git a/docs/img/current-tally.png b/docs/img/current-tally.png new file mode 100644 index 000000000..72ea034de Binary files /dev/null and b/docs/img/current-tally.png differ diff --git a/docs/img/cyclic-tracks.png b/docs/img/cyclic-tracks.png new file mode 100644 index 000000000..f58cdf90f Binary files /dev/null and b/docs/img/cyclic-tracks.png differ diff --git a/docs/img/exponential-interpolation-algorithm.png b/docs/img/exponential-interpolation-algorithm.png new file mode 100644 index 000000000..f6f37fa8a Binary files /dev/null and b/docs/img/exponential-interpolation-algorithm.png differ diff --git a/docs/img/exponential-tangent.png b/docs/img/exponential-tangent.png new file mode 100644 index 000000000..34b285f68 Binary files /dev/null and b/docs/img/exponential-tangent.png differ diff --git a/docs/img/fig-fsr-mesh-regions.png b/docs/img/fig-fsr-mesh-regions.png new file mode 100644 index 000000000..28d75b91b Binary files /dev/null and b/docs/img/fig-fsr-mesh-regions.png differ diff --git a/docs/img/find-cell-algorithm.png b/docs/img/find-cell-algorithm.png new file mode 100644 index 000000000..ce61e54cf Binary files /dev/null and b/docs/img/find-cell-algorithm.png differ diff --git a/docs/img/find-universe-algorithm.png b/docs/img/find-universe-algorithm.png new file mode 100644 index 000000000..c712c224f Binary files /dev/null and b/docs/img/find-universe-algorithm.png differ diff --git a/docs/img/fission-rates.png b/docs/img/fission-rates.png new file mode 100644 index 000000000..869fe7303 Binary files /dev/null and b/docs/img/fission-rates.png differ diff --git a/docs/img/flat-source-regions.png b/docs/img/flat-source-regions.png new file mode 100644 index 000000000..2920dfa2f Binary files /dev/null and b/docs/img/flat-source-regions.png differ diff --git a/docs/img/flux-fsr-0.png b/docs/img/flux-fsr-0.png new file mode 100644 index 000000000..6bbc52ac3 Binary files /dev/null and b/docs/img/flux-fsr-0.png differ diff --git a/docs/img/flux-fsr-1.png b/docs/img/flux-fsr-1.png new file mode 100644 index 000000000..7c4deb2e8 Binary files /dev/null and b/docs/img/flux-fsr-1.png differ diff --git a/docs/img/flux-group-1.png b/docs/img/flux-group-1.png new file mode 100644 index 000000000..e750a6c6f Binary files /dev/null and b/docs/img/flux-group-1.png differ diff --git a/docs/img/flux-group-7.png b/docs/img/flux-group-7.png new file mode 100644 index 000000000..c33913e19 Binary files /dev/null and b/docs/img/flux-group-7.png differ diff --git a/docs/img/fs-32-angles-group-3.png b/docs/img/fs-32-angles-group-3.png new file mode 100644 index 000000000..d352ffde6 Binary files /dev/null and b/docs/img/fs-32-angles-group-3.png differ diff --git a/docs/img/fs-4-angles-group-3.png b/docs/img/fs-4-angles-group-3.png new file mode 100644 index 000000000..8fc86dd1d Binary files /dev/null and b/docs/img/fs-4-angles-group-3.png differ diff --git a/docs/img/fs-flux-calc-32-angles-group-1.png b/docs/img/fs-flux-calc-32-angles-group-1.png new file mode 100644 index 000000000..58ffc7ec7 Binary files /dev/null and b/docs/img/fs-flux-calc-32-angles-group-1.png differ diff --git a/docs/img/fs-flux-calc-4-angles-group-1.png b/docs/img/fs-flux-calc-4-angles-group-1.png new file mode 100644 index 000000000..ae8e26792 Binary files /dev/null and b/docs/img/fs-flux-calc-4-angles-group-1.png differ diff --git a/docs/img/general-spatial-plot-1.png b/docs/img/general-spatial-plot-1.png new file mode 100644 index 000000000..088d4d540 Binary files /dev/null and b/docs/img/general-spatial-plot-1.png differ diff --git a/docs/img/general-spatial-plot-2.png b/docs/img/general-spatial-plot-2.png new file mode 100644 index 000000000..088d4d540 Binary files /dev/null and b/docs/img/general-spatial-plot-2.png differ diff --git a/docs/img/get_rand_array.cpp b/docs/img/get_rand_array.cpp new file mode 100644 index 000000000..0b3f727bb --- /dev/null +++ b/docs/img/get_rand_array.cpp @@ -0,0 +1,12 @@ +/* File get_rand_array.cpp */ +#include "get_rand_array.h" + +/* Define function implementation */ +void get_rand_array(double* output_array, int length) { + + /* Populate input NumPy array with random numbers */ + for (int i=0; i < length; i++) + output_array[i] = ((double) rand()) / RAND_MAX; + + return; +} diff --git a/docs/img/get_rand_array.h b/docs/img/get_rand_array.h new file mode 100644 index 000000000..0f7aa782f --- /dev/null +++ b/docs/img/get_rand_array.h @@ -0,0 +1,5 @@ +/* File get_rand_array.h */ +#include + +/* Define function prototype to take in a NumPy array */ +void get_rand_array(double* output_array, int length); diff --git a/docs/img/get_rand_array.i b/docs/img/get_rand_array.i new file mode 100644 index 000000000..4c37a41fc --- /dev/null +++ b/docs/img/get_rand_array.i @@ -0,0 +1,18 @@ +%module get_rand_array + +%{ + #define SWIG_FILE_WITH_INIT + #include "get_rand_array.h" +%} + +/* Include the NumPy typemaps library */ +%include "numpy.i" + +%init %{ + import_array(); +%} + +/* Typemap for get_rand_array(double* output_array, int length) C/C++ routine */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* output_array, int length)}; + +%include "get_rand_array.h" diff --git a/docs/img/get_rand_list.cpp b/docs/img/get_rand_list.cpp new file mode 100644 index 000000000..e501f71f5 --- /dev/null +++ b/docs/img/get_rand_list.cpp @@ -0,0 +1,15 @@ +/* File get_rand_list.cpp */ +#include "get_rand_list.h" + +/* Define function implementation */ +std::vector get_rand_list(int length) { + + /* Allocate memory for the C++ STL vector */ + std::vector output_list(length); + + /* Populate vector with random numbers */ + for (int i=0; i < length; i++) + output_list[i] = ((double) rand()) / RAND_MAX; + + return output_list; +} diff --git a/docs/img/get_rand_list.h b/docs/img/get_rand_list.h new file mode 100644 index 000000000..03c295f66 --- /dev/null +++ b/docs/img/get_rand_list.h @@ -0,0 +1,6 @@ +/* File get_rand_list.h */ +#include +#include + +/* Define function prototype to return a random Python tuple */ +std::vector get_rand_list(int length); diff --git a/docs/img/get_rand_list.i b/docs/img/get_rand_list.i new file mode 100644 index 000000000..f3535d91a --- /dev/null +++ b/docs/img/get_rand_list.i @@ -0,0 +1,16 @@ +%module get_rand_list +%{ + #define SWIG_FILE_WITH_INIT + #include "get_rand_list.h" +%} + +%include "std_vector.i" + +/* SWIG template for get_rand_list(int length) C++ routine */ +namespace std { + %template(DoubleVector) vector; +} + +%include "get_rand_list.h" + + diff --git a/docs/img/halfspace.png b/docs/img/halfspace.png new file mode 100644 index 000000000..93a6bacfd Binary files /dev/null and b/docs/img/halfspace.png differ diff --git a/docs/img/halfspace.svg b/docs/img/halfspace.svg new file mode 100644 index 000000000..8f5c5d54d --- /dev/null +++ b/docs/img/halfspace.svg @@ -0,0 +1,54 @@ + + + + + + + + + image/svg+xml + + + + + + + + +1 + -1 + + diff --git a/docs/img/materials.png b/docs/img/materials.png new file mode 100644 index 000000000..ce25b0b24 Binary files /dev/null and b/docs/img/materials.png differ diff --git a/docs/img/min-surf-dist-algorithm.png b/docs/img/min-surf-dist-algorithm.png new file mode 100644 index 000000000..ade3ec814 Binary files /dev/null and b/docs/img/min-surf-dist-algorithm.png differ diff --git a/docs/img/nested-coordinates.odg b/docs/img/nested-coordinates.odg new file mode 100644 index 000000000..378d1e342 Binary files /dev/null and b/docs/img/nested-coordinates.odg differ diff --git a/docs/img/nested-coordinates.png b/docs/img/nested-coordinates.png new file mode 100644 index 000000000..5f421bca2 Binary files /dev/null and b/docs/img/nested-coordinates.png differ diff --git a/docs/img/next-intersection-point-algorithm.png b/docs/img/next-intersection-point-algorithm.png new file mode 100644 index 000000000..d21b9783c Binary files /dev/null and b/docs/img/next-intersection-point-algorithm.png differ diff --git a/docs/img/numpy.i b/docs/img/numpy.i new file mode 100644 index 000000000..2bad3bb2b --- /dev/null +++ b/docs/img/numpy.i @@ -0,0 +1,1576 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +# define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#include +%} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject *)a)) +%#define array_type(a) (int)(PyArray_TYPE(a)) +%#define array_numdims(a) (((PyArrayObject *)a)->nd) +%#define array_dimensions(a) (((PyArrayObject *)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject *)a)->dimensions[i]) +%#define array_data(a) (((PyArrayObject *)a)->data) +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED(a)) +%#define array_is_fortran(a) (PyArray_ISFORTRAN(a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; + if (PyModule_Check( py_obj)) return "module" ; +%#if PY_MAJOR_VERSION < 3 + if (PyFile_Check( py_obj)) return "file" ; + if (PyInstance_Check(py_obj)) return "instance" ; +%#endif + + return "unkown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) { + static const char* type_names[25] = {"bool", "byte", "unsigned byte", + "short", "unsigned short", "int", + "unsigned int", "long", "unsigned long", + "long long", "unsigned long long", + "float", "double", "long double", + "complex float", "complex double", + "complex long double", "object", + "string", "unicode", "void", "ntypes", + "notype", "char", "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. Allow character and byte + * to match. Also allow int and long to match. This is deprecated. + * You should use PyArray_EquivTypenums() instead. + */ + int type_match(int actual_type, int desired_type) { + return PyArray_EquivTypenums(actual_type, desired_type); + } +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", "header", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char * desired_type = typecode_string(typecode); + const char * actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, + int min_dims, int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object, + int min_dims, int max_dims) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(ary->descr); + result = (PyArrayObject*) PyArray_FromArray(ary, ary->descr, NPY_FORTRAN); + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2, 0, 0); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + +} /* end fragment */ + + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", "header", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, npy_intp* size, int n) + { + int i; + int success = 1; + int len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to to be FORTRAN ordered. If the + * the PyArrayObject is already FORTRAN ordered, do nothing. Else, + * set the FORTRAN ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + if (array_is_fortran(ary)) return success; + /* Set the FORTRAN ordered flag */ + ary->flags = NPY_FARRAY; + /* Recompute the strides */ + ary->strides[0] = ary->strides[nd-1]; + for (i=1; i < nd; ++i) + ary->strides[i] = ary->strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", "header", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") { } + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 41 typemaps that allow C arguments + * of the form + * + * (DATA_TYPE IN_ARRAY1[ANY]) + * (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * (DATA_TYPE INPLACE_ARRAY1[ANY]) + * (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect FORTRAN ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject * array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject * array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject * array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject * array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject * array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject * array = (PyArrayObject*) obj; + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject * array = (PyArrayObject*) obj; + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3)); + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,array); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject * array = (PyArrayObject*) obj; + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject * array = (PyArrayObject*) obj; + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +/* *************************************************************** + * Swig complains about a syntax error for the following macro + * expansions: + * + * %numpy_typemaps(complex float, NPY_CFLOAT , int) + * + * %numpy_typemaps(complex double, NPY_CDOUBLE, int) + * + * %numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int) + */ + +#endif /* SWIGPYTHON */ diff --git a/docs/img/openmoc-logo-api.png b/docs/img/openmoc-logo-api.png new file mode 100644 index 000000000..b56c94a93 Binary files /dev/null and b/docs/img/openmoc-logo-api.png differ diff --git a/docs/img/openmoc-logo-sphinx-small.png b/docs/img/openmoc-logo-sphinx-small.png new file mode 100644 index 000000000..a4835aef5 Binary files /dev/null and b/docs/img/openmoc-logo-sphinx-small.png differ diff --git a/docs/img/openmoc-logo-sphinx.png b/docs/img/openmoc-logo-sphinx.png new file mode 100644 index 000000000..a3162b47e Binary files /dev/null and b/docs/img/openmoc-logo-sphinx.png differ diff --git a/docs/img/openmoc-logo.png b/docs/img/openmoc-logo.png new file mode 100644 index 000000000..4a0f24478 Binary files /dev/null and b/docs/img/openmoc-logo.png differ diff --git a/docs/img/openmoc-software-design.png b/docs/img/openmoc-software-design.png new file mode 100644 index 000000000..5e259ba19 Binary files /dev/null and b/docs/img/openmoc-software-design.png differ diff --git a/docs/img/overall-iterative-scheme.png b/docs/img/overall-iterative-scheme.png new file mode 100644 index 000000000..ec8fa6d7a Binary files /dev/null and b/docs/img/overall-iterative-scheme.png differ diff --git a/docs/img/pin-cell-fsrs-annular.png b/docs/img/pin-cell-fsrs-annular.png new file mode 100644 index 000000000..f003326c1 Binary files /dev/null and b/docs/img/pin-cell-fsrs-annular.png differ diff --git a/docs/img/pin-cell-fsrs-moderator-rings.png b/docs/img/pin-cell-fsrs-moderator-rings.png new file mode 100644 index 000000000..4cbd7b90a Binary files /dev/null and b/docs/img/pin-cell-fsrs-moderator-rings.png differ diff --git a/docs/img/pin-cell-fsrs.png b/docs/img/pin-cell-fsrs.png new file mode 100644 index 000000000..d87462af6 Binary files /dev/null and b/docs/img/pin-cell-fsrs.png differ diff --git a/docs/img/pin-cell-materials-annular.png b/docs/img/pin-cell-materials-annular.png new file mode 100644 index 000000000..3e46b19a1 Binary files /dev/null and b/docs/img/pin-cell-materials-annular.png differ diff --git a/docs/img/pin-cell-materials.png b/docs/img/pin-cell-materials.png new file mode 100644 index 000000000..da18e71f6 Binary files /dev/null and b/docs/img/pin-cell-materials.png differ diff --git a/docs/img/polar-quad-ty.png b/docs/img/polar-quad-ty.png new file mode 100644 index 000000000..e1d610df7 Binary files /dev/null and b/docs/img/polar-quad-ty.png differ diff --git a/docs/img/polar_quadrature_sets.png b/docs/img/polar_quadrature_sets.png new file mode 100644 index 000000000..7fc07c4d3 Binary files /dev/null and b/docs/img/polar_quadrature_sets.png differ diff --git a/docs/img/print_list.cpp b/docs/img/print_list.cpp new file mode 100644 index 000000000..58b8ca7a1 --- /dev/null +++ b/docs/img/print_list.cpp @@ -0,0 +1,10 @@ +/* File print_list.cpp */ +#include "print_list.h" + +void print_list(int length, double* list) { + printf("Printing a Python list from C/C++\n"); + + /* Loop over each list value and print to the screen */ + for (int i=0; i < length; i++) + printf("list[%d] = %f\n", i, list[i]); +} diff --git a/docs/img/print_list.h b/docs/img/print_list.h new file mode 100644 index 000000000..b6662fb2c --- /dev/null +++ b/docs/img/print_list.h @@ -0,0 +1,5 @@ +/* File print_list.h */ +#include + +/* Define function prototype */ +void print_list(int length, double* list); diff --git a/docs/img/print_list.i b/docs/img/print_list.i new file mode 100644 index 000000000..f534ff32b --- /dev/null +++ b/docs/img/print_list.i @@ -0,0 +1,44 @@ +%module print_list +%{ + #define SWIG_FILE_WITH_INIT + #include "print_list.h" +%} + +/* Include the SWIG typemaps library */ +%include typemaps.i + +/* Typemap for the print(int length, double* list) C/C++ routine */ +%typemap(in) (int length, double* list) { + + /* Check that the input is a Python list data structure */ + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values\n"); + return NULL; + } + + /* Set the first parameter to the length of the Python list input */ + $1 = PySequence_Length($input); + + /* Allocate memory to convert the list into a C/C++ array */ + $2 = (double*) malloc($1 * sizeof(double)); + + /* Loop over the values in the list */ + for (int i = 0; i < $1; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If the value is a number, cast it as an int and set the + * input array value */ + if (PyNumber_Check(o)) { + $2[i] = (double) PyFloat_AsDouble(o); + } + else { + free($2); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers\n"); + return NULL; + } + } +} + +%include "print_list.h" diff --git a/docs/img/ray-tracing-algorithm.png b/docs/img/ray-tracing-algorithm.png new file mode 100644 index 000000000..1466154dc Binary files /dev/null and b/docs/img/ray-tracing-algorithm.png differ diff --git a/docs/img/saxpy.cpp b/docs/img/saxpy.cpp new file mode 100644 index 000000000..5346d3064 --- /dev/null +++ b/docs/img/saxpy.cpp @@ -0,0 +1,44 @@ +/* File saxpy.cpp */ +#include "saxpy.h" + +/* Define global variables */ +int length; +double a; +double* x; +double* y; + +void set_array_length(int n) { + length = n; +} + +void initialize_data() { + + /* Allocate memory for arrays */ + x = (double*)malloc(length*sizeof(double)); + y = (double*)malloc(length*sizeof(double)); + + /* Initialize data with random numbers in [0,1] */ + a = float(rand()) / RAND_MAX; + + for (int i=0; i < length; i++) { + x[i] = float(rand()) / RAND_MAX; + y[i] = float(rand()) / RAND_MAX; + } +} + +void free_data() { + free(x); + free(y); +} + +void print_data() { + printf("a = %f\n", a); + + for (int i=0; i < length; i++) + printf("x[%d] = %f\ty[%d] = %f\n", i, x[i], i, y[i]); +} + +void saxpy() { + for (int i=0; i < length; i++) + y[i] = a * x[i] + y[i]; +} diff --git a/docs/img/saxpy.h b/docs/img/saxpy.h new file mode 100644 index 000000000..f91228822 --- /dev/null +++ b/docs/img/saxpy.h @@ -0,0 +1,10 @@ +/* File saxpy.h */ +#include +#include + +/* Define function prototypes */ +void set_array_length(int n); +void initialize_data(); +void free_data(); +void print_data(); +void saxpy(); diff --git a/docs/img/saxpy.i b/docs/img/saxpy.i new file mode 100644 index 000000000..7fefc5efe --- /dev/null +++ b/docs/img/saxpy.i @@ -0,0 +1,7 @@ +%module saxpy +%{ + #define SWIG_FILE_WITH_INIT + #include "saxpy.h" +%} + +%include "saxpy.h" diff --git a/docs/img/segments.png b/docs/img/segments.png new file mode 100644 index 000000000..00147bde1 Binary files /dev/null and b/docs/img/segments.png differ diff --git a/docs/img/solvers.png b/docs/img/solvers.png new file mode 100644 index 000000000..15a645c64 Binary files /dev/null and b/docs/img/solvers.png differ diff --git a/docs/img/source-update-algorithm.png b/docs/img/source-update-algorithm.png new file mode 100644 index 000000000..d0a04cd48 Binary files /dev/null and b/docs/img/source-update-algorithm.png differ diff --git a/docs/img/spatial-a.png b/docs/img/spatial-a.png new file mode 100644 index 000000000..088d4d540 Binary files /dev/null and b/docs/img/spatial-a.png differ diff --git a/docs/img/spatial-b.png b/docs/img/spatial-b.png new file mode 100644 index 000000000..03c8a85f1 Binary files /dev/null and b/docs/img/spatial-b.png differ diff --git a/docs/img/spatial-c.png b/docs/img/spatial-c.png new file mode 100644 index 000000000..9b2167ec2 Binary files /dev/null and b/docs/img/spatial-c.png differ diff --git a/docs/img/sum_array.cpp b/docs/img/sum_array.cpp new file mode 100644 index 000000000..541bcc3c3 --- /dev/null +++ b/docs/img/sum_array.cpp @@ -0,0 +1,14 @@ +/* File sum_array.cpp */ + +/* Define function implementation */ +double sum_array(double* input_array, int length) { + + /* Initialize sum */ + double sum = 0.; + + /* Compute sum of array elements */ + for (int i=0; i < length; i++) + sum += input_array[i]; + + return sum; +} diff --git a/docs/img/sum_array.h b/docs/img/sum_array.h new file mode 100644 index 000000000..869d8e44b --- /dev/null +++ b/docs/img/sum_array.h @@ -0,0 +1,4 @@ +/* File sum_array.h */ + +/* Define function prototype to take in a NumPy array */ +double sum_array(double* input_array, int length); diff --git a/docs/img/sum_array.i b/docs/img/sum_array.i new file mode 100644 index 000000000..135267498 --- /dev/null +++ b/docs/img/sum_array.i @@ -0,0 +1,18 @@ +%module sum_array + +%{ + #define SWIG_FILE_WITH_INIT + #include "sum_array.h" +%} + +/* Include the NumPy typemaps library */ +%include "numpy.i" + +%init %{ + import_array(); +%} + +/* Typemap for the sum_list(double* input_list, int length) C/C++ routine */ +%apply (double* IN_ARRAY1, int DIM1) {(double* input_array, int length)}; + +%include "sum_array.h" diff --git a/docs/img/sum_list.cpp b/docs/img/sum_list.cpp new file mode 100644 index 000000000..29368a06e --- /dev/null +++ b/docs/img/sum_list.cpp @@ -0,0 +1,14 @@ +/* File sum_list.cpp */ +#include "sum_list.h" + +double sum_list(double* input_list, int length) { + + /* Initialize sum */ + double sum = 0.; + + /* Compute sum of array elements */ + for (int i=0; i < length; i++) + sum += input_list[i]; + + return sum; +} diff --git a/docs/img/sum_list.h b/docs/img/sum_list.h new file mode 100644 index 000000000..aee2debc3 --- /dev/null +++ b/docs/img/sum_list.h @@ -0,0 +1,5 @@ +/* File sum_list.h */ +#include + +/* Define function prototype */ +double sum_list(double* input_list, int length); diff --git a/docs/img/sum_list.i b/docs/img/sum_list.i new file mode 100644 index 000000000..677e64be8 --- /dev/null +++ b/docs/img/sum_list.i @@ -0,0 +1,44 @@ +%module sum_list +%{ + #define SWIG_FILE_WITH_INIT + #include "sum_list.h" +%} + +/* Include the SWIG typemaps library */ +%include typemaps.i + +/* Typemap for the sum_list(double* input_list, int length) C/C++ routine */ +%typemap(in) (double* input_list, int length) { + + /* Check that the input is a Python list data structure */ + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values\n"); + return NULL; + } + + /* Set the second parameter to the length of the Python list input */ + $2 = PySequence_Length($input); + + /* Allocate memory to convert the list into a C/C++ array */ + $1 = (double*) malloc($2 * sizeof(double)); + + /* Loop over the values in the list */ + for (int i = 0; i < $2; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If the value is a number, cast it as an int and set the + * input array value */ + if (PyNumber_Check(o)) { + $1[i] = (double) PyFloat_AsDouble(o); + } + else { + free($1); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers\n"); + return NULL; + } + } +} + +%include "sum_list.h" diff --git a/docs/img/surfaces.png b/docs/img/surfaces.png new file mode 100644 index 000000000..8d25f35cc Binary files /dev/null and b/docs/img/surfaces.png differ diff --git a/docs/img/surfs-cells.png b/docs/img/surfs-cells.png new file mode 100644 index 000000000..c603d299c Binary files /dev/null and b/docs/img/surfs-cells.png differ diff --git a/docs/img/tracks.png b/docs/img/tracks.png new file mode 100644 index 000000000..5e82d3fbe Binary files /dev/null and b/docs/img/tracks.png differ diff --git a/docs/img/transport-sweep-algorithm.png b/docs/img/transport-sweep-algorithm.png new file mode 100644 index 000000000..cb2c0d262 Binary files /dev/null and b/docs/img/transport-sweep-algorithm.png differ diff --git a/docs/img/transport-sweep.odg b/docs/img/transport-sweep.odg new file mode 100644 index 000000000..b1ecc45ec Binary files /dev/null and b/docs/img/transport-sweep.odg differ diff --git a/docs/img/transport-sweep.png b/docs/img/transport-sweep.png new file mode 100644 index 000000000..4fded7dd1 Binary files /dev/null and b/docs/img/transport-sweep.png differ diff --git a/docs/img/union.png b/docs/img/union.png new file mode 100644 index 000000000..44dc6e010 Binary files /dev/null and b/docs/img/union.png differ diff --git a/docs/img/union.svg b/docs/img/union.svg new file mode 100644 index 000000000..066fa2ba1 --- /dev/null +++ b/docs/img/union.svg @@ -0,0 +1,105 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + +1 + -1 + -2 + +2 + -3 + +3 + + diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html new file mode 100644 index 000000000..9df3ab446 --- /dev/null +++ b/docs/source/_templates/layout.html @@ -0,0 +1,18 @@ +{% extends "!layout.html" %} + +{% block footer %} +{{ super() }} + +{% endblock %} diff --git a/docs/source/api/cell.rst b/docs/source/api/cell.rst new file mode 100644 index 000000000..c4da472f2 --- /dev/null +++ b/docs/source/api/cell.rst @@ -0,0 +1,9 @@ +.. _cell: + +==== +Cell +==== + +.. doxygenclass:: Cell + :project: OpenMOC + :members: diff --git a/docs/source/api/cellbasic.rst b/docs/source/api/cellbasic.rst new file mode 100644 index 000000000..7c6fb2542 --- /dev/null +++ b/docs/source/api/cellbasic.rst @@ -0,0 +1,9 @@ +.. _cellbasic: + +========= +CellBasic +========= + +.. doxygenclass:: CellBasic + :project: OpenMOC + :members: diff --git a/docs/source/api/cellfill.rst b/docs/source/api/cellfill.rst new file mode 100644 index 000000000..ad841b13d --- /dev/null +++ b/docs/source/api/cellfill.rst @@ -0,0 +1,9 @@ +.. _cellfill: + +======== +CellFill +======== + +.. doxygenclass:: CellFill + :project: OpenMOC + :members: diff --git a/docs/source/api/circle.rst b/docs/source/api/circle.rst new file mode 100644 index 000000000..4283c3588 --- /dev/null +++ b/docs/source/api/circle.rst @@ -0,0 +1,9 @@ +.. _circle: + +====== +Circle +====== + +.. doxygenclass:: Circle + :project: OpenMOC + :members: diff --git a/docs/source/api/cpusolver.rst b/docs/source/api/cpusolver.rst new file mode 100644 index 000000000..3b60da779 --- /dev/null +++ b/docs/source/api/cpusolver.rst @@ -0,0 +1,9 @@ +.. _cpusolver: + +========= +CPUSolver +========= + +.. doxygenclass:: CPUSolver + :project: OpenMOC + :members: diff --git a/docs/source/api/geometry.rst b/docs/source/api/geometry.rst new file mode 100644 index 000000000..2d25f8584 --- /dev/null +++ b/docs/source/api/geometry.rst @@ -0,0 +1,9 @@ +.. _geometry: + +======== +Geometry +======== + +.. doxygenclass:: Geometry + :project: OpenMOC + :members: diff --git a/docs/source/api/gpusolver.rst b/docs/source/api/gpusolver.rst new file mode 100644 index 000000000..7d04845b1 --- /dev/null +++ b/docs/source/api/gpusolver.rst @@ -0,0 +1,9 @@ +.. _gpusolver: + +========= +GPUSolver +========= + +.. doxygenclass:: GPUSolver + :project: OpenMOC + :members: diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst new file mode 100644 index 000000000..96bf402b8 --- /dev/null +++ b/docs/source/api/index.rst @@ -0,0 +1,75 @@ +.. _api: + +=========== +OpenMOC API +=========== + +Welcome to the OpenMOC API! + +------- +Solvers +------- + +.. toctree:: + :maxdepth: 1 + + solver + cpusolver + gpusolver + threadprivatesolver + vectorizedsolver + vectorizedprivatesolver + +-------- +Geometry +-------- + +.. toctree:: + :maxdepth: 1 + + surface + plane + xplane + yplane + zplane + circle + cell + cellfill + cellbasic + universe + lattice + geometry + +----------- +Ray Tracing +----------- + +.. toctree:: + :maxdepth: 1 + + point + track + segment + trackgenerator + quadrature + + +--------- +Materials +--------- + +.. toctree:: + :maxdepth: 1 + + material + +--------- +Utilities +--------- + +.. toctree:: + :maxdepth: 1 + + timer + log + pairwisesum diff --git a/docs/source/api/lattice.rst b/docs/source/api/lattice.rst new file mode 100644 index 000000000..4629d8b98 --- /dev/null +++ b/docs/source/api/lattice.rst @@ -0,0 +1,9 @@ +.. _lattice: + +======= +Lattice +======= + +.. doxygenclass:: Lattice + :project: OpenMOC + :members: diff --git a/docs/source/api/log.rst b/docs/source/api/log.rst new file mode 100644 index 000000000..201412627 --- /dev/null +++ b/docs/source/api/log.rst @@ -0,0 +1,8 @@ +.. _log: + +=== +Log +=== + +.. doxygenfile:: log.h + :project: OpenMOC diff --git a/docs/source/api/material.rst b/docs/source/api/material.rst new file mode 100644 index 000000000..293dececb --- /dev/null +++ b/docs/source/api/material.rst @@ -0,0 +1,9 @@ +.. _material: + +======== +Material +======== + +.. doxygenclass:: Material + :project: OpenMOC + :members: diff --git a/docs/source/api/pairwisesum.rst b/docs/source/api/pairwisesum.rst new file mode 100644 index 000000000..524ce716a --- /dev/null +++ b/docs/source/api/pairwisesum.rst @@ -0,0 +1,8 @@ +.. _pairwisesum: + +============ +Pairwise Sum +============ + +.. doxygenfile:: pairwise_sum.h + :project: OpenMOC diff --git a/docs/source/api/plane.rst b/docs/source/api/plane.rst new file mode 100644 index 000000000..5e30ab90e --- /dev/null +++ b/docs/source/api/plane.rst @@ -0,0 +1,9 @@ +.. _plane: + +===== +Plane +===== + +.. doxygenclass:: Plane + :project: OpenMOC + :members: diff --git a/docs/source/api/point.rst b/docs/source/api/point.rst new file mode 100644 index 000000000..a207ab13b --- /dev/null +++ b/docs/source/api/point.rst @@ -0,0 +1,9 @@ +.. _point: + +===== +Point +===== + +.. doxygenclass:: Point + :project: OpenMOC + :members: diff --git a/docs/source/api/quadrature.rst b/docs/source/api/quadrature.rst new file mode 100644 index 000000000..828381650 --- /dev/null +++ b/docs/source/api/quadrature.rst @@ -0,0 +1,9 @@ +.. _quadrature: + +========== +Quadrature +========== + +.. doxygenclass:: Quadrature + :project: OpenMOC + :members: diff --git a/docs/source/api/segment.rst b/docs/source/api/segment.rst new file mode 100644 index 000000000..978e3f764 --- /dev/null +++ b/docs/source/api/segment.rst @@ -0,0 +1,8 @@ +.. _segment: + +======= +Segment +======= + +.. doxygenstruct:: segment + :project: OpenMOC diff --git a/docs/source/api/solver.rst b/docs/source/api/solver.rst new file mode 100644 index 000000000..fd2313616 --- /dev/null +++ b/docs/source/api/solver.rst @@ -0,0 +1,9 @@ +.. _solver: + +====== +Solver +====== + +.. doxygenclass:: Solver + :project: OpenMOC + :members: diff --git a/docs/source/api/surface.rst b/docs/source/api/surface.rst new file mode 100644 index 000000000..d5e108cbf --- /dev/null +++ b/docs/source/api/surface.rst @@ -0,0 +1,9 @@ +.. _surface: + +======= +Surface +======= + +.. doxygenclass:: Surface + :project: OpenMOC + :members: diff --git a/docs/source/api/threadprivatesolver.rst b/docs/source/api/threadprivatesolver.rst new file mode 100644 index 000000000..89dfcc070 --- /dev/null +++ b/docs/source/api/threadprivatesolver.rst @@ -0,0 +1,9 @@ +.. _threadprivatesolver: + +=================== +ThreadPrivateSolver +=================== + +.. doxygenclass:: ThreadPrivateSolver + :project: OpenMOC + :members: diff --git a/docs/source/api/timer.rst b/docs/source/api/timer.rst new file mode 100644 index 000000000..c31edbbe6 --- /dev/null +++ b/docs/source/api/timer.rst @@ -0,0 +1,9 @@ +.. _timer: + +===== +Timer +===== + +.. doxygenclass:: Timer + :project: OpenMOC + :members: diff --git a/docs/source/api/track.rst b/docs/source/api/track.rst new file mode 100644 index 000000000..59d02f485 --- /dev/null +++ b/docs/source/api/track.rst @@ -0,0 +1,9 @@ +.. _track: + +===== +Track +===== + +.. doxygenclass:: Track + :project: OpenMOC + :members: diff --git a/docs/source/api/trackgenerator.rst b/docs/source/api/trackgenerator.rst new file mode 100644 index 000000000..16b93e7f4 --- /dev/null +++ b/docs/source/api/trackgenerator.rst @@ -0,0 +1,9 @@ +.. _trackgenerator: + +============== +TrackGenerator +============== + +.. doxygenclass:: TrackGenerator + :project: OpenMOC + :members: diff --git a/docs/source/api/universe.rst b/docs/source/api/universe.rst new file mode 100644 index 000000000..4c48c5b31 --- /dev/null +++ b/docs/source/api/universe.rst @@ -0,0 +1,9 @@ +.. _universe: + +======== +Universe +======== + +.. doxygenclass:: Universe + :project: OpenMOC + :members: diff --git a/docs/source/api/vectorizedprivatesolver.rst b/docs/source/api/vectorizedprivatesolver.rst new file mode 100644 index 000000000..74f266a23 --- /dev/null +++ b/docs/source/api/vectorizedprivatesolver.rst @@ -0,0 +1,9 @@ +.. _vectorizedprivatesolver: + +======================= +VectorizedPrivateSolver +======================= + +.. doxygenclass:: VectorizedPrivateSolver + :project: OpenMOC + :members: diff --git a/docs/source/api/vectorizedsolver.rst b/docs/source/api/vectorizedsolver.rst new file mode 100644 index 000000000..2801b5fb4 --- /dev/null +++ b/docs/source/api/vectorizedsolver.rst @@ -0,0 +1,9 @@ +.. _vectorizedsolver: + +================ +VectorizedSolver +================ + +.. doxygenclass:: VectorizedSolver + :project: OpenMOC + :members: diff --git a/docs/source/api/xplane.rst b/docs/source/api/xplane.rst new file mode 100644 index 000000000..399a906c2 --- /dev/null +++ b/docs/source/api/xplane.rst @@ -0,0 +1,9 @@ +.. _xplane: + +====== +XPlane +====== + +.. doxygenclass:: XPlane + :project: OpenMOC + :members: diff --git a/docs/source/api/yplane.rst b/docs/source/api/yplane.rst new file mode 100644 index 000000000..6aa1d2c50 --- /dev/null +++ b/docs/source/api/yplane.rst @@ -0,0 +1,9 @@ +.. _yplane: + +====== +YPlane +====== + +.. doxygenclass:: YPlane + :project: OpenMOC + :members: diff --git a/docs/source/api/zplane.rst b/docs/source/api/zplane.rst new file mode 100644 index 000000000..98e50088d --- /dev/null +++ b/docs/source/api/zplane.rst @@ -0,0 +1,9 @@ +.. _zplane: + +====== +ZPlane +====== + +.. doxygenclass:: ZPlane + :project: OpenMOC + :members: diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 000000000..dfc149322 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +# +# metasci documentation build configuration file, created by +# sphinx-quickstart on Sun Feb 7 22:29:49 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('../sphinxext')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.pngmath'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'OpenMOC' +copyright = u'2012-2014, Massachusetts Institute of Technology' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = "0.1" +# The full version, including alpha/beta/rc tags. +release = "0.1.1" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = C++ + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +#pygments_style = 'sphinx' +#pygments_style = 'friendly' +#pygments_style = 'bw' +#pygments_style = 'fruity' +#pygments_style = 'manni' +pygments_style = 'tango' + + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +#html_theme = 'haiku' +html_theme = 'nature' +#html_theme = 'sphinxdoc' +#html_theme = 'pyramid' +#html_theme = 'agogo' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {'linkcolor': '#0c3762', + # 'visitedlinkcolor': '#0c3762'} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = ["_theme"] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = "OpenMOC Documentation" + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = '../img/openmoc-logo-sphinx-small.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'openmocdoc' + + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'openmoc.tex', u'OpenMOC Documentation', + u'Massachusetts Institute of Technology', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + +#Autodocumentation Flags +#autodoc_member_order = "groupwise" +#autoclass_content = "both" +#autosummary_generate = [] diff --git a/docs/source/developers.rst b/docs/source/developers.rst new file mode 100644 index 000000000..61189f3f8 --- /dev/null +++ b/docs/source/developers.rst @@ -0,0 +1,39 @@ +.. _developers: + +================ +Development Team +================ + + +`Massachusetts Institute of Technology`_ +---------------------------------------- + +- **Will Boyd** (@wbinventor) is a PhD candidate in MIT's NSE Department working on statistical inference-based acceleration methods for Monte Carlo neutron transport simulations. He has been involved with OpenMOC from the start, with a focus on parallel algorithms for multi-core and GPU platforms. + +* **Samuel Shaner** (@samuelshaner) is a PhD candidate in the NSE Department working on time-dependent methods for deterministic and stochastic neutron transport simulations. As part of the initial development team, he worked on implementing coarse mesh finite difference acceleration. + +- **Geoffrey Gunow** (@geogunow) is a PhD candidate in MIT's NSE Department working on implementing a 3D MOC solver into OpenMOC using an axially-quadratic source approximation. He joined the development team in June 2014 and co-authored SimpleMOC_, a mini-app that prototypes the performance of a 3D MOC solver. + +* **Nathan Gibson** (@PrezNattyGibbs) has been a member of the OpenMOC development team since the fall of 2013 and is a Ph.D. candidate in the NSE Department at MIT. His research focuses on using ultrafine energy discretization to account for self-shielding effects. He is implementing these methods as well as legacy self-shielding methods into OpenMOC. + +- **Lulu Li** (@lilulu) is a PhD candidate in the NSE Department and has been involved with OpenMOC with her fellow grad students from the start. She developed a physics-based multi-grid acceleration method called Low-Order Operator (LOO) for OpenMOC, and is porting it to OpenMC_. + +* **Prof. Benoit Forget** is Associate Professor of Nuclear Science and Engineering at MIT. He leads research in a variety of reactor physics topics ranging from deterministic to stochastic methods and is a leading advisor for the OpenMOC development team. + +- **Prof. Kord Smith** is the Korea Electric Power Company (KEPCO) Professor of the Practice of Nuclear Science and Engineering at MIT. He is Chief Scientist for the DOE’s Office of Science, Center for Exascale Simulation of Advanced Reactors (CESAR), and a leading advisor for the OpenMOC development team. + +`Argonne National Laboratory`_ +------------------------------ + +* **Tim Shuo** (@theshuo) is a predoctoral appointee with the Center for Exascale Simulation of Advanced Reactors (CESAR) at Argonne National Laboratory. He has been working with performance profiling and scaling studies of OpenMOC. + +- **Dr. Andrew Siegel** is a scientist in the Division of Mathematics and Computer Science at ANL and a fellow at the Computation Institute at the University of Chicago. He is the Director of the DOE's Office of Science, Center for Exascale Simulation of Advanced Reactors (CESAR), and a leading advisor for the OpenMOC development team. + + +.. _Massachusetts Institute of Technology: http://web.mit.edu/ +.. _Argonne National Laboratory: http://www.anl.gov/ +.. _Benoit Forget: http://web.mit.edu/nse/people/faculty/forget.html +.. _Kord Smith: http://web.mit.edu/nse/people/faculty/smith.html +.. _Andrew Siegel: http://www.mcs.anl.gov/person/andrew-siegel +.. _OpenMC: https://mit-crpg.github.io/openmc/ +.. _SimpleMOC: https://github.com/ANL-CESAR/SimpleMOC diff --git a/docs/source/devguide/build_system.rst b/docs/source/devguide/build_system.rst new file mode 100644 index 000000000..57cae473d --- /dev/null +++ b/docs/source/devguide/build_system.rst @@ -0,0 +1,542 @@ +.. _build_sytem: + +=================== +Python Build System +=================== + +OpenMOC is built and installed using the Python distutils_ package, which is a standard package provided with all Python distributions. Some developers will find this to be an adjustment since this stands in contrast to the legacy make_ and cmake_ build systems used by many scientific simulation codes. The following sections will describe how a developer can interact with the build system for configuration management. + + +.. _configuration_file: + +------------------ +Configuration File +------------------ + +The primary options for the build and installation of OpenMOC are defined in the :file:`/OpenMOC/config.py` file. In particular, :file:`config.py` creates the `C/C++ Extensions`_ using distutils in the ``configuration`` class. The ``Extension`` class in the ``distutils.extension`` module defines all of the source code and compiler and linker options to create a `shared library`_ which can be imported into Python as module. The class attributes for the ``configuration`` class encapsulate the build options specified by the user at compile time (see :ref:`Build Configuration Options `) and are itemized in :ref:`Table 1 `. + +.. _table_configuration_attributes: + +================================= ============================== =========================================== +Class Attribute Type Default Value +================================= ============================== =========================================== +``cc`` string 'gcc' +``fp`` string 'single' +``with_ccache`` boolean False +``debug_mode`` boolean False +``profile_mode`` boolean False +``with_cuda`` boolean False +``with_numpy`` boolean True +``sources`` dictionary of strings C/C++/CUDA source files flags for each ``Extension`` object +``compiler_flags`` dictionary of strings Flags for each ``Extension`` object +``linker_flags`` dictionary of strings Flags for each ``Extension`` object +``shared_libraries`` dictionary of strings Libraries for each ``Extension`` object +``library_directories`` dictionary of strings Libraries for each ``Extension`` object +``include_directories`` dictionary of strings Includes for each ``Extension`` object +``macros`` dictionary of strings Macros for each ``Extension`` object +``extensions`` list of ``Extension`` objects +================================= ============================== =========================================== + +**Table 1**: Attributes for the ``configuration`` class. + +The class attributes each have default values corresponding to the configuration needed to build and install the ``openmoc`` module. The :file:`OpenMOC/setup.py` file instantiates a ``configuration`` class object and redefines the class attributes based on the command line options given at runtime. This process is discussed in greater detail in the :ref:`Setup File ` section. + +Once the build options have been defined for the ``configuration`` class, the :file:`setup.py` calls the ``setup_extension_modules(...)`` class method which instantiates one or more ``Extension`` class objects for each Python module the user wishes to build and install. + +For example, the following command would build and install the ``openmoc`` module using the default compiler (gcc) and with double precision:: + + python setup.py install --user --fp=double + +Similarly, the following command would build and install the ``openmoc`` module with default compiler (gcc), as well was the ``openmoc.cuda`` module, each with single precision and `debug symbols`_:: + + python setup.py install --user --with-cuda --sp=single --debug-mode + + +.. _setup_file: + + +---------- +Setup File +---------- + +The :file:`/OpenMOC/setup.py` file is used to execute the build and installation process for OpenMOC. The methodology and implementation to handle command line options, custom compilers and linkers, and the build and installation phase. + + +Command Line Options +-------------------- + +The :file:`setup.py` file first defines the ``custom_install`` class to override (subclass) the ``install`` class in the ``distutils.command.install`` module. In particular, the ``initialize_options(...)`` class method is used to initialize the default build options for the ``configuration`` class (see :ref:`Configuration File `). The ``finalize_options(...)`` routine extracts the command line options, initializes the corresponding ``configuration`` class attributes, and calls the ``configuration.setup_extension_modules()`` class method to create the distutils ``Extension`` object. + + +Custom Compilers and Linkers +---------------------------- + +The ``customize_compiler(...)`` method is used to override the ``_compile(...)`` method in distutils to allow for compilation with a variety of toolchains (*e.g.*, ``gcc``, ``icpc``, etc.). As presently implemented, the method chooses a compiler based on the macro definitions in the compile line (i.e, ``gcc`` for the macro definition :envvar:`-DGNU`). Likewise, the ``customize_linker(...)`` method is used to override the ``link(...)`` method in distutils to allow for linking with a variety of toolchains (*e.g.*, ``g++``, ``icpc``, etc.). The method chooses an executable for linking based on the target shared library name. + +The ``custom_build_ext(...)`` class is used to override (subclass) the ``build_ext`` class in the ``distutils.command`` module. In particular, this class overrides the ``build_extension(...)`` method and uses it for the following: + +- Inject the ``customize_compiler(...)`` and ``customize_linker(...)`` methods into the ``build_ext`` class +- Call SWIG to generate Python wrappers for the C/C++ source code. + + +Building and Installation +------------------------- + +In the final step, the ``setup(...)`` method from the ``distutils.core`` module is called in the ``setup.py`` file. The ``setup(...)`` method receives the list of the ``Extension`` class objects and builds and installs each one as a shared library in the :file:`/home//.local/lib/python-x.x/site-packages/` directory. On a Unix-based machine, the shared library for the default ``openmoc`` module will be ``_openmoc.so``. The Python modules in OpenMOC (*e.g.*, ``openmoc.materialize``, ``openmoc.plotter``, etc.) will be installed in the :file:`/home//.local/lib/python-x.x/site-packages/` directory. + + +-------------------- +SWIG Interface Files +-------------------- + +OpenMOC uses the SWIG system (discussed in :ref:`Simplified Wrapper Interface Generator `) to generate Python bindings for classes and routines in the compiled C/C++ source code. In order for SWIG to work, the C/C++ header files **must contain all of the class and function prototypes.** Furthermore, the headers files must be exposed to SWIG through a `SWIG interface file`_ (see :ref:`SWIG Input `). OpenMOC includes the interface file :file:`/OpenMOC/openmoc/openmoc.i` for the main ``openmoc`` Python module, and an interface file :file:`/OpenMOC/openmoc/cuda/openmoc_cuda.i` for the ``openmoc.cuda`` module. + +The :ref:`Add a C/C++ Source File ` section discusses how to add new C/C++ source files and expose them to SWIG through the interface files. The interface files are useful for a variety of auxiliary purposes as well, most notably the specifications to input and retrieve NumPy_ data from the compiled C/C++ shared library object(s) from Python (see :ref:`NumPy Typemaps `). + + +-------------------- +Common Modifications +-------------------- + +The following sections cover some of the most common modifications and extensions that many developers need as they incorprate new features into OpenMOC, including how to add new C/C++ source files, Python modules, C/C++ extension modules and more. + + +.. _add_source_file: + +Add a C/C++ Source File +----------------------- + +There are three steps which must be taken to integrate a new source C/C++ file into the build system for OpenMOC. + +1. Include source header file (``.h``) in top of SWIG interface file (*e.g.* :file:`/OpenMOC/openmoc/openmoc.i`) using the following code syntax: + + .. code-block:: none + + #include "../src/MyFile.h" + +2. Include source header file (``.h``) in bottom of SWIG interface file (*e.g.* :file:`/OpenMOC/openmoc/openmoc.i`) using the following code syntax: + + .. code-block:: none + + %include ../src/MyFile.h + +3. Append the source implementation file (``.c``, ``.cpp``, ``.cu``, etc.) to the ``sources`` attribute for the ``configuration`` class in the :file:`/OpenMOC/config.py` file (see :ref:`Configuration File `). + +.. note:: Changes to the C/C++ source files are not reflected until the OpenMOC has been reinstalled. + + +Add a Python Module +------------------- + +OpenMOC includes several Python modules by default (i.e., ``openmoc.materialize``, ``openmoc.plotter``, etc.). These modules are Python files located in the :file:`/OpenMOC/openmoc` directory and are installed each time the C/C++ extension module(s) for OpenMOC are built and installed. For example, to create the ``openmoc.mymodule`` module, create the :file:`mymodule.py` file in the :file:`OpenMOC/openmoc` directory. You must then append the name of the module (*i.e.*, ``openmoc.mymodule``) to the ``packages`` list class attribute in the ``configuration`` class in the :file:`/OpenMOC/config.py` file. + +.. note:: Changes to a Python module are not reflected until OpenMOC has been reinstalled. + + +Add a Compiler Flag +-------------------- + +In order to add a new compiler flag to OpenMOC, simply append it as a Python string to the ``compiler_flags`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``compiler_flags`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the compiler flag is applicable to and append the string to the list corresponding to that key. For example, to add the :option:`-falign-functions` flag for ``gcc``, append '-falign-functions' to the list in ``compiler_flags`` corresponding to 'gcc'. + + +Add a Linker Flag +----------------- + +In order to add a new linker flag to OpenMOC, simply append it as a Python string to the ``linker_flags`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``linker_flags`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the linker flag is applicable to and append the string to the list corresponding to that key. For example, to add the :option:`-dynamiclib` flag for ``gcc``, append '-dynamiclib' to the list in ``linker_flags`` corresponding to 'gcc'. + +Add a Library Directory +----------------------- + +In order to add a new library directory to OpenMOC, simply append it as a Python string to the ``library_directories`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``library_directories`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the library directory is applicable to and append the string to the list corresponding to that key. For example, to add the :option:`/usr/local/cuda/lib` include directory for ``nvcc``, append '/usr/local/cuda/lib' to the list in ``library_directories`` corresponding to 'gcc'. + +You do not need to add a library directory if it is already in included in your :envvar:`LD_LIBRARY_PATH` environment variable. You can check if the directory is included with the following command from a Linux or Mac bash console: + +.. code-block:: bash + + $ echo $LD_LIBRARY_PATH + +To include the directory in :envvar:`LD_LIBRARY_PATH` instead of the :file:`config.py` file, use the following command from a Linux or Mac bash console: + +.. code-block:: bash + + $ export LD_LIBRARY_PATH=/my/library/directory/here:$LD_LIBRARY_PATH + + +Add an Include Directory +------------------------ + +In order to add a new include directory to OpenMOC, simply append it as a Python string to the ``include_directories`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``include_directories`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the include directory is applicable to and append the string to the list corresponding to that key. For example, to add the :option:`/usr/local/cuda/include` include directory for ``gcc``, append '/usr/local/cuda/include' to the list in ``include_directories`` corresponding to 'gcc'. + + +Link a Shared Library +--------------------- + +In order to link OpenMOC to a shared library, simply append the library name as a Python string to the ``shared_libraries`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``shared_libraries`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the shared library is applicable to and append the string to the list corresponding to that key. For example, to add the :option:`gomp` shared library for ``gcc``, append 'gomp' to the list in ``shared_libraries`` corresponding to 'gcc'. + +.. warning:: Do **NOT** prepend "l" or "lib" to the shared library as is typical for most compilers. Python distutils will automatically do this for you. + + +Add a Macro Definition +---------------------- + +In order to add a C/C++ pre-processing macro option to OpenMOC, simply append the macro as a Python tuple to the ``macros`` attribute of the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The ``macros`` attribute is a Python dictionary (see :ref:`Configuration File `) with keys for each compiler supported by the build system. Simply choose which compiler the macro is applicable to and append the tuple to the list corresponding to that key. For example, to add the :option:`METHOD=fast` macro for ``gcc``, append the ``('METHOD', 'fast')`` tuple to the list in ``macros`` corresponding to 'gcc'. + + +---------------------------- +Add a C/C++ Extension Module +---------------------------- + +Many developers may write new C/C++ source code which performs some new physics or compute-intensive task. In some cases, the new code may be applicable for some users but less desirable for others. Alternatively, the code may only be applicable for certain types of simulations and less so for others. In these situations, it may be best to include the new C/C++ source code as a new extension module to OpenMOC. The following section discuses the steps which must be taken (in order) to incorporate a new extension module into OpenMOC's build system. + + +Create New SWIG Interface File +------------------------------ + +The first step to creating a new extension module is to create new SWIG interface file for the module. Interface files and some SWIG capabilities are discussed in more detail in :ref:`Simplified Wrapper Interface Generator `. In this section, it suffices to say that if you wish to create the ``openmoc.submodule`` extension module, you will need to create the :file:`openmoc_submodule.i` interface file akin to what is illustrated below: + +.. code-block:: none + + %module openmoc_submodule + + %{ + + #define SWIG_FILE_WITH_INIT + + /* Include all header files to wrap here */ + #include "first_source_file.h" + ... + #include "last_source_file.h" + %} + + /* Include all header files to wrap here */ + %include first_source_file.h + ... + %include last_source_file.h + + +Add Source Files +---------------- + +Second, you need to create a new entry in the ``sources`` dictionary attribute for the ``configuration`` class in the :file:`/OpenMOC/config.py` file. The entry should contain a list of the C/C++ source files to compile, including the :ref:`SWIG wrap file `. An example of what might be appended to the ``configuration`` class is illustrated below + +.. code-block:: python + + # Store list of C/C++ source files for the module + sources['submodule'] = ['submodule_wrap.cpp', + 'first_source_file.cpp', + ... + 'last_source_file.cpp'] + +.. _add_build_options: + +Add Build Options +----------------- + +Next, you must create new entries in the ``configuration`` class attributes for compiler flags, linker flags, etc. in the :file:`/OpenMOC/config.py` file. Each of these build options is stored as a Python dictionary. Some of your build options may be identical to those for one or more of the main extension modules for OpenMOC. An example of what might be appended to the ``configuration`` class is illustrated below: + +.. code-block:: python + + # Store build options for the module + + # Compiler flags + compiler_flags['submodule'] = ['-first-option', ... , '-last-option'] + + # Linker flags + linker_flags['submodule'] = ['-first-option', ... , '-last-option'] + + # Shared libraries (do not prepend "l" or "lib") + shared_libraries['submodule'] = ['-firstlib', ..., '-lastlib'] + + # Library directories (if not set in LD_LIBRARY_PATH) + library_directories['submodule'] = ['/first/library/directory', + ... + '/second/library/directory'] + + # Include directories + include_directories['submodule'] = ['/first/include/directory', + ... + '/second/include/directory'] + + + # Define new macros as with tuples for each + macros['submodule'] = [('FIRST_MACRO', None), + ... + ('LAST_MACRO', 42)] + +Add a Build Option +------------------ + +In order to make your ``openmoc.submodule`` extension module an optional module for OpenMOC, you need to add a build option (or flag). The build options are defined and interpreted by the ``custom_install`` class in the :file:`/OpenMOC/setup.py` file. There are three primary steps which must be taken in order to add a build option. + +1) First, append your option to the ``user_options`` list attribute in the ``custom_install`` class. The ``user_options`` list contains tuples of three elements each. The first element is the option string name, the second element is typically ``None``, and the third element is a brief description of the option to be printed for the ``--help`` option. An example of the creation of the :option:`--newopt` option which can be assigned a numerical or string value from the command line is given as follows: + + .. code-block:: python + + user_options = [..., + ('newopt=', None, 'A new option which takes a string or numerical value'), + ...] + +2) Alternatively, if your option is a boolean option - for example, a binary switch to turn on/off the compilation of your ``openmoc.submodule`` extension module - you will need to define it in the ``boolean_options`` list attribute in the ``custom_install`` class: + + .. code-block:: python + + boolean_options = [... + 'newopt', + ...] + +3) Create a class attribute corresponding to your build option to the ``custom_install`` class in the :file:`/OpenMOC/setup.py` file. The class attribute should have the same name and capitalization as the command line option. This should be done in the ``initialize_options(...)`` class method. An example is given for the boolean option case as follows: + + .. code-block:: python + + def initialize_options(self): + + install.initialize_options(self) + + ... + + Set a default value for the new build option + self.newopt = False + +4) Inform the ``configuration`` class (given by the global ``config`` variable in ``setup.py``) to use the value passed in for the build option. This may entail creating a new class attribute for the ``configuration`` class in the :file:`/OpenMOC/config.py` file to account specifically for this option. + + .. code-block:: python + + def finalize_options(self): + + install.finalize_options(self) + + ... + + # Tell the configuration class what to do with the option + config.newopt = self.newopt + +Once the build option is given to the ``configuration`` class, it is up to you to figure out what to do with it. The command line options are typically applied to the build configuration in the ``setup_extension_modules`` method for the ``configuration`` class in the :file:`/OpenMOC/config.py` file as presented in the next section. + + +Inject Compiler Options +----------------------- + +Although you created a list of compiler flags for your module in :ref:`Add Build Options `, they will not be used unless we expose them to the underlying distutils build system. We do this using the ``customize_compiler(...)`` routine in the :file:`/OpenMOC/setup.py` file. This routine overrides the ``_compile(...)`` routine in distutils and allows us to configure the compiler executable and compiler flags as we please. In particular, ``customize_compiler`` defines a new version of the ``_compile(...)`` method and *injects* it into distutils. + +In order to ensure that distutils will use your compiler flags, you need to add a new conditional block to the ``_compile(...)`` method. This conditional should be able to determine when the ``_compile(...)`` method has received the build information for your extension module through its parameter set. One way to do this is to assign a specific macro to your build module which can be found in the ``pp_opts`` (pre-processing options) parameter to the ``_compile(...)`` method. for example, if you add a macro :envvar:`FIRST_MACRO` which is unique and only used for your extension module, then you can look for it in ``pp_opts`` and configure the compiler when needed. An example of how this might be done in the ``_compile(...)`` routine is shown as follows: + +.. code-block:: python + + # If we find your macro, distutils is building your module + if '-DFIRST_MACRO' in pp_opts: + + # Set the compiler executable to the compiler + # you want to use for your module + self.set_executable('compiler_so', 'gcc') + + # Set the compiler flags + postargs = config.compiler_flags['gcc'] + + +Append Module to Installation Packages +-------------------------------------- + +Next, you must append the name of the module (*i.e.*, ``openmoc.submodule``) to the ``packages`` list class attribute in the ``configuration`` class in the :file:`/OpenMOC/config.py` file. This will ensure that your new extension module will not only be compiled, but also installed into the directory with the rest of the OpenMOC shared library extension module(s) and Python modules. An example is as follows: + +.. code-block:: python + + packages = ['openmoc', ..., 'openmoc.materialize', ..., 'openmoc.submodule'] + + +Create SWIG Wrap File +--------------------- + +Your extension module C/C++ source files must be "wrapped" using SWIG to create a SWIG "wrap file." The distutils package will automatically do this for most Python distributions, but in some cases it is not done properly. To account for the inconsistencies across platforms, the OpenMOC build system manually calls SWIG for each extension module we wish to build at compile time. In particular, the ``custom_build_ext(...)`` routine in the :file:`/OpenMOC/setup.py` file is used to directly call SWIG to wrap the source code for each extension module. An example of what one might append to the ``custom_build_ext(...)`` routine to wrap the source for the ``openmoc.submodule`` extension module might be the following: + +.. code-block:: python + + if 'submodule' in config.extensions: + os.system('swig -python -c++ -keyword -o ' + \ + 'openmoc/submodule/openmoc_submodule_wrap.cpp ' + \ + 'openmoc/submodule/openmoc_submodule.i') + + +Create an Extension Object +-------------------------- + +The final step is to create an ``Extension`` object for your module in the ``setup_extension_modules(...)`` class method in the ``configuration`` class. The particular setup of your module is highly dependent on the functionality of your module and the build options added in the preceding steps. That said, there are several common issues to note when creating the ``Extension`` object. + +First, the filename should begin with an underscore "_" since this is common practice for Python C/C++ extension modules. Second, the ``name`` parameter should be set to the filename of the shared library you wish to create. Typically, it is recommended that the shared library filename be constructed using the same words intended for the Python module, with "." replaced by "_". For example, to create the ``module.submodule.subsubmodule`` C/C++ extension module for Python, the shared library should be called :file:`_module_submodule_subsubmodule.so`. Finally, each of the parameters to the ``Extension`` object should be set using the lists of build options (*i.e.*, compiler flags, include libraries, etc.) configured in :ref:`Add Build Options `. + +An example of how one might instantiate the ``Extension`` object in the ``setup_extension_modules(...)`` routine is given below: + +.. code-block:: python + + # Create Extension object and append to the list of objects + # in the configuration class + if config.submodule: + + self.extensions.append( + Extension(name = '_openmoc_submodule', + sources = self.sources['submodule'], + library_dirs = self.library_directories['submodule'], + libraries = self.shared_libraries['submodule'], + extra_link_args = self.linker_flags['submodule'], + include_dirs = self.include_directories['submodule'], + define_macros = self.macros['submodule'][self.fp], + swig_opts = self.swig_flags, + export_symbols = ['init_openmoc'])) + +.. _python_package_tree: + +Python Package Tree +------------------- + +Finally, you will need to create a directory tree to represent your module within the OpenMOC `Python package`_. For example, for the ``openmoc.submodule`` extension module, you would need to create the :file:`/OpenMOC/openmoc/submodule` directory. In addition, you will need to create a Python :file:`__init__.py` file, which is required for Python to treat the directory as a Python package. For a C/C++ extension module, the :file:`__init__.py` file typically will import the shared library (*i.e.*, :file:`_openmoc_submodule.so`) as follows: + +.. code-block:: python + + import _openmoc_submodule + + # Do any other initialization needed when + # someone imports your module into Python + ... + +.. note:: You must create an :file:`__init__.py` file for each level of the Python package hierarchy. For example, for the ``openmoc.submodule.subsubmodule``, you will need to create the :file:`/OpenMOC/openmoc/submodule/__init__.py` and :file:`/OpenMOC/openmoc/submodule/subsubmodule/__init__.py` files. + + +Build the Extension Module +-------------------------- + +FINALLY, you should be prepared to compile and install your C/C++ extension module using OpenMOC's distutils-based build system!! The next step is to build OpenMOC as discussed in :ref:`Installation and Configuration `, using the build option(s) which you defined for your module. For example, if you defined the build option :option:`--newopt` as a binary option for building your module, you might run the following in the console: + +.. code-block:: bash + + $ python setup.py install --user --newopt + +This command should compile and install your shared library extension module in :file:`/home//.local/lib/pythonX.X/site-packages/` directory. In particular, you should be able to find the :file:`_openmoc_submodule.so` file in that directory, as well as the import directory tree for the module as presented in :ref:`Python Package Tree ` (*i.e.*, :file:`/openmoc/submodule/` with the :file:`__init__.py` file). + +If all was properly configured as described in the preceding steps, you should be able to import your extension module into Python with the following: + +.. code-block:: python + + from openmoc.submodule import * + + # Do cool things with your extension module here + ... + +============================ +Alternative C++ Build System +============================ +Some developers might not wish to include the Python/SWIG build system due to the additional requirements such as SWIG_, Python_, Numpy_, matplotlib_, and h5py_. Since OpenMOC source code is entirely written in C++, it is possible to bypass the Python/SWIG build system and run OpenMOC using a compiled C++ input file. This is primarily useful for developers running OpenMOC on new architectures that might not support Python and SWIG. Performance analysis can also be easier without the Python/SWIG interface. + +.. note:: It is **highly** recommended that users utilize the regular Python/SWIG build system unless there is a specific reason for using the alternative C++ build system. + +-------- +Makefile +-------- + +The alternative C++ build system is available in the :file:`OpenMOC/profile/` +directory. +The build system depends on the source files found in the :file:`OpenMOC/src/` +directory so that any changes to those files are noticed by both the regular +Python/SWIG build system and the alternative C++ build system. +The alternative C++ build system is based on the use of Make_. +Since OpenMOC includes some C++11 features, developers should ensure +the C++ compiler they wish to use includes full C++11 support. Developers using +the alternative C++ build system should be familiar with both C++ and Make_. + +The alternative C++ build system compiler options are included in +:file:`OpenMOC/profile/Makefile`. This Makefile includes several command line +options that can be executed from the :file:`OpenMOC/profile/` directory: + + * **make** - Compiles the OpenMOC source files with the C++ input file + indicated by the ``case`` variable in the Makefile. The default is + :file:`OpenMOC/profile/models/c5g7/c5g7-cmfd.cpp`. + * **make all** - Compiles the OpenMOC source files with all input + files given in the Makefile indicated in the variable ``cases``. + * **make run** - Runs the OpenMOC C++ input file indicated by the ``case`` + variable in the Makefile. Note: the case must be compiled before this + command will run correctly. + * **make clean** - Deletes all output files formed from compiling OpenMOC source + and input files described in the ``cases`` variable in the Makefile. + +------------------------ +Building C++ Input Files +------------------------ + +It is advised to first compile the included example C++ inputs provided in the +:file:`OpenMOC/profile/models/` directory. After ensuring the inputs compile and +verifying correct behavior runtime behavior, the developer should use the example +C++ inputs as a reference to write new C++ input files. Most OpenMOC commands +should translate reasonably well between Python on C++ inputs, though some +aspects such as array declaration are much more difficult in C++. It is important +to note that ``Material``, ``Cell``, ``Universe``, and ``Lattice`` objects +should be allocated on the heap rather than the stack to prevent segmentation +faults when the program terminates. For instance, while + +.. code-block:: cpp + + Cell basic_cell(0, "basic cell"); + Universe basic_universe(0, "basic universe"); + basic_universe.addCell(&basic_cell); + Geometry geometry; + geometry.setUniverses(1, 1, &basic_universe); + +would seem like correct syntax, a segmentation fault would occur at the end of +the program execution when the geometry destructor is called since it deletes +all member universes. Likewise, universes delete all member cells. The correct +way of writing this code block to prevent this error would be to allocate +``basic_cell`` and ``basic_universe`` on the heap as: + +.. code-block:: cpp + + Cell* basic_cell = new Cell(0, "basic cell"); + Universe* basic_universe = new Universe(0, "basic universe"); + basic_universe->addCell(basic_cell); + Geometry geometry; + geometry.setUniverses(1, 1, basic_universe); + +---------------- +Compiler Options +---------------- + +Once the C++ input file is completed, it should be added to the Makefile to be +compiled. To do this, add the location of the C++ input file to the ``cases`` +variable in the Makefile. Note that the Makefile assumes input files are located +in a sub-directory of the :file:`OpenMOC/profile/models/` directory. Therefore, +the Makefile adds :file:`models/` as a prefix to any input file locations. +In addition, several compiler options can be specified at the top of the +Makefile, presented as variables detailed in :ref:`Table 2 `. + +.. _table_makefile_options: + +========================= =============================================== ============================== ========================= +Variable Description Allowed Values Default Value +========================= =============================================== ============================== ========================= +``COMPILER`` Specifies the compiler gnu, intel, clang, bluegene gnu +``OPENMP`` Flag to turn on OpenMP parallelism yes, no yes +``OPTIMIZE`` Flag to turn on compiler optimizations yes, no yes +``DEBUG`` Flag to turn on vector reports and debug mode yes, no no +``PROFILE`` Creates a :file:`gmon.out` file for profiling yes, no no +``PRECISION`` Specifies the floating point precision single, double single +========================= =============================================== ============================== ========================= + +**Table 2**: Makefile compiler options for the alternative C++ build system. + + +After the input is compiled, an executable will be created in the same directory +as the input file. The executable can be called directly based on its location +or it can be run using the **make run** command described previously with a +modification of the ``case`` variable in the Makefile. + + +.. _distutils: http://docs.python.org/2/library/distutils.html +.. _make: http://www.gnu.org/software/make/ +.. _cmake: http://www.cmake.org/ +.. _C/C++ Extensions: http://docs.python.org/2/extending/building.html +.. _shared library: http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html +.. _debug symbols: http://en.wikipedia.org/wiki/Debug_symbol +.. _SWIG interface file: http://www.swig.org/Doc2.0/SWIGDocumentation.html#Introduction_nn6 +.. _NumPy: http://www.numpy.org +.. _Python package: http://docs.python.org/2/tutorial/modules.html#packages +.. _SWIG: http://www.swig.org/ +.. _NumPy: http://www.numpy.org/ +.. _matplotlib: http://matplotlib.org/ +.. _h5py: http://www.h5py.org/ +.. _Make: http://www.gnu.org/software/make/ diff --git a/docs/source/devguide/debugging.rst b/docs/source/devguide/debugging.rst new file mode 100644 index 000000000..cd14997b2 --- /dev/null +++ b/docs/source/devguide/debugging.rst @@ -0,0 +1,420 @@ +.. _debugging: + +================= +Debugging OpenMOC +================= + +This section describes some recommended debugging techniques for developers working with OpenMOC source code. Although many novice code developers are accustomed to use **printf debugging** with the ``printf(...)`` C/C++ routing. The printf debugging methodology is **highly discouraged** since it leads to a very long debug iteration cycle between source code revision, compilation, and testing. Instead, developers are advised to use some form of a debug environment for C/C++ and/or Python. + +In particular, this section describes **GNU debugger** ``gdb`` in detail with some basic examples of how to use it with the shared library C++ extension module that is built for OpenMOC. In addition, some debugging techniques for the Python source are overviewed. + +---------------------- +The GNU Debugger (GDB) +---------------------- + +The `GNU Project Debugger`_ (GDB) provides the free open source ``gdb`` program for debugging of programs written in C/C++ (and other languages). The GNU debugger is typically installed when the GNU compiler collection (*e.g.*, ``gcc``, ``g++``) is installed. However, if for some reason you do not have ``gdb``, you may install it in Ubuntu using the ``apt-get`` package manager as follows: + +.. code-block:: none + + sudo apt-get install gdb + +Likewise, the GNU debugger can be installed using MacPorts on machines running Mac OS X as follows: + +.. code-block:: none + + sudo port install gdb + +There are a number of different ways to use to use and interact with GDB. There are a variety of graphical user interfaces for GDB, including DDD_ and `Eclipse CDT`_ which may be helpful for advanced code developers. This section, however, will focus on using the command line interface to GDB via the console. + + +--------------------------- +Debugging C/C++ Source Code +--------------------------- + +The majority of the compute-intensive code in OpenMOC is written in C/C++ as a compiled back-end shared library. This section overviews some of the key steps to using GDB to debug OpenMOC's C/C++ source code. By no means does this section cover all of GDB's capabilities. Advanced developers should consult one of the many outlets for GDB documentation available online, including the following + +* `Official GDB Documentation`_ +* `GNU GDB Debugger Command Cheat Sheet`_ +* `The Art of Debugging`_ +* `Debugging with GDB`_ + + +Installing OpenMOC with Debug Symbols +------------------------------------- + +In order to debug OpenMOC C/C++ source code, you must build and install the C/C++ extension module for Python with `debug symbols`_. This is easily done by appending the :option:`-g` command line option for the ``gcc`` compiler. The build system for OpenMOC can automatically append this flag for the compilation process with the :option:`--debug-mode` option: + +.. code-block:: none + + python setup.py install --user --debug-mode + + +Starting GDB +------------ + +The GNU Debugger may be started from the console with the ``gdb`` command: + +.. code-block:: none + + $ gdb + GNU gdb (GDB) 7.5-ubuntu + Copyright (C) 2012 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. Type "show copying" + and "show warranty" for details. + This GDB was configured as "x86_64-linux-gnu". + For bug reporting instructions, please see: + . + (gdb) + +If you are debugging code written for the GPU, the CUDA GNU Debugger should be used: + +.. code-block:: none + + $ cuda-gdb + NVIDIA (R) CUDA Debugger + 5.5 release + Portions Copyright (C) 2007-2013 NVIDIA Corporation + GNU gdb (GDB) 7.2 + Copyright (C) 2010 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. Type "show copying" + and "show warranty" for details. + This GDB was configured as "x86_64-unknown-linux-gnu". + For bug reporting instructions, please see: + . + (cuda-gdb) + +The CUDA GDB debugger oftentimes does not fail at the exact location of the error, so it is recommended to turn cuda memcheck on: + +.. code-block:: none + + (cuda-gdb) set cuda memcheck on + +These commands will leave you in an interactive session with GDB, complete with its own command line interface. From now on we will give all examples with gdb, but the same commands apply for cuda-gdb. + + +Initializing Python +------------------- + +From within the interactive GDB session, you must inform GDB that you plan to use Python as your binary executable: + +.. code-block:: none + + (gdb) file python + Reading symbols from /usr/bin/python...Reading symbols from /usr/lib/debug/usr/bin/python2.7...done. + + +Running Python in GDB +--------------------- + +Next you can select a Python file to execute using the ``run`` command with the Python script as the argument. For example, to run the :file:`/OpenMOC/sample-input/simple-lattice/simple-lattice.py` from within GDB, simply execute the following: + +.. code-block:: none + + (gdb) run simple-lattice.py -i 5 + Starting program: /usr/bin/python simple-lattice.py -i 5 + [Thread debugging using libthread_db enabled] + Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + [ NORMAL ] Importing materials data from HDF5... + [ NORMAL ] Creating surfaces... + [ NORMAL ] Creating cells... + [ NORMAL ] Creating simple 4 x 4 lattice... + [ NORMAL ] Creating geometry... + [ NORMAL ] Number of flat source regions: 60 + [ NORMAL ] Initializing the track generator... + [ NORMAL ] Returning from readTracksFromFile + [ NORMAL ] Computing azimuthal angles and track spacings... + [ NORMAL ] Generating track start and end points... + [ NORMAL ] Segmenting tracks... + [ NORMAL ] Initializing track boundary conditions... + [ NORMAL ] Converging the source... + [ NORMAL ] Iteration 0: k_eff = 1.000000 res = 0.000E+00 + [ NORMAL ] Iteration 1: k_eff = 1.270088 res = 2.594E+02 + [ NORMAL ] Iteration 2: k_eff = 1.290540 res = 4.797E-01 + [ NORMAL ] Iteration 3: k_eff = 1.309195 res = 1.919E-01 + [ NORMAL ] Iteration 4: k_eff = 1.318423 res = 1.680E-01 + [ WARNING ] Unable to converge the source after 5 iterations + [ TITLE ] ******************************************************************* + [ TITLE ] TIMING REPORT + [ TITLE ] ******************************************************************* + [ RESULT ] Total time to solution...............................3.9251E-03 sec + [ RESULT ] Solution time per unknown............................9.3454E-06 sec + [ RESULT ] Solution time per iteration..........................7.8502E-04 sec + [ RESULT ] Integration time per segment integration.............2.0098E-08 sec + [SEPARATOR] ------------------------------------------------------------------- + [ RESULT ] # tracks # segments # FSRs + [SEPARATOR] ------------------------------------------------------------------- + [ RESULT ] 116 930 60 + [SEPARATOR] ------------------------------------------------------------------- + [ NORMAL ] Plotting data... + [ TITLE ] ******************************************************************* + [ TITLE ] Finished + [ TITLE ] ******************************************************************* + [Inferior 1 (process 25820) exited normally] + (gdb) + +To obtain more information about program execution, GDB can be run in verbose mode using the :option:`-v` optional argument to the ``run`` command: + +.. code-block:: none + + (gdb) run -v simple-lattice.py + ... + [Inferior 1 (process 25820) exited normally] + (gdb) + + +Set Breakpoints +--------------- + +A **breakpoint** is an intentional stopping or pausing place in a program for debugging purposes. A breakpoint can be set using ``gdb`` using the ``breakpoint`` or ``br`` commands. The ``br`` command can be set at a specific line number in a specific source file. For example, if we wanted to run an OpenMOC program until the ``Material::setNumEnergyGroups(...)`` routine was called, we could set a breakpoint to the first line in that routine and then execute :file:`simple-lattice.py` as follows: + +.. code-block:: none + + (gdb) br Material.cpp:349 + No source file named Material.cpp. + Make breakpoint pending on future shared library load? (y or [n]) y + + Breakpoint 1 (Material.cpp:349) pending. + (gdb) run simple-lattice.py + Starting program: /usr/bin/python simple-lattice.py + [Thread debugging using libthread_db enabled] + Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + [ NORMAL ] Importing materials data from HDF5... + + Breakpoint 1, Material::setNumEnergyGroups (this=0x1b6ef80, num_groups=7) + at src/Material.cpp:349 + 349 if (num_groups < 0) + (gdb) + +As shown in the snippet above, the code executes until the breakpoint is reached and short summary of the source code is printed to the console. Alternatively, we could have set the breakpoint using the name of the routine instead: + +.. code-block:: none + + (gdb) br Material::setNumEnergyGroups + Function "Material::setNumEnergyGroups" not defined. + Make breakpoint pending on future shared library load? (y or [n]) y + + Breakpoint 1 (Material::setNumEnergyGroups) pending. + (gdb) run simple-lattice.py + Starting program: /usr/bin/python simple-lattice.py + [Thread debugging using libthread_db enabled] + Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + [ NORMAL ] Importing materials data from HDF5... + + Breakpoint 1, Material::setNumEnergyGroups (this=0x1b6ef80, num_groups=7) + at src/Material.cpp:347 + 347 void Material::setNumEnergyGroups(const int num_groups) { + (gdb) + +In each case, a breakpoint is set and the program is executed until that line is reached. The entire program state is stored and the execution is simply interrupted until further notice to GDB is given by the user. + + +Set Watchpoints +--------------- + +A **watchpoint** is a *conditional breakpoint*, or a breakpoint that is only reached when a certain condition is met. The condition may be the reading, writing, or modification of a specific location in memory. For example, if we wanted to watch the value of the ``Material::_num_groups`` private class attribute we could place a watchpoint on it. First, we might start gdb and place a breakpoint on the ``Material::setNumEnergyGroups(...)`` routine as shown in the preceding section. Then we could place a watchpoint as follows: + +.. code-block:: none + + (gdb) watch _num_groups + Watchpoint 2: _num_groups + (gdb) continue + Continuing. + Watchpoint 2: _num_groups + + Old value = 0 + New value = 7 + Material::setNumEnergyGroups (this=0x1b6ef80, num_groups=7) + at src/Material.cpp:358 + 358 if (_data_aligned) { + (gdb) + +As illustrated, GDB stepped through the program until ``_num_groups`` was modified or used and reported its value to the console. Note that this snippet made use of the ``continue`` command which is covered in th next section. At this point, it suffices to say that ``continue`` resumes program execution from a breakpoint until it a new breakpoint or watchpoint is reached. + +GDB provides a variety of method to `set watchpoints`_ during a program's execution. For example, instead of placing a watchpoint on ``_num_groups``, we could instead have placed a watchpoint on the condition that ``_num_groups`` > 0 as follows: + +.. code-block:: none + + (gdb) watch _num_groups > 0 + Watchpoint 2: _num_groups > 0 + (gdb) continue + Continuing. + Watchpoint 2: _num_groups > 0 + + Old value = false + New value = true + Material::setNumEnergyGroups (this=0x1b6ef80, num_groups=7) + at src/Material.cpp:358 + 358 if (_data_aligned) { + (gdb) + +In this case, the result of the conditional is reported to the screen. + + +Step through the Program +------------------------ + +This section highlights a few of the key commands which may be used to control program execution using GDB. + +* **Continue** + + The ``continue`` or ``c`` command is used to instruct GDB to continue program execution until the next breakpoint or watchpoint is reached (*i.e.*, useful for loops). An optional integer argument :option:`` may be given to ``continue`` to instruct GDB to ignore the current breakpoint some number of times. + + .. code-block:: none + + (gdb) continue + + +* **Step** + + The ``step`` or ``s`` command will step to the next line of code. If the next line of code is a function call, the ``step`` command **will** step into the function. An optional integer argument :option:`` may be given to ``step`` to instruct GDB to step through some number of lines. + + .. code-block:: none + + (gdb) step + + +* **Next** + + The ``next`` or ``n`` command will step to the next line of code. If the next line of code is a function call, the ``step`` command **will not** step into the function. An optional integer argument :option:`` may be given to ``next`` to instruct GDB to step through some number of lines (without entering functions). + + .. code-block:: none + + (gdb) next + + +* **Until** + + The ``until`` command will continue processing until reaching a specifed line number :option:``. This is akin to setting a breakpoint which is only used once and which is immediately deleted following its first use. + + .. code-block:: none + + (gdb) until + + +* **Where** + + The ``where`` command will show which line number you are at and which function you are in. + + .. code-block:: none + + (gdb) where + + +Examine Variables +----------------- + +The ``print`` or ``p`` command may be used to examine variables within some scope of the code with GDB. For example, if you were interested in the value of :option:`variable`, you might set a breakpoint at the entrance point to the code region of interest, and step through the region while printing the value as follows: + +.. code-block:: none + + (gdb) print variable + + +Report the Debugger State +------------------------- + +The ``info`` or ``i`` command may be used to report debugger state information to the console. For example, to list all breakpoints - including the file and line numbers where each is set - the ``info`` command is used with the :option:`breakpoints` option: + +.. code-block:: none + + (gdb) info breakpoints + +To list breakpoint numbers only, ``info`` command is used with the :option:`break` option: + +.. code-block:: none + + (gdb) info break + +Likewise, to list all watchpints, the ``info`` command is used with the :option:`watchpoints` option: + +.. code-block:: none + + (gdb) info watchpoints + + +Disable Breakpoints +------------------- + +The ``disable`` command is used to disable breakpoints with GDB. When a breakpoint is disabled, it is still retained by GDB but is not used during program execution. The ``enable`` command may be used to continue using the breakpoint again at a later time. The following illustrates how to cancel breakpoints 1, 3, 4, 5, and 6, and re-enable breakpoints 4 and 5: + +.. code-block:: none + + (gdb) disable 1 3-6 + (gdb) enable 4-5 + + +Printing the Stack +------------------ + +The ``backtrace`` or ``bt`` command may be used to show the trace of the function the program is currently in: + +.. code-block:: none + + (gdb) bt + +The ``backtrace`` command can be particularly useful when debugging `segmentation faults`_. In particular, GDB may be used to run the program until the segmentation fault is reached. At this point, the use of ``backtrace`` will print the function call stack, showing where the segmentation faul occurred. + + +Stop Program Execution +---------------------- + +The ``kill`` command may be used to stop a program's execution while keeping the GDB process running: + +.. code-block:: none + + (gdb) kill + + +Exiting GDB +----------- + +The ``quit`` or ``q`` command may be used to exit the ``gdb`` debugger and return to the console: + +.. code-block:: none + + (gdb) quit() + + +---------------------------- +Debugging Python Source Code +---------------------------- + +There are a a number of resources which one may use to debug Python code. Many popular `Integrated Development Environments`_ (IDEs) for Python include interactive visual debugging support, including `PyCharm`_, `Eclipse PyDev`_, and `Wing IDE`_. It is **highly recommended** that code developers use one of these IDEs for Python development and debugging. The `PyCharm`_ IDE is especially recommended for OpenMOC users developing input and data processing modules in Python. Although PyCharm is a commercial product, a community version is provided for free with many of the most essential features including the following: + +* Syntax highlighting +* Auto-indentation +* Code formatting +* Code completion +* Line/block commenting +* Refactoring +* Python interpreter +* Integrated debugger + +In addition, advanced developers should consult one of the many online outlets for documentation on debugging Python programs, including the following: + +* `Debugging in Python`_ +* `Interactive Debugging in Python`_ + + +.. _printf: http://www.cplusplus.com/reference/cstdio/printf/ +.. _GNU Project Debugger: https://www.gnu.org/software/gdb/ +.. _MacPorts: http://www.macports.org/ +.. _debug symbols: http://en.wikipedia.org/wiki/Debug_symbol +.. _DDD: http://www.gnu.org/software/ddd/ +.. _Eclipse CDT: http://www.eclipse.org/cdt/ +.. _Official GDB Documentation: http://www.gnu.org/software/gdb/documentation/ +.. _GNU GDB Debugger Command Cheat Sheet: http://www.yolinux.com/TUTORIALS/GDB-Commands.html +.. _The Art of Debugging: http://www.nostarch.com/debugging.htm +.. _Debugging with GDB: http://www.amazon.com/Debugging-GDB-The-Source-Level-Debugger/dp/1882114884 +.. _set watchpoints: https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html +.. _segmentation faults: http://en.wikipedia.org/wiki/Segmentation_fault +.. _Integrated Development Environments: http://en.wikipedia.org/wiki/Integrated_development_environment +.. _Pycharm: http://www.jetbrains.com/pycharm/ +.. _Eclipse PyDev: http://pydev.org/ +.. _Wing IDE: https://wiki.python.org/moin/Wing%20IDE +.. _Debugging in Python: http://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/ +.. _Interactive Debugging in Python: http://www.onlamp.com/pub/a/python/2005/09/01/debugger.html diff --git a/docs/source/devguide/documentation.rst b/docs/source/devguide/documentation.rst new file mode 100644 index 000000000..9da842c00 --- /dev/null +++ b/docs/source/devguide/documentation.rst @@ -0,0 +1,110 @@ +.. _documentation: + +============= +Documentation +============= + +The following describes the suggested steps that developers should take to edit, revise or add to OpenMOC's documentation. When new features are added to OpenMOC, the documentation located in :file:`/docs` should be updated in the same pull request as the new feature. OpenMOC uses the Sphinx_ tool for documentation due to its growing popularity for open source codes. Sphinx uses reStructuredText_ (rst) files to encapuslate text-based content with semantic markup for figures, tables, URLs, and more. Sphinx provides a compiler which parses the reStructuredText source files to generate a target output in the form of HTML or a PDF. OpenMOC also uses Doxygen_ for automated generated of Application Programming Interface (API) documentation based on source code comments. The use of Doxygen-style comments is explained further in :ref:`Code Comments `. + + +------------------------- +Preliminary Configuration +------------------------- + +First, in order to build OpenMOC's documentation, you must have installed both Sphinx and Doxygen. Since both tools are widely used, they are available with most source package system. On Debian-based systems, such as Ubuntu, you may install both tools with the following command in the console: + +.. code-block:: none + + sudo apt-get install python-sphinx doxygen + +Likewise, on Mac OS with MacPorts_ you may install each with the following command: + +.. code-block:: none + + sudo port install py27-sphinx doxygen + +These packages are all that is required to build and update the documentation in your pull request. Next, we will discuss how you can build and update the documentation when you modify the source code. + +------------------------- +Writing New Documentation +------------------------- + +This tutorial will not present any of the semantics of how to write documentation for Sphinx as that is well covered by its own tutorials. Likewise, the same is true for Doxygen-style comments, although the basics are presented in :ref:`Code Comments `. Instead, this section presents the location of the source code and the basic console commands used to generate HTML documentation. + +First, the :file:`/docs/source` directory contains the reStructuredText source for the Sphinx documentation. In order to compile the Sphinx documentation into HTML, you can run the following from within the :file:`/docs` directory: + +.. code-block:: none + + cd docs + make html + +This command will use the Sphinx tool to generate HTML in the :file:`/docs/build` directory. From within the :file:`/docs` directory, you may use a web browser, such as Mozilla Firefox, to view your newly generated documentation as follows: + +.. code-block:: none + + firefox build/html/index.html + +The reStructuredText source files that should be updated with each pull request are located in the :file:`/docs/source` directory. If developers wish to add new pictures to the documentation, image files should be added to the :file:`/docs/img` directory in either png or svg format. Developers can test out their changes to the documentation by recompiling the Sphinx documentation into HTML and viewing the updated HTML files. + +Likewise, in order to build a revised version of the :ref:`OpenMOC API ` from Doxygen-style comments in the Python and C++ source code, you may use the following console commands from within the :file:`/docs` directory: + +.. code-block:: none + + cd doxygen + doxygen Doxyfile + ./doxy2swig.py + +This will build a new version of the API in the :file:`/docs/doxygen/html` directory. In addition, the :file:`docs/doxy2swig.py` script will parse the Doxygen-style comments and generate Python docstring-equivalents in an updated :file:`openmoc/docstring.i` file for SWIG to inject into the :code:`openmoc` Python module. From within the :file:`/docs/doxygen` directory, you may use a web browser, such as Mozilla Firefox, to view your newly generated documentation as follows: + +.. code-block:: none + + firefox html/index.html + +Note that this procedure updates the documentation shipped with the source code in the **develop** branch, but changes will not be reflected in the documentation on the website. GitHub_ reserves the use of the **gh-pages** branch to host a project website for each repository. The **gh-pages** branch contains the documentation source code for the latest public release of OpenMOC and thus will only be periodically updated with the documentation from the **develop** branch. The procedure for updating the website documentation will be discussed in the next section. + +------------------------------------- +Version Control for New Documentation +------------------------------------- + +With each new release, the website documentation will be updated by one of the core developers with the latest documentation from the **develop** branch. In order to **expose** newly generated HTML documentation to GitHub such that it will present on the website, the Sphinx and Doxygen build files must be copied to the **gh-pages** branch. Once the documentation is ready to be copied over to the **gh-pages** branch, the Sphinx and Doxygen HTML files need to be built: + +.. code-block:: none + + cd docs + make html + cd doxygen + doxygen Doxyfile + cd ../.. + +Now that the HTML files have been built, you can checkout the **gh-pages** branch and then checkout a new branch to store the new version of the documentation: + +.. code-block:: none + + git checkout gh-pages + git checkout -b gh-pages-update + +You can then copy the files from the :file:`/docs` directory to the root OpenMOC directory on your new branch: + +.. code-block:: none + + cp -r docs/build/html/* . + cp -r docs/doxygen/html doxygen/ + +Since the :file:`.gitignore` file does not allow image and HTML files to be tracked, you will need to force all image and HTML files to be added to tracking history. The :file:`configure.sh` script contains the commands to add all the necessary files. The :file:`configure.sh` can be executed and the changes committed and pushed to GitHub: + +.. code-block:: none + + ./configure.sh + git commit -am 'my commit message here' + git push origin gh-pages-update + +The final step in updating the website documentation is to `pull request`_ to the ``gh-pages`` branch of the OpenMOC repository on GitHub as described in :ref:`Development Workflow `. + +.. note:: The diff for the pull request into **gh-pages** will likely be massive! The purpose of this pull request is not to conduct a code review, but rather to provide a transparent and publicly-available record of when the website documentation has been changed. + +.. _Sphinx: http://sphinx-doc.org/ +.. _reStructuredText: http://docutils.sourceforge.net/rst.html +.. _Doxygen: http://www.stack.nl/~dimitri/doxygen/ +.. _MacPorts: http://www.macports.org/ +.. _GitHub: https://github.com/mit-crpg/OpenMOC +.. _pull request: https://help.github.com/articles/using-pull-requests diff --git a/docs/source/devguide/index.rst b/docs/source/devguide/index.rst new file mode 100644 index 000000000..272890653 --- /dev/null +++ b/docs/source/devguide/index.rst @@ -0,0 +1,19 @@ +.. _devguide: + +================= +Developer's Guide +================= + +Welcome to the OpenMOC Developer's Guide! The Developer's Guide is a **must read** for those planning to contribute new code features to the OpenMOC open source project. This guide documents and explains the structure and design of the OpenMOC source code. The Guide discusses how SWIG is used to couple compiled C/C++ source code into a Python interface. In addition, the Python build system and techniques for debugging OpenMOC are presented. The Guide concludes with an overview of the coding style and development workflow used by the OpenMOC development team. + +.. toctree:: + :numbered: + :maxdepth: 2 + + software_design + swig + build_system + debugging + style_guide + documentation + work_flow diff --git a/docs/source/devguide/software_design.rst b/docs/source/devguide/software_design.rst new file mode 100644 index 000000000..b8b98649d --- /dev/null +++ b/docs/source/devguide/software_design.rst @@ -0,0 +1,77 @@ +.. _software_design: + +=============== +Software Design +=============== + +OpenMOC uses a compiled language coupled with a scripting language "glue" [Sanner]_, a methodology that has increasingly gained traction across disciplines since it enables both usability and performance. The majority of the source code is written in C/C++ as it is the most robust and well supported general purpose, high performance, compiled programming language with object-oriented features. In addition, OpenMOC's solver routines for the GPU are written in NVIDIA's CUDA programming language [CUDA]_ - a compiled language with similar syntax to C/C++. The widely adopted Simplified Wrapper Interface Generator (SWIG) [Beazley]_ is deployed to expose the C/C++/CUDA classes and routines to the Python scripting language. The model to couple the compiled C/C++/CUDA code to the Python scripting language is illustrated in :ref:`Figure 1 `. OpenMOC's Python interface allows for rapid prototyping and testing of code features and tight integration with the rich ecosystem of powerful data processing and visualization tools developed for Python. + +.. _figure_software_design: + +.. figure:: ../../img/openmoc-software-design.png + :align: center + :figclass: align-center + :width: 500px + + **Figure 1**: Programming model in OpenMOC. + +---------------------- +Object-Oriented Design +---------------------- + +OpenMOC is designed using the Object-Oriented (OO) programming paradigm, the standard for software development for over two decades. In OO programming, data structures called **classes** are used to encapsulate both attributes and subroutines. Object-oriented programming is powerful since it directly enables code generalization and requires the use of **trust boundaries** which lead to more resilient code. An OpenMOC simulation is created through the instantiation and manipulation of class objects. A complete listing of classes in OpenMOC is displayed in :ref:`Table 1 `. + +.. _table_classes: + + +=========================== ======================= ============================ +Class Parent Class Category +=========================== ======================= ============================ +``Surface`` N/A Constructive Solid Geometry +``Plane`` ``Surface`` Constructive Solid Geometry +``XPlane`` ``Plane`` Constructive Solid Geometry +``YPlane`` ``Plane`` Constructive Solid Geometry +``ZCylinder`` ``Surface`` Constructive Solid Geometry +``Cell`` N/A Constructive Solid Geometry +``Universe`` ``Universe`` Constructive Solid Geometry +``Lattice`` N/A Constructive Solid Geometry +``Geometry`` N/A Constructive Solid Geometry +``TrackGenerator`` N/A Ray Tracing +``Quadrature`` N/A Ray Tracing +``Material`` N/A Nuclear Data +``Solver`` N/A Method of Characteristics +``CPUSolver`` ``Solver`` Method of Characteristics +``GPUSolver`` ``Solver`` Method of Characteristics +``VectorizedSolver`` ``CPUSolver`` Method of Characteristics +=========================== ======================= ============================ + +**Table 1**: OpenMOC's classes. + + +-------------- +Python Modules +-------------- + +OpenMOC’s Python interface makes it relatively easy to create complicated simulation input. Generating input for an OpenMOC simulation does not involve writing an input file in the traditional sense. OpenMOC leverages the flexiblity provided by Python to allow users complete control to build their inputs in one or more scripts just as one may do for any Python program. The user imports the necessary OpenMOC modules (see :ref:`Table 2 `) into Python and “builds” a simulation using only those classes and routines which are needed. + + +.. _table_python_modules: + +======================= ====================================== +Module Description +======================= ====================================== +``openmoc`` The main module for OpenMOC +``openmoc.options`` Command line options +``openmoc.log`` Level-based logging messages +``openmoc.materialize`` Import/export multi-group nuclear data +``openmoc.plotter`` Visualizations for geometry, flux, etc. +``openmoc.process`` Data processing +``openmoc.cuda`` Solver for NVIDIA GPUs +======================= ====================================== + +**Table 2**: OpenMOC's Python modules. + + +.. [Sanner] M. Sanner, "Python: A Programming Language for Software Integration and Development." Journal of Molecular Graphics and Modelling, **17(1)**, pp. 57-61 (1999). +.. [CUDA] NVIDIA, "NVIDIA CUDA C Programming Guide." http://docs.nvidia.com/cuda/cuda-c-programming-guide/ (2013). +.. [Beazley] D. Beazley, "Automated Scientific Software Scripting with SWIG." Future Generation Computer Systems, **19(5)**, pp. 599-609 (2003). diff --git a/docs/source/devguide/style_guide.rst b/docs/source/devguide/style_guide.rst new file mode 100644 index 000000000..66faecdbd --- /dev/null +++ b/docs/source/devguide/style_guide.rst @@ -0,0 +1,321 @@ +.. _style_guide: + +======================= +Style Guide for OpenMOC +======================= + +In order to keep the OpenMOC code base consistent in style, this guide specifies +a number of rules which should be adhered to when modified existing code or +adding new code in OpenMC. + +------------- +General Rules +------------- + +* **Compilation** - Make sure code can be compiled with most common compilers, especially gcc and the Intel C++ compiler icpc. + +* **Dependencies** - Avoid using special extensions or libraries which add dependencies to the OpenMOC source. + +* **Code Comments** - Always include comments to describe what your code is doing. Do not be afraid of using copious amounts of comments. + + +------------------ +Source Code Syntax +------------------ + +The following describes some of the rules for source code syntax, including the class naming convention, rules for class methods and attributes as well as normal routines and variables. + + +Class Names +----------- +Class names are CamelCase_ starting with a **capital** letter and without **"_"** between words as illustrated in the C++ snippet below: + +.. code-block:: c + + /* Yes */ + class MyClass { + ... + }; + + /* No */ + class myClass { + ... + }; + + /* No */ + class My_Class{ + ... + }; + + +Class Methods +------------- +Class methods are camelCase_ starting with a **lowercase** letter and without **"_"** between words as illustrated in the Python snippet below: + +.. code-block:: python + + class MyClass: + + # Yes + def getterMethod(self): + ... + + # No + def Setter_Method(self): + ... + + # No + def logic_method(self): + ... + + +Class Attributes +---------------- +Class attributes are **private** and **lowercase** which start with **"_"** and with "_" between words as illustrated in the C++ snippet below: + +.. code-block:: c + + class MyClass { + + private: + + /* Yes */ + int _first_attribute; + + /* No */ + double second_attribute; + + /* No */ + float _ThirdAttribute; + + ... + + }; + + +Function Names +-------------- +Functions (not class methods) are all **lowercase** with **"_"** between words as illustrated in the Python snippet below: + +.. code-block:: python + + # Yes + def my_function(a, b): + ... + + # No + def myFunction(a, b): + ... + + # No + def My_Function(a, b): + ... + + +Variable Names +-------------- +Temporary variables (e.g. variables defined within the scope of a function) are **lowercase** with **"_"** between words as illustrated in the C/C++ snippet below: + +.. code-block:: c + + void my_function(int a, int b) { + + /* Yes */ + int first_variable; + + /* No */ + int secondVariable; + + /* No */ + int Second_Variable; + + ... + + } + + +.. _code_comments: + +------------- +Code Comments +------------- + +OpenMOC uses Doxygen_ for automated generation of Application Programming Interface (API_) documentation based upon code comments. Please adhere to the Doxygen standard for code comments in both C/C++ and Python source code. In particular, + +* **C/C++ functions** should be preceded by Doxygen-style comments as illustrated in the following code snippet: + +.. code-block:: c + + /** + * @brief Single precision A*X plus Y + * @details Multiplies single precision vectors a and x and + * adds vector y. The output vector is stored in y. + * @param n the size of the vectors x and y + * @param a a single precision vector of length n + * @param x a single precision vector of length n + * @param y a single precision vector of length n + */ + int saxpy(int n, float* a, float* x, float* y) { + for (int i=0; i`). The function prototypes are defined and will be wrapped by SWIG as described in the next section. + +.. code-block:: c + + /* File saxpy.h */ + #include + #include + + /* Define function prototypes */ + void set_array_length(int n); + void initialize_data(); + void free_data(); + void print_data(); + void saxpy(); + +The corresponding function implementations for the SAXPY example are given in the C++ source file :file:`saxpy.cpp` below (:download:`download <../../img/saxpy.cpp>`). + +.. code-block:: c + + /* File saxpy.cpp */ + #include "saxpy.h" + + /* Define global variables */ + int length; + double a; + double* x; + double* y; + + void set_array_length(int n) { + length = n; + } + + void initialize_data() { + + /* Allocate memory for arrays */ + x = (double*)malloc(length*sizeof(double)); + y = (double*)malloc(length*sizeof(double)); + + /* Initialize data with random numbers in [0,1] */ + a = float(rand()) / RAND_MAX; + + for (int i=0; i < length; i++) { + x[i] = float(rand()) / RAND_MAX; + y[i] = float(rand()) / RAND_MAX; + } + } + + void free_data() { + free(x); + free(y); + } + + void print_data() { + printf("a = %f\n", a); + + for (int i=0; i < length; i++) + printf("x[%d] = %f\ty[%d] = %f\n", i, x[i], i, y[i]); + } + + void saxpy() { + for (int i=0; i < length; i++) + y[i] = a * x[i] + y[i]; + } + + +.. _swig_input: + +SWIG Interface File +------------------- + +SWIG requires the use of **interface files** for input. A `SWIG interface file`_ is required for each `C/C++ extension module`_ generated for Python. The primary purpose for SWIG interface file(s) in OpenMOC is to expose the C/C++ source code to SWIG. This is done by including the header files which contain all of the function prototypes, class definitions, etc. for SWIG to wrap. In addition, the name of the module must be included at the top of the interface file. The following illustrates :file:`saxpy.i` interface file (:download:`download <../../img/saxpy.i>`) for the SAXPY example. + +.. code-block:: none + + %module saxpy + %{ + #include SWIG_FILE_WITH_INIT + #include "saxpy.h" + %} + + %include "saxpy.h" + +.. note:: The reader is encouraged to reference the online documentation for the many options which may be used in SWIG interface files. + + +Wrapping the C/C++ Source Code +------------------------------ + +SWIG is provided as the ``swig`` executable and is called on the command line to wrap C/C++ source code given a SWIG interface file. The call to ``swig`` produces a SWIG wrap file, which is designated following the :option:`-o` argument. The language used for the input source files (*e.g.*, C/C++) as well as the language targeted for the bindings (*e.g.*, Python) must be specified as flags to the ``swig`` executable. The following is an example of how to issue a command from the shell to wrap the source code in the :file:`saxpy.i` SWIG interface file: + +.. code-block:: none + + $ swig -python -c++ -o saxpy_wrap.cpp saxpy.i + + +One output from the ``swig`` command to wrap C/C++ source code is a new C/C++ source file which contains all of the wrapper code needed to build an extension module. For example, the interface file :file:`saxpy.i` will be transformed into an output :file:`saxpy_wrap.cpp` file. To build the final extension module, the SWIG output file is compiled and linked with the rest of the C/C++ program to create a shared library as discussed in the following sections. + +Another output from a ``swig`` command to wrap C/C++ source code is a new file in the scripting language targeted by SWIG. In the case of OpenMOC, the target scripting language is Python and hence a Python file containing the wrapped routines is created. For example, the interface file :file:`saxpy.i` will be transformed into an output :file:`saxpy.py` file. This is the file which is imported when a user imports the ``saxpy`` module into Python and which interfaces with the shared library created for the module. + + +Creating the Extension Module +----------------------------- + +The next step is to compile both the the C/C++ source files as well as the wrap file generated by SWIG. The wrap file includes :file:`Python.h` which is included with the Python development package provided by most package managers (*i.e.*, ``python-dev`` for Ubuntu's ``apt-get`` package manager). The C/C++ source **MUST** be compiled with the :option:`-fpic` option to produce "position independent code" for the shared library. The following two commands may be used to compile the source ``saxpy.cpp`` and ``saxpy_wrap.cpp`` files for this example: + +.. code-block:: none + + $ gcc -c saxpy.cpp -o saxpy.o -fpic -std=c++0x + $ gcc -I/usr/include/python2.7 -c saxpy_wrap.cpp -o saxpy_wrap.o -fpic -std=c++0x + +The final step is to link the object files into a shared library which will serve as the extension module. It is standard practice for C/C++ extension modules to begin with an underscore "_" prefix. The object files for the SAXPY example can be linked into the :file:`_saxpy.so` shared libary file as follows: + +.. code-block:: none + + $ g++ saxpy_wrap.o saxpy.o -o _saxpy.so -shared -Wl,-soname,_saxpy.so + + +Using the Extension Module +-------------------------- + +Finally, the shared library extension module can be imported into Python and used as follows: + + +.. code-block:: none + + $ python + Python 2.7.3 (default, Sep 26 2013, 16:35:25) + [GCC 4.7.2] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> import _saxpy as module + >>> module.set_array_length(10) + >>> module.initialize_data() + >>> module.saxpy() + >>> module.print_data() + a = 0.840188 + x[0] = 0.394383 y[0] = 1.114455 + x[1] = 0.798440 y[1] = 1.582487 + x[2] = 0.197551 y[2] = 0.501203 + x[3] = 0.768230 y[3] = 0.923232 + x[4] = 0.553970 y[4] = 0.942836 + x[5] = 0.628871 y[5] = 0.893154 + x[6] = 0.513401 y[6] = 1.383583 + x[7] = 0.916195 y[7] = 1.405488 + x[8] = 0.717297 y[8] = 0.744267 + x[9] = 0.606969 y[9] = 0.526268 + >>> module.free_data() + + +.. _numpy_typemaps: + +-------------- +NumPy Typemaps +-------------- + +It is often useful to input/return NumPy data structures to/from C/C++ routines. The `NumPy C API`_ makes this functionality possibility through **array conversions**. In addition, it is possible to automatically *embed* the NumPy C API directly into the source code with the use of `NumPy typemaps`_. Typemaps are a mechanism to match **function signatures** through a list of of function arguments. When SWIG finds a function which matches the typemap, it will target and subsequently modify the function to include the NumPy C API in order to input/output NumPy data arrays. Two types of parameters must be specified in the C/C++ function(s) of interest in order to match a NumPy typemap: + +* **Array Pointer** - The data type and pointer to the array +* **Array Dimensions** - An integer for each array dimension + +The :file:`numpy.i` interface file (:download:`download <../../img/numpy.i>`) defines the typemaps and is shipped with OpenMOC in the :file:`/OpenMOC/openmoc` directory. In order to utilize NumPy typemaps, the following should be appended to the SWIG interface file used for the C/C++ extension module of interest: + +.. code-block:: none + + %include "numpy.i" + + %init %{ + import_array(); + %} + +The following sections overview the basic steps to utilize NumPy typemaps to input NumPy data from Python into C/C++ routines, and return data from C/C++ routines as NumPy arrays. + + +Input NumPy Data Arrays +----------------------- + +The :file:`numpy.i` interface file provides two particular typemaps for inputting a NumPy data array into a C/C++ routine. The :envvar:`IN_ARRAY*` defines an array which is passed into a routine but is not modified in-place by the C/C++ function and is not returned to the user. The :envvar:`INPLACE_ARRAY*` typemap defines arrays that are modified in-place. In each case, the :envvar:`*` represents the number of dimensions for the input array. For example, in order to input a 3D array to be modified in-place, one would use the :envvar:`INPLACE_ARRAY3` typemap. The array dimension(s) are included in each typemap through the use of the :envvar:`DIM*` parameter. + +The following is an example C/C++ in which which we wish to wrap some function ``sum_array(...)`` with SWIG and provide the capability to input a NumPy array as a function parameter. Note that the function prototype includes a first paramter for the pointer to the input double array and a second parameter for the length of the array (which together form the function signature). The function prototype is given below in the :file:`sum_array.h` file below file (:download:`download <../../img/sum_array.h>`): + +.. code-block:: c + + /* File sum_array.h */ + + /* Define function prototype to take in a NumPy array */ + double sum_array(double* input_array, int length); + +One possible implementation of the ``sum_array(...)`` routine is given in the :file:`sum_array.cpp` file below (:download:`download <../../img/sum_array.cpp>`): + +.. code-block:: c + + /* File sum_array.cpp */ + + /* Define function implementation */ + double sum_array(double* input_array, int length) { + + /* Initialize sum */ + double sum = 0.; + + /* Compute sum of array elements */ + for (int i=0; i < length; i++) + sum += input_array[i]; + + return sum; + } + +The following would be the required SWIG interface file :file:`sum_array.i` (:download:`download <../../img/sum_array.i>`) to wrap :file:`sum_array.h` into the ``_sum_array`` C/C++ extension module for Python. The second-to-last line defines the NumPy typemap - the first tuple is a pair of the typemap (array type and dimension) while the second is the function signature to match using that typemap. + +.. code-block:: none + + %module sum_array + + %{ + #define SWIG_FILE_WITH_INIT + #include "sum_array.h" + %} + + /* Include the NumPy typemaps library */ + %include "numpy.i" + + %init %{ + import_array(); + %} + + /* Typemap for the sum_list(double* input_array, int length) C/C++ routine */ + %apply (double* IN_ARRAY1, int DIM1) {(double* input_array, int length)}; + + %include "sum_array.h" + +The source code can be wrapped and compiled in similar fashion to that shown before using the following commands from the console: + +.. code-block:: none + + $ swig -python -c++ -o sum_array_wrap.cpp sum_array.i + $ gcc -c sum_array.cpp -o sum_array.o -fpic -std=c++0x + $ gcc -I/usr/include/python2.7 -c sum_array_wrap.cpp -o sum_array.o -fpic -std=c++0x + $ g++ sum_array_wrap.o sum_array.o -o _sum_array.so -shared -Wl,-soname,_sum_array.so + +Finally, the shared library extension module may be imported into Python and the routine used with a NumPy array as follows: + +.. code-block:: none + + $ python + Python 2.7.3 (default, Sep 26 2013, 16:35:25) + [GCC 4.7.2] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> from numpy.random import rand + >>> from _sum_array import * + >>> input_array = rand(5) + >>> sum = sum_array(input_array) + >>> print 'The sum of the array is %d' % (sum) + The sum of the array is 2 + +.. note:: More detailed information on :envvar:`IN_ARRAY` and :envvar:`INPLACE_ARRAY` typemaps is provided in the official `NumPy.i`_ documetation. + + +Return NumPy Data Arrays +------------------------ + +The :file:`numpy.i` interface file (:download:`download <../../img/numpy.i>`) also provides two typemaps for returning a NumPy data array from a C/C++ routine. The :envvar:`ARGOUT_ARRAY*` used in situations where you would allocate an array on the heap and call the function to fill the array values. In Python, the arrays are allocated for you and returned as new array objects. As was the case for array input, the :envvar:`*` represents the number of dimensions for the input array. For example, in order to input a 3D array to be modified in-place, one would use the :envvar:`ARGOUT_ARRAY3` typemap. The array dimension(s) are included in each typemap through the use of the :envvar:`DIM*` parameter. + +The following is an example C/C++ in which which we wish to wrap some function ``get_rand_array(...)`` with SWIG and provide the capability to convert a C/C++ array into an output NumPy array. Based on the function signature, it would appear that the output array is input into the function and nothing is returned. Instead, SWIG will modify the source code with the NumPy C API such that a NumPy array is initialized and input as a C/C++ array and subsequently returned as a NumPy array. + +The function prototype is given below in the :file:`get_rand_array.h` file below (:download:`download <../../img/get_rand_array.h>`): + +.. code-block:: c + + /* File get_rand_array.h */ + #include + + /* Define function prototype to take in a NumPy array */ + void get_rand_array(double* output_array, int length); + +One possible implementation of the ``get_rand_array(...)`` routine is given in the :file:`get_rand_array.cpp` file below (:download:`download <../../img/get_rand_array.cpp>`): + +.. code-block:: c + + /* File get_rand_array.cpp */ + #include "get_rand_array.h" + + /* Define function implementation */ + void get_rand_array(double* output_array, int length) { + + /* Populate input NumPy array with random numbers */ + for (int i=0; i < length; i++) + output_array[i] = ((double) rand()) / RAND_MAX; + + return; + } + +The following would be the required SWIG interface file :file:`get_rand_array.i` (:download:`download <../../img/get_rand_array.i>`) to wrap :file:`get_rand_array.h` into the ``_get_rand_array`` C/C++ extension module for Python. The second-to-last line defines the NumPy typemap - the first tuple is a pair of the typemap (array type and dimension) while the second is the function signature to match using that typemap. + +.. code-block:: none + + %module get_rand_array + + %{ + #define SWIG_FILE_WITH_INIT + #include "get_rand_array.h" + %} + + /* Include the NumPy typemaps library */ + %include "numpy.i" + + %init %{ + import_array(); + %} + + /* Typemap for the get_rand_array(double* output_array, int length) C/C++ routine */ + %apply (double* ARGOUT_ARRAY1, int DIM1) {(double* output_array, int length)}; + + %include "get_rand_array.h" + +The source code can be wrapped and compiled in similar fashion to that shown before using the following commands from the console: + +.. code-block:: none + + $ swig -python -c++ -o get_rand_array_wrap.cpp get_rand_array.i + $ gcc -c get_rand_array.cpp -o get_rand_array.o -fpic -std=c++0x + $ gcc -I/usr/include/python2.7 -c get_rand_array_wrap.cpp -o get_rand_array.o -fpic -std=c++0x + $ g++ get_rand_array_wrap.o get_rand_array.o -o _get_rand_array.so -shared -Wl,-soname,_get_rand_array.so + +Finally, the shared library extension module may be imported into Python and the routine used with a NumPy array as follows: + +.. code-block:: none + + $ python + Python 2.7.3 (default, Sep 26 2013, 16:35:25) + [GCC 4.7.2] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> from _get_rand_array import * + >>> output_array = get_rand_array(10) + >>> print output_array + [ 0.84018773 0.39438292 0.78309923 0.79844004 0.91164738 0.19755137 + 0.33522275 0.7682296 0.27777472 0.55396998] + >>> type(output_array) + + + +.. note:: More detailed information on the :envvar:`ARGOUT_ARRAY` typemap is provided in the official `NumPy.i`_ documetation. + + +------------- +SWIG Typemaps +------------- + +On some machines - such as some leadership class supercomputing clusters - NumPy may not be available. As a result it may be preferable to input/output data from Python using standard Python data structures (*e.g.*, lists, tuples). SWIG provides it's own library of typemaps for this purpose in the :file:`typemaps.i` file which is included in the standard SWIG installation. + +In order to utilize `SWIG typemaps`_, the following include should be appended to the SWIG interface file used for the C/C++ extension module of interest: + +.. code-block:: none + + %include "typemaps.i" + + +The following sections overview the basic steps to utilize SWIG typemaps to input data from Python lists into C/C++ routines, and return data from C/C++ routines as Python lists. + +.. note:: The reader is encouraged to reference the online documentation for `SWIG typemaps`_ for more in-depth information and examples. + + + +Input Python Lists +------------------ + +This section introduces the SWIG typemaps for inputting Python lists into C/C++ routines with a simple example. The example uses SWIG to wrap a C/C++ file to create a routine which takes in a list of floating point data and prints it to the console. + +The following is the C++ header file :file:`sum_list.h` for the example code (:download:`download <../../img/sum_list.h>`). + +.. code-block:: c + + /* File sum_list.h */ + #include + + /* Define function prototype */ + double sum_list(double* input_list, int length); + +The corresponding function implementation for this example is given in the C++ source file :file:`sum_list.cpp` below (:download:`download <../../img/sum_list.cpp>`). + +.. code-block:: c + + /* File sum_list.cpp */ + #include "sum_list.h" + + double sum_list(double* input_list, int length) { + + /* Initialize sum */ + double sum = 0.; + + /* Compute sum of array elements */ + for (int i=0; i < length; i++) + sum += input_list[i]; + + return sum; + } + + +The following would be the required SWIG interface file :file:`sum_list.i` (:download:`download <../../img/sum_list.i>`) to wrap :file:`sum_list.h` into the ``_sum_list`` C/C++ extension module for Python. Writing an interface file using `SWIG typemaps`_ is more involved than it is for NumPy typemaps and requires some familiarity with the `Python/C API`_. + +.. code-block:: none + + %module sum_list + %{ + #define SWIG_FILE_WITH_INIT + #include "sum_list.h" + %} + + /* Include the SWIG typemaps library */ + %include typemaps.i + + /* Typemap the sum_list(double* input_list, int length) C/C++ routine */ + %typemap(in) (double* input_list, int length) { + + /* Check that the input is a Python list data structure */ + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values\n"); + return NULL; + } + + /* Set the second parameter to the length of the Python list input */ + $2 = PySequence_Length($input); + + /* Allocate memory to convert the list into a C/C++ array */ + $1 = (double*) malloc($2 * sizeof(double)); + + /* Loop over the values in the list */ + for (int i = 0; i < $2; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If the value is a number, cast it as an int and set the + * input array value */ + if (PyNumber_Check(o)) { + $1[i] = (double) PyFloat_AsDouble(o); + } + else { + free($1); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers\n"); + return NULL; + } + } + } + + %include "sum_list.h" + + +The source code can be wrapped and compiled in similar fashion to that shown before using the following commands from the console: + +.. code-block:: none + + $ swig -python -c++ -o sum_list_wrap.cpp sum_list.i + $ gcc -c sum_list.cpp -o sum_list.o -fpic -std=c++0x + $ gcc -I/usr/include/python2.7 -c sum_list_wrap.cpp -o sum_list_wrap.o -fpic -std=c++0x + $ g++ sum_list_wrap.o sum_list.o -o _sum_list.so -shared -Wl,-soname,_sum_list.so + +Finally, the shared library extension module can be imported into Python and used as follows: + +.. code-block:: none + + $ python + Python 2.7.3 (default, Sep 26 2013, 16:35:25) + [GCC 4.7.2] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> from _sum_list import * + >>> input_list = [2.,4.,8.,16.,32.] + >>> sum = sum_list(input_list) + >>> print 'The sum of the array is %d' % (sum) + The sum of the array is 62 + + +Return Python Lists +------------------- + +The :file:`std_vector.i` interface file provides `SWIG templates`_ for returning a Python tuple from a function returning a `C++ STL`_ ``std::vector`` data structure. The following is an example C/C++ in which we wish to wrap some function ``get_rand_list(...)`` with SWIG and provide the capability to convert a C++ ``std::vector`` into an output Python list. SWIG will modify the source code with the `Python/C API`_ such that a Python tuple is returned with the data, which will then be converted to a Python list. + +The function prototype is given below in the :file:`get_rand_list.h` file below (:download:`download <../../img/get_rand_list.h>`): + +.. code-block:: c + + /* File sum_list.h */ + #include + #include + + /* Define function prototype */ + std::vector get_rand_list(int length); + +One possible implementation of the ``get_rand_list(...)`` routine is given in the :file:`get_rand_list.cpp` file below (:download:`download <../../img/get_rand_list.cpp>`): + +.. code-block:: c + + /* File get_rand_list.cpp */ + #include "get_rand_list.h" + + /* Define function implementation */ + std::vector get_rand_list(int length) { + + /* Allocate memory for the C++ STL vector */ + std::vector output_list(length); + + /* Populate vector with random numbers */ + for (int i=0; i < length; i++) + output_list[i] = ((double) rand()) / RAND_MAX; + + return output_list; + } + +The following would be the required SWIG interface file :file:`get_rand_list.i` (:download:`download <../../img/get_rand_list.i>`) to wrap :file:`get_rand_list.h` into the ``_get_rand_list`` C/C++ extension module for Python. The interface file includes the :file:`std_vector.i` file and defines a SWIG template to match C++ STL vectors. + +.. code-block:: none + + %module get_rand_list + %{ + #define SWIG_FILE_WITH_INIT + #include "get_rand_list.h" + %} + + %include "std_vector.i" + + /* SWIG template for get_rand_list(int length) C++ routine */ + namespace std { + %template(DoubleVector) vector; + } + + %include "get_rand_list.h" + +The source code can be wrapped and compiled in similar fashion to that shown before using the following commands from the console: + +.. code-block:: none + + $ swig -python -c++ -o get_rand_list_wrap.cpp get_rand_list.i + $ gcc -c get_rand_list.cpp -o get_rand_list.o -fpic -std=c++0x + $ gcc -I/usr/include/python2.7 -c get_rand_list_wrap.cpp -o get_rand_list_wrap.o -fpic -std=c++0x + $ g++ get_rand_list_wrap.o get_rand_list.o -o _get_rand_list.so -shared -Wl,-soname,_get_rand_list.so + +Finally, the shared library extension module can be imported into Python and used as follows: + +.. code-block:: none + + $ python + Python 2.7.3 (default, Sep 26 2013, 16:35:25) + [GCC 4.7.2] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> from _get_rand_list import * + >>> output_list = list(get_rand_list(10)) + >>> print output_list + [0.8401877171547095, 0.39438292681909304, 0.7830992237586059, 0.7984400334760733, + 0.9116473579367843, 0.19755136929338396, 0.335222755714889, 0.768229594811904, + 0.2777747108031878, 0.5539699557954305] + >>> type(output_list) + + + +------------------ +Default Parameters +------------------ + +It is highly recommended that developers make use of `default parameters`_ for routines when possible. Default arguments in a C++ routine are wrapped by ``swig`` given the :option:`-keyword` command line option to provide `keyword arguments`_ (also known as named parameters) in the Python binding for that routine. There are several benefits for defining default arguments in the C/C++ source code: + +* **Readability** - Keyword arguments make code more readable, especially in example input files for users new to OpenMOC + +* **Ordering** - Keyword arguments can be provided in any order, lessening the burden to the user to remember a specific ordering + +* **Flexibility** - Function parameters with useful default values are not required at runtime, making Python scripts easier to comprehend + +An example of function parameters with default values and the use of keyword arguments to override the default values in Python is given below: + +.. code-block:: python + + # Define a function with two arguments with default values + def multiverseHelloWorld(count=5, greeting='Hello'): + + for i in range(count): + print '%s from World %d!' % (greeting, i) + + # Call routine and override default keyword arguments + # The keyword arguments can be provided in any order + multiverseHelloWorld(greeting='Hola', count=7) + +Likewise, an example of how to define default values for function parameters - which will be provided through the Python interface as `SWIG default arguments`_ - in C/C++ is given below: + +.. code-block:: c + + /* Define a function prototype with two arguments with default values */ + void multiverseHelloWorld(int count=5, char* greeting="Hello"); + + /* Function implementation doesn't include default values in C++ */ + void multiverseHelloWorld(int count, char* greeting) { + + for (int i=0; i < count; i++) + printf("%s from World %d!", greeting, i) + } + + +------ +Macros +------ + +SWIG provides preprocessing_ capabilities for interface files. `Macro expansions`_ may be defined in the interface file using the traditional syntax for C/C++: + +.. code-block:: c + + #ifndef PI + #define PI 3.14159 + #endif + +SWIG also includes special `SWIG macros`_ with more enhanced capabilities for interface files. + + +-------- +Typedefs +-------- + +SWIG provides functionality to define typedefs_ in interface files. `SWIG typedefs`_ can be defined using the same syntax as in C/C++. As discussed in the SWIG online documentation, the typedef must be defined twice in the interface file for in order for it to be propagated to the generated wrapper file: + +.. code-block:: c + + %{ + /* Include in the generated wrapper file */ + typedef unsigned int size_t; + %} + + /* Tell SWIG about it */ + typedef unsigned int size_t; + + + +.. _SWIG Project: http://www.swig.org/ +.. _NumPy typemaps: http://docs.scipy.org/doc/numpy/reference/swig.interface-file.html +.. _Numpy.i: http://docs.scipy.org/doc/numpy/reference/swig.interface-file.html +.. _NumPy C API: http://docs.scipy.org/doc/numpy/reference/c-api.html +.. _SWIG typemaps: http://www.swig.org/Doc1.3/Typemaps.html +.. _SWIG Basics Tutorial: http://www.swig.org/Doc1.3/SWIG.html +.. _SWIG C++ Tutorial: http://www.swig.org/Doc1.3/SWIGPlus.html + +.. _SWIG default arguments: http://www.swig.org/Doc1.3/SWIGPlus.html#SWIGPlus_default_args +.. _default parameters: http://www.learncpp.com/cpp-tutorial/77-default-parameters/ +.. _keyword arguments: http://en.wikipedia.org/wiki/Named_parameter +.. _preprocessing: http://en.wikipedia.org/wiki/C_preprocessor +.. _Macro expansions: http://www.swig.org/Doc1.3/Preprocessor.html#Preprocessor_nn5 +.. _SWIG macros: http://www.swig.org/Doc1.3/Preprocessor.html#Preprocessor_nn6 +.. _typedefs: http://en.wikipedia.org/wiki/Typedef +.. _SWIG typedefs: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn20 +.. _SWIG interface file: http://www.swig.org/Doc2.0/SWIGDocumentation.html#SWIG_nn47 +.. _C/C++ extension module: http://docs.python.org/2/extending/extending.html +.. _SWIG exception handling: http://www.swig.org/Doc1.1/HTML/Exceptions.html +.. _Python/C API: http://docs.python.org/2/c-api/ +.. _SWIG STL vector typemap: http://www.swig.org/Doc2.0/SWIGDocumentation.html#Library_std_vector +.. _C++ STL: http://en.wikipedia.org/wiki/Standard_Template_Library +.. _SWIG templates: http://www.swig.org/Doc1.3/SWIGPlus.html#SWIGPlus_nn30 diff --git a/docs/source/devguide/work_flow.rst b/docs/source/devguide/work_flow.rst new file mode 100644 index 000000000..cd9c8fc1b --- /dev/null +++ b/docs/source/devguide/work_flow.rst @@ -0,0 +1,41 @@ +.. _work_flow: + + +==================== +Development Workflow +==================== + +Anyone wishing to make contributions to OpenMOC should be fully acquianted and +comfortable working with git_ and GitHub_. The primary means of modifying and +making contributions to OpenMOC is through a GitHub `pull request`_. This is +what's known as a `fork and pull development model`_. The steps for this are as +follows: + +* **Fork the Repository** - Fork_ the main OpenMOC repository from `mit-crpg/OpenMOC`_. This will create a repository with the same name under your personal account. + +* **Create a Git Branch** - `Create a git branch`_ to your local repository and make commits that you intend to merge back into the main OpenMOC repository. + +* **Create a Pull Request** - Create a `pull request`_ from GitHub and select the branch to merge from your local repository with the appropriate branch in `mit-crpg/OpenMOC`_. + +* **Merge the Pull Request** - The OpenMOC integration manager will review your pull request and make sure it compiles and runs correctly and conforms to the :ref:`style_guide`. + +* **Code Integration** - After the pull request has been thoroughly vetted, the integration manager will merge it back into `mit-crpg/OpenMOC`_. + +While the process above depends on the fork of the OpenMOC repository being +publicly available on GitHub, you may also wish to do development on a private +repository for research or commercial purposes. The proper way to do this is to +create a complete copy of the OpenMOC repository (not a fork from GitHub). The +private repository can then either be stored just locally or in conjunction with +a private repository on Github (this requires a `paid plan`_). If you want to +merge some changes you've made in your private repository back to +`mit-crpg/OpenMOC`_ repository, simply follow the steps above with an extra step +of pulling a branch from your private repository into your public fork. + +.. _git: http://git-scm.com/ +.. _GitHub: https://github.com/ +.. _pull request: https://help.github.com/articles/using-pull-requests +.. _fork and pull development model: https://help.github.com/articles/using-pull-requests +.. _Fork: https://help.github.com/articles/fork-a-repo +.. _Create a git branch: http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging +.. _mit-crpg/OpenMOC: https://github.com/mit-crpg/OpenMOC +.. _paid plan: https://github.com/plans diff --git a/docs/source/doxygen/api.rst b/docs/source/doxygen/api.rst new file mode 100644 index 000000000..5beaaebf9 --- /dev/null +++ b/docs/source/doxygen/api.rst @@ -0,0 +1,9 @@ +.. _api: + +=========== +OpenMOC API +=========== + +.. raw:: html + + diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 000000000..744fe56c8 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,36 @@ +========================================== +The OpenMOC Method of Characteristics Code +========================================== + +OpenMOC is a Method of Characteristics (MOC) neutral particle transport code for reactor physics criticality calculations. The OpenMOC project aims to be the first publicly available MOC code platform for full-core 3D reactor physics analysis. At the present time, it is capable of simulating 2D assembly and full-core reactor models based on constructive solid geometry with second-order surfaces. High-performance parallel solvers for multi-core CPUs and GPUs are actively pursued as part of the OpenMOC project. In addition, continued development of algorithmic acceleration techniques such as coarse mesh finite difference (CMFD) acceleration, are a focus of the OpenMOC project. + +OpenMC was originally developed by members of the `Computational Reactor Physics +Group`_ at the `Massachusetts Institute of Technology`_ starting +in 2012. For more information on OpenMOC, feel free to send a message to the User's Group `mailing list`_. + +.. _Computational Reactor Physics Group: http://crpg.mit.edu +.. _Massachusetts Institute of Technology: http://web.mit.edu +.. _mailing list: https://groups.google.com/forum/?hl=en#!forum/openmoc-users + + +-------- +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + quickinstall + releasenotes/index + methods/index + usersguide/index + devguide/index + doxygen/api + publications + developers + license + + +.. figure:: ../img/cover.png + :align: center + :figclass: align-center diff --git a/docs/source/license.rst b/docs/source/license.rst new file mode 100644 index 000000000..60aea2760 --- /dev/null +++ b/docs/source/license.rst @@ -0,0 +1,24 @@ +.. _license: + +================= +License Agreement +================= + +Copyright © 2012-2015 Massachusetts Institute of Technology + +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/docs/source/methods/cmfd.rst b/docs/source/methods/cmfd.rst new file mode 100644 index 000000000..e77416c3a --- /dev/null +++ b/docs/source/methods/cmfd.rst @@ -0,0 +1,460 @@ +.. _cmfd: + +========================================== +Coarse Mesh Finite Difference Acceleration +========================================== + +While MOC offers many benefits including treatment of complex geometries and amenability to parallelization, it suffers from slow convergence which necessitates the use of acceleration methods. Numerous acceleration schemes have been proposed for MOC such as CMFD [Smith-1983]_, coarse mesh rebalance (CMR) [Yamamoto-2002]_, [Yamamoto-2005]_, [Yamamoto-2008]_, [Lewis]_, and low order transport operator acceleration [Li]_ with CMFD being the most widely adopted due to its simplicity and acceleration performance. OpenMOC uses the CMFD nonlinear diffusion acceleration (NDA) scheme to reduce the number of iterations required for convergence. Acceleration schemes, such as NDA, are necessary when solving full-core problems which require thousands of power iterations in LWR problems that tend to have high dominance ratios. CMFD was first proposed by Smith [1]_ and has been widely used in accelerating neutron diffusion and transport problems for many years. In particular, it has been shown that CMFD acceleration gives :math:`>` 100x speedups on large LWR problems [Smith-2002]_. + +CMFD acceleration functions by using the solution of a coarse mesh diffusion problem to accelerate the convergence of a fine mesh transport problem. It is implemented by overlaying a 2D cartesian mesh over an FSR mesh. :ref:`Figure 1 ` gives an illustration of the FSR mesh layout and coarse mesh layout used for solving a 17 x 17 PWR assembly problem. + +CMFD acceleration functions by using the solution of a coarse mesh diffusion problem to accelerate the convergence of a fine mesh transport problem. It is implemented by overlaying a 2D cartesian mesh over an unstructured FSR mesh. :ref:`Figure 1 ` gives an illustration of the FSR mesh layout and coarse mesh layout used for solving a 17 x 17 PWR assembly problem. + +.. _figure-fsr-mesh-regions: + +.. figure:: ../../img/fig-fsr-mesh-regions.png + :align: center + :figclass: align-center + :width: 700 px + + **Figure 1**: Flat source region (left) and CMFD (right) mesh layout for a 17 x 17 PWR assembly where each colored cell denotes a different region. + +To derive the CMFD equations, we begin with the 2D, steady state multi-group neutron diffusion equation: + +.. math:: + :label: dif-eqn + + - \nabla \cdot D_{\mathbf{g}} (x,y) \nabla \phi_{\mathbf{g}} (x,y) + \varSigma^A_{\mathbf{g}} (x,y) \phi_{\mathbf{g}} (x,y) + \sum_{\substack{{\mathbf{g}} \prime = 1 \\ {\mathbf{g}} \prime \neq {\mathbf{g}}}}^{\mathbf{G}} \varSigma^S_{{\mathbf{g}} \rightarrow {\mathbf{g}} \prime} (x,y) \phi_{\mathbf{g}} (x,y) = \frac{\chi_{\mathbf{g}} (x,y)}{k_{eff}} \sum_{{\mathbf{g}} \prime = 1}^{\mathbf{G}} \nu \varSigma^F_{{\mathbf{g}} \prime} (x,y) \phi_{{\mathbf{g}} \prime} (x,y) + \sum_{\substack{{\mathbf{g}} \prime = 1 \\ {\mathbf{g}} \prime \neq {\mathbf{g}}}}^{\mathbf{G}} \varSigma^S_{{\mathbf{g}} \prime \rightarrow {\mathbf{g}}} (x,y) \phi_{{\mathbf{g}} \prime} (x,y) + +Where the terms in equation :eq:`dif-eqn` are defined as: + +.. _table-dif-eqn-terms: + +========================================= ============================= =================== ============================= +Variable Description Variable Description +========================================= ============================= =================== ============================= +:math:`D` Diffusion coefficient :math:`\phi` Scalar flux on coarse mesh +:math:`\varSigma^A` Coarse mesh absorption XS :math:`\chi` Fission spectrum +:math:`\varSigma^S` Coarse mesh scattering XS :math:`k_{eff}` Neutron multiplication factor +:math:`\varSigma^F` Coarse mesh fission XS :math:`\nu` Neutrons per fission +:math:`{\mathbf{g}}, {\mathbf{g}} \prime` Energy group index :math:`x, y` Position variable +========================================= ============================= =================== ============================= + +.. _gen-coarse-mesh + +Cross Section Generation +======================== + +The cross sections for the CMFD diffusion equation are generated by energy-condensation and area-averaging of the cross sections from the fine mesh as shown in :eq:`xs-condensation`. The diffusion coefficient is computed by spatially condensing the flux-volume weighted transport cross section for an MOC group and then energy-condensing the diffusion coefficient for the CMFD cell. The energy group structure of the CMFD diffusion equation does not have to be the same as the energy group structure used in MOC. For example, :ref:`Figure 2 ` shows the various ways to formulate the CMFD group structure to accelerate a three group MOC problem. + + +The cross sections for the CMFD diffusion equation are generated by energy-condensation and area-averaging of the cross sections from the fine mesh as shown in equation :eq:`xs-condensation`. The energy group structure of the CMFD diffusion equations does not have to be the same as the energy group structure used in MOC. For example, :ref:`Figure 2 ` shows the various ways to formulate the CMFD group structure to accelerate a three group MOC problem. + +.. _figure-coarse-group-CMFD: + +.. figure:: ../../img/cmfd-gs.png + :align: center + :figclass: align-center + :width: 700 px + + **Figure 2**: Illustration of possible CMFD energy group structures for a three group MOC calculation. + +where energy groups in MOC are denoted with :math:`g` and energy groups in CMFD are denoted with :math:`\mathbf{g}`. The generalized equations for computing cross sections on the coarse mesh are then described by :eq:`xs-condensation`. + + +**Cross section condensation equations** + +.. math:: + :label: xs-condensation + + \varSigma^{A,i,j}_{\mathbf{g}} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Sigma^{A}_{r,g} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r} + +.. math:: + + \varSigma^{F,i,j}_{\mathbf{g}} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Sigma^{F}_{r,g} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r} + +.. math:: + + \nu \varSigma^{F,i,j}_{\mathbf{g}} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \nu \Sigma^{F}_{r,g} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r} + +.. math:: + + \varSigma^{S,i,j}_{\mathbf{g} \rightarrow \mathbf{g} \prime} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{g \prime \in \mathbf{g} \prime} \displaystyle\sum\limits_{r \in (i,j)} \Sigma^S_{r,g \rightarrow g \prime} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r} + +.. math:: + + \varSigma^{tr,i,j}_{g} = \frac{\displaystyle\sum\limits_{r \in (i,j)} \Sigma^{tr}_{r,g} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r} + +.. math:: + + D_{\mathbf{g}}^{i,j} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \frac{1}{3 \Sigma^{tr,i,j}_{g}} \phi^{i,j}_{g}}{\phi^{i,j}_{\mathbf{g}}} + +.. math:: + + \chi_{\mathbf{g}}^{i,j} = \frac{\displaystyle\sum\limits_{g \in \mathbf{g}} \displaystyle\sum\limits_{r \in (i,j)} \displaystyle\sum\limits_{g \prime = 1}^G \chi_{r,g} \nu \Sigma^F_{r,g \prime} \Phi_{r,g \prime} A_r}{\displaystyle\sum\limits_{r \in (i,j)} \displaystyle\sum\limits_{g \prime = 1}^G \displaystyle\sum\limits_{g \prime \prime = 1}^G \chi_{r,g \prime \prime} \nu \Sigma^{F}_{r,g \prime} \Phi_{r,g \prime} A_r} + +.. math:: + + \phi_{g}^{i,j} = \frac{\displaystyle\sum\limits_{r \in (i,j)} \Phi_{r,g} A_r}{\displaystyle\sum\limits_{r \in (i,j)} A_r} + +.. math:: + + \phi_{\mathbf{g}}^{i,j} = \displaystyle\sum\limits_{g \in \mathbf{g}} \phi_{g}^{i,j} + +where :math:`i` and :math:`j` denote the mesh cell indices in the x and y directions, respectively. + + +Applying the Finite Difference Approximation +============================================ + +The diffusion operator in :eq:`dif-eqn` can be expanded to yield: + +.. math:: + :label: dif-eqn-expand-1 + + - \frac{\partial}{\partial x} D_{\mathbf{g}} (x,y) \frac{\partial}{\partial x} \phi_{\mathbf{g}} (x,y) - \frac{\partial}{\partial y} D_{\mathbf{g}} (x,y) \frac{\partial}{\partial y} \phi_{\mathbf{g}} (x,y) + \varSigma^R_{\mathbf{g}} (x,y) \phi_{\mathbf{g}} (x,y) = \frac{\chi_{\mathbf{g}} (x,y)}{k_{eff}} \sum_{\mathbf{g} \prime = 1}^{\mathbf{G}} \nu \varSigma^F_{\mathbf{g} \prime} (x,y) \phi_{\mathbf{g} \prime} (x,y) + \sum_{\substack{\mathbf{g} \prime = 1 \\ \mathbf{g} \prime \neq \mathbf{g}}}^{\mathbf{G}} \varSigma^S_{\mathbf{g} \prime \rightarrow \mathbf{g}} (x,y) \phi_{\mathbf{g} \prime} (x,y) + +where the removal cross section, :math:`\varSigma^R_{\mathbf{g}}` is defined as: + +.. math:: + :label: emoval-xs + + \varSigma^R_{\mathbf{g}} \equiv \varSigma^A_{\mathbf{g}} + \sum_{\substack{\mathbf{g} \prime = 1 \\ \mathbf{g} \prime \neq \mathbf{g}}}^{\mathbf{G}} \varSigma^S_{\mathbf{g} \rightarrow \mathbf{g} \prime} + +In cases where axial buckling is specified the removal cross section takes the following form: + +.. math:: + :label: removal-xs-2 + + \varSigma^R_{\mathbf{g}} \equiv D_{\mathbf{g}} B_z^2 + \varSigma^A_{\mathbf{g}} + \sum_{\substack{\mathbf{g} \prime = 1 \\ \mathbf{g} \prime \neq \mathbf{g}}}^{\mathbf{G}} \varSigma^S_{\mathbf{g} \rightarrow \mathbf{g} \prime} + +We can integrate :eq:`dif-eqn-expand-1` over a mesh cell to get the neutron balance in that cell. Performing the integration on cell :math:`(i,j)` and simplifying we get: + +.. math:: + + - \int_{i-\frac{1}{2}}^{i+\frac{1}{2}} \int_{j-\frac{1}{2}}^{j+\frac{1}{2}} \frac{\partial}{\partial x} D_{\mathbf{g}}^{i,j} \frac{\partial}{\partial x} \phi_{\mathbf{g}}^{i,j} dx dy - \int_{i-\frac{1}{2}}^{i+\frac{1}{2}} \int_{j-\frac{1}{2}}^{j+\frac{1}{2}} \frac{\partial}{\partial y} D_{\mathbf{g}}^{i,j} \frac{\partial}{\partial y} \phi_{\mathbf{g}}^{i,j} dx dy + \Delta x^{i,j} \Delta y^{i,j} \varSigma_{{\mathbf{g}}}^{R,i,j} \phi_{\mathbf{g}}^{i,j} = \Delta x^{i,j} \Delta y^{i,j} \frac{\chi_{\mathbf{g}}^{i,j}}{k_{eff}} \sum_{{\mathbf{g}} \prime = 1}^{\mathbf{G}} \nu \varSigma_{{\mathbf{g}} \prime}^{F,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + \Delta x^{i,j} \Delta y^{i,j} \sum_{\substack{{\mathbf{g}} \prime = 1 \\ {\mathbf{g}} \prime \neq {\mathbf{g}}}}^{\mathbf{G}} \varSigma_{{\mathbf{g}} \prime \rightarrow {\mathbf{g}}}^{S,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + +Where :math:`\Delta x^{i,j}` and :math:`\Delta y^{i,j}` denote the width and height of cell (i,j), respectively. Using the Divergence Theorem, we can reduce the volume integrals of the streaming terms to surface integrals over the bounding surfaces of a cell. The surface integrals will then represent currents across the surfaces of a cell. Using streaming in the x-direction as an example, we can rewrite the volume integral of the streaming term in the x-direction as: + +.. math:: + + - \int_{i-\frac{1}{2}}^{i+\frac{1}{2}} \int_{j-\frac{1}{2}}^{j+\frac{1}{2}} \frac{\partial}{\partial x} D_{\mathbf{g}}^{i,j} \frac{\partial}{\partial x} \phi_{\mathbf{g}}^{i,j} dx dy = \Delta y^{i,j} (J_{\mathbf{g}}^{i+\frac{1}{2},j} - J_{\mathbf{g}}^{i-\frac{1}{2},j}) + +Where :math:`J_{\mathbf{g}}^{i+\frac{1}{2},j}` and :math:`J_{\mathbf{g}}^{i-\frac{1}{2},j}` represent the surface-averaged net current across the right surface and across the left surface, respectively. An analogous equation can be written for streaming in the y direction. + +As an example, we will now solve for the currents on the right surface of a cell :math:`(i,j)` with neighboring cell :math:`(i + 1, j)` as illustrated in :ref:`Figure 3 `. + +.. _figure-cmfd-example: + +.. figure:: ../../img/cmfd-example.png + :align: center + :figclass: align-center + :width: 400 px + + **Figure 3**: Illustration of terms required to solve for streaming of neutrons from cell :math:`(i,j)` to :math:`(i+1,j)` in CMFD diffusion. + +To solve for the current at cell boundaries, we can perform finite difference approximations of the flux at a surface using the flux in the adjacent cells: + +.. math:: + + J_{\mathbf{g}}^{i+\frac{1}{2},j,+} = \left. - D_{\mathbf{g}}^{i+1,j} \frac{d \phi_{\mathbf{g}}^{i+\frac{1}{2},j}}{d x} \right|_{x^{i+\frac{1}{2},j,+}} = - D_{\mathbf{g}}^{i+1,j} \frac{\phi_{\mathbf{g}}^{i+1,j} - \phi_{\mathbf{g}}^{i+\frac{1}{2},j}}{\frac{\Delta x^{i+1,j}}{2}}\\ \nonumber + J_{\mathbf{g}}^{i+\frac{1}{2},j,-} = \left. - D_{\mathbf{g}}^{i,j} \frac{d \phi_{\mathbf{g}}^{i+\frac{1}{2},j}}{d x} \right|_{x^{i+\frac{1}{2},j,-}} = - D_{\mathbf{g}}^{i,j} \frac{\phi_{\mathbf{g}}^{i+\frac{1}{2},j} - \phi_{\mathbf{g}}^{i,j}}{\frac{\Delta x^{i,j}}{2}} + +Where :math:`J_{\mathbf{g}}^{i+\frac{1}{2},j,+}` and :math:`J_{\mathbf{g}}^{i+\frac{1}{2},j,-}` are the surface-averaged partial currents as approximated using a backward difference approximation from the cell at :math:`(i,j)` and a forward difference approximation from the cell at :math:`(i+1,j)`, respectively. Equating these representations of the current we can solve for the flux at the surface: + +.. math:: + + \phi_{\mathbf{g}}^{i+\frac{1}{2},j} = \frac{D_{\mathbf{g}}^{i,j} \phi_{\mathbf{g}}^{i,j} \Delta x^{i+1,j} + D_{\mathbf{g}}^{i+1,j} \phi_{\mathbf{g}}^{i+1,j} \Delta x^{i,j}}{D_{\mathbf{g}}^{i,j}\Delta x^{i+1,j} + D_{\mathbf{g}}^{i+1,j} \Delta x^{i,j}} + +The net current across the surface at :math:`(i+\frac{1}{2},j)` is then: + +.. math:: + :label: eqn-alg-net-current + + J_{\mathbf{g}}^{i+\frac{1}{2},j} = - \hat{D}_{\mathbf{g}}^{i+\frac{1}{2},j} (\phi_{\mathbf{g}}^{i+1,j} - \phi_{\mathbf{g}}^{i,j}) + +Where: + +.. math:: + :label: eqn-surf-dif-coef + + \hat{D}_{\mathbf{g}}^{i+\frac{1}{2},j} = \frac{2 D_{\mathbf{g}}^{i,j} D_{\mathbf{g}}^{i+1,j}}{D_{\mathbf{g}}^{i,j} \Delta x^{i+1,j} + D_{\mathbf{g}}^{i+1,j} \Delta x^{i,j}} + +The neutron balance equation in a cell then becomes: + +.. math:: + :label: eqn-dif-eqn-simple + + \Delta y^{i,j} (J_{\mathbf{g}}^{i+\frac{1}{2},j} - J_{\mathbf{g}}^{i-\frac{1}{2},j}) + \Delta + x^{i,j} (J_{\mathbf{g}}^{i,j+\frac{1}{2}} - J_{\mathbf{g}}^{i,j-\frac{1}{2}}) + \Delta x^{i,j} + \Delta y^{i,j} \varSigma_{\mathbf{g}}^{R,i,j} \phi_{\mathbf{g}}^{i,j} = \Delta x^{i,j} \Delta y^{i,j} \frac{\chi_{\mathbf{g}}^{i,j}}{k_{eff}} \sum_{{\mathbf{g}} \prime = 1}^{\mathbf{G}} \nu \varSigma_{{\mathbf{g}} \prime}^{F,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + \Delta x^{i,j} \Delta y^{i,j} \sum_{\substack{{\mathbf{g}} \prime = 1 \\ {\mathbf{g}} \prime \neq {\mathbf{g}}}}^{\mathbf{G}} \varSigma_{{\mathbf{g}} \prime \rightarrow {\mathbf{g}}}^{S,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + +Note that :eq:`eqn-alg-net-current` is the algebraic net current based on the finite difference approximation being applied across the surface of two neighboring cells and not the actual net current in the MOC problem. The actual current from the MOC problem is computed by accumulating the current contribution from every segment that crosses a surface as will be shown in the :ref:`Section 7.3 `. + +.. _nonlinear-dif-coef + +Introduction to nonlinear diffusion correction factors +====================================================== + +In order to conserve neutron balance between the CMFD and MOC problems, the net currents across the coarse mesh cell surfaces must be equal. The surface diffusion coefficient expression in :eq:`eqn-surf-dif-coef` results in a neutron current close to the actual current produced via the MOC solve, but there is no guarantee the currents will be equal. To compute the currents from MOC, the net currents are tallied during a transport sweep by summing the current contributions from each track that intersects a surface. For example, :eq:`eqn-surf-avg-tallied-current` represents the net current tally expression for surface :math:`(i + \frac{1}{2}, j)`. + +.. math:: + :label: eqn-surf-avg-tallied-current + + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2}, j} = \sum_{k \cap (i+\frac{1}{2},j)} \sum_{g \in \mathbf{g}} 2 \pi \omega_{m(k)} \tilde{\omega}_k \omega_p \sin \theta_p \Psi_{k,g,p} \cdot \hat{n} + +Where :math:`\hat{n}` is the unit surface normal and :math:`\tilde{\omega}_k` is the length of surface crossed by the track, as illustrated in :ref:`Figure 4 `. The first sum in :eq:`eqn-surf-avg-tallied-current` is over all tracks that cross the surface between mesh cells :math:`(i,j)` and :math:`(i+1,j)`. + +.. _figure-current-tally: + +.. figure:: ../../img/current-tally.png + :align: center + :figclass: align-center + :width: 400 px + + **Figure 4**: Angular flux from track :math:`k` with energy group :math:`g` and polar angle :math:`p` crossing surface :math:`(i+\frac{1}{2}, j)`. + +The length of surface crossed by the track is defined as: + +.. math:: + :label: eqn-surf-len-track + + \tilde{\omega}_k = \frac{\omega_k}{\cos \theta_k} + +Inserting :eq:`eqn-surf-len-track` into :eq:`eqn-surf-avg-tallied-current` gives us: + +.. math:: + :label: eqn-surf-avg-tallied-current-2 + + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2}, j} = \sum_{k \cap (i+\frac{1}{2},j)} \sum_{g \in \mathbf{g}} 2 \pi \omega_{m(k)} \frac{\omega_k}{\cos \theta_k} \omega_p \sin \theta_p \Psi_{k,g,p} \cdot \hat{n} + +When we apply the scalar product between the track azimuthal angle with the unit surface normal of the track, we get :math:`\cos \theta_k`, which reduces :eq:`eqn-surf-avg-tallied-current-2` to: + +.. math:: + :label: eqn-surf-avg-tallied-current-3 + + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2}, j} = \sum_{k \cap (i+\frac{1}{2},j)} \sum_{g \in \mathbf{g}} 2 \pi \omega_{m(k)} \omega_k \omega_p \sin \theta_p \Psi_{k,g,p} + +In order for the tallied net currents to equal the net current expression, a nonlinear diffusion coefficient term is added to :eq:`eqn-alg-net-current`: + +.. math:: + :label: eqn-alg-net-current-cor + + \frac{\tilde{J}_{\mathbf{g}}^{i+\frac{1}{2},j}}{\Delta y^{i,j}} = - \hat{D}_{\mathbf{g}}^{i+\frac{1}{2},j} (\phi_{\mathbf{g}}^{i+1,j} - \phi_{\mathbf{g}}^{i,j}) - \tilde{D}_{\mathbf{g}}^{i+\frac{1}{2},j} (\phi_{\mathbf{g}}^{i+1,j} + \phi_{\mathbf{g}}^{i,j}) + +Where :math:`\tilde{D}` is the nonlinear diffusion coefficient correction factor. Note that current expression on the right hand side of :eq:`qn-alg-net-current-cor` computes the surface-averaged net current whereas the current tallied from MOC has not been averaged over the surface; therefore, in :eq:`eqn-alg-net-current-cor` the net current tallied from MOC has been divided by the length of the surface that is being crossed. :math:`\tilde{D}` is computed to make :eq:`eqn-alg-net-current-cor` valid for the tallied net surface current in MOC for the most recent transport sweep: + +.. math:: + :label: eqn-dif-cor-factor + + \tilde{D}_{\mathbf{g}}^{i+\frac{1}{2},j} = \frac{- \hat{D}_{\mathbf{g}}^{i+\frac{1}{2},j} (\phi_{\mathbf{g}}^{i+1,j} - \phi_{\mathbf{g}}^{i,j}) - \frac{\tilde{J}_{\mathbf{g}}^{i+\frac{1}{2},j}}{\Delta y^{i,j}}}{(\phi_{\mathbf{g}}^{i+1,j} + \phi_{\mathbf{g}}^{i,j})} + + +.. _optically-thick: + +Treatment of optically thick regions +==================================== + +As shown in :ref:`Figure 1 ` the CMFD mesh is often applied at the pin cell level with cells on the order of 1-2 cm. By conserving reaction and leakage rates within cells, CMFD guarantees preservation of area-averaged scalar fluxes and net surface currents from the MOC fixed source iteration if the CMFD equations can be converged. However, when the fine mesh cell size becomes significantly larger than the neutron mean free path in that cell, the step characteristics no longer preserve the linear infinite medium solution to the transport equation [Larsen]_. While the nonlinear diffusion correction term in CMFD is guaranteed to preserve reaction rates and surface net currents for any choice of diffusion coefficient, convergence (and convergence rate) of the nonlinear iteration acceleration of CMFD is affected by the choice of diffusion coefficient. All flat source methods, when applied for thick optical meshes, artificially distribute neutrons in space. This is the reason that Larsen's effective diffusion coefficient is useful in assuring that the CMFD acceleration equations have a diffusion coefficient (on the flux gradient term) that is consistent, not with the physical transport problem, but with the transport problem that is being accelerated by the CMFD equations. Larsen's effective diffusion coefficient is precisely this term in the one-dimensional limit. The effective diffusion coefficient in the x-direction for cell :math:`(i,j)` can be expressed as: + +.. math:: + :label: eqn-optic-thick-d + + D_{\mathbf{g}}^{i,j,eff,x} = D_{\mathbf{g}}^{i,j} \bigg(1 + \frac{\Delta x^{i,j} \rho_{\mathbf{g}}^{i,j,x}}{2 D_{\mathbf{g}}^{i,j}} \bigg) \\ + \rho_{\mathbf{g}}^{i,j,x} = \frac{\displaystyle\sum\limits_{p = 1}^P \cos (\theta_p) \omega_p \alpha_{{\mathbf{g}},p}^{i,j,x}}{\displaystyle\sum\limits_{p = 1}^{P} \omega_p} \\ + \alpha_{{\mathbf{g}},p}^{i,j,x} = \left( \frac{1 + exp[-\gamma^{i,j,x}_{\mathbf{g},p}]}{1 - exp[-\gamma^{i,j,x}_{\mathbf{g},p}]} \right) - \frac{2}{\gamma^{i,j,x}_{\mathbf{g},p}} \\ + \gamma^{i,j,x}_{\mathbf{g},p} = \frac{\Delta x^{i,j}}{3 D_{\mathbf{g}}^{i,j} \cos (\theta_p)} + +Note that the effective diffusion coefficient depends on the width of the cell and is therefore directional in a 2D mesh. :eq:`eqn-optic-thick-d` can also be used to compute the effective diffusion coefficient in the y-direction, which will differ from the effective diffusion coefficient in the x-direction if the cell is not square. As the size of the cell approaches zero and the optical thickness of the cell approaches the optically thin limit, the effective diffusion coefficient will approach the material diffusion coefficient. For simplicity, we continue to use the surface diffusion coefficient terms in the rest of this thesis without the "eff" superscript. + + +.. _corner-crossings + +Treatment of coarse mesh cell corner crossings +============================================== + +In the CMFD formalism introduced in the previous sections, we only treat transport to adjacent cells. However, MOC produces tracks that directly and indirectly intersect mesh cell corners. A direct crossing is defined as a crossing where the centerline of a track directly intersects a mesh cell corner. An indirect crossing is defined as a crossing where the track sweeps through a corner but the track centerline does not directly cross through it. Illustrations of these two crossing types are shown in :ref:`Figure 5 `. + +.. _figure-corner-crossing: + +.. figure:: ../../img/corner-crossing.png + :align: center + :figclass: align-center + :width: 800 px + + **Figure 5**: Illustration of direct (1) and indirect (2) track corner crossings. + +There are three main approximations to treat corner crossings: + +1. Consistently tallying the current from direct corner crossings to only one of the surfaces. This approximation effectively moves the tracks that directly cross through a corner far enough to one side such that the entire segment crosses a single surface. In order to maintain neutron balance, tracks must be consistently moved to the same side for tracking forward and backwards along a track. Indirect crossings are ignored. +2. Split the current from direct corner crossings to each of the neighboring surfaces. This approximation effectively splits the track into two half-weighted segments and moves them to either side of the corner such that each new half-weighted track only sweeps across one surface. Indirect crossings are ignored. This is essentially a special case of approximation 3 where only direct crossings are treated. +3. Split the current from direct and indirect corner crossings to each of the neighboring surfaces and weight the current contribution to each surface based on the length of surfaces swept through by the track. + +Note that tracks are not physically moved in any of these cases; rather, we make the assumption that they are moved when we tally the surface currents. In OpenMOC we have implemented approximation 2 where only direct corner crossings are treated; indirect crossings are tallied only on the surface that is directly crossed by a track. While applying approximation 3 would be more accurate, this would incur additional storage requirements as each segment that crosses a surface needs to know which surface(s) it crosses and a weight for splitting the current contribution to each surface crossed. Illustrations of the approximations applied to direct and indirect surface crossings are illustrated in :ref:`Figure 6 `. + +.. _figure-corner-crossing-2: + +.. figure:: ../../img/corner-crossing-2.png + :align: center + :figclass: align-center + :width: 800 px + + **Figure 6**: Illustration of approximations applied to direct (above) and indirect (below) corner crossings. The approximation applied is denoted by the number in the circle. The blue dashed lines bound the track sweeping area and the red dashed lines separate partially weighted tracks. + +The tallies for a track that crosses from cell :math:`(i,j)` to :math:`(i+1,j+1)` with approximation 1 include a tally on the surface between cell :math:`(i,j)` to :math:`(i+1,j)` and on the surface between cells :math:`(i+1,j)` to :math:`(i+1,j+1)`. The current must be tallied on the second surface in order to preserve neutron balance ensure that neutrons traveling on the track get transferred from cell :math:`(i,j)` to :math:`(i+1,j+1)`. It is also important that the track be assigned to the same surface for both forward and reverse tracking. + +The tallies with approximation 2 are simply half-weighted tallies for tracks that pass on either side of the corner: + +.. math:: + :label: eqn-corner-crossing + + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2},j} += \frac{1}{2} \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i,j + \frac{1}{2}} += \frac{1}{2} \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i + 1, j + \frac{1}{2}} += \frac{1}{2} \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2}, j + 1} += \frac{1}{2} \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \epsilon_{k,g,p} + +where: + +.. math:: + :label: eqn-corner-tally-flux + + \epsilon_{k,g,p} = 2 \pi \omega_{m(k)} \omega_k \omega_p \sin \theta_p \Psi_{k,g,p} + +The first summation in :eq:`eqn-corner-crossing` is over the tracks that directly cross through corner :math:`(i+\frac{1}{2},j+\frac{1}{2})`. Like the tallies in approximation 1, the tallies used in approximation 2 include tallies for the surface of the adjacent cell to the diagonal cell. The tallies with approximation 3 are slightly more complicated as they include the position at which the track crosses the surface and the position of the corner. Let's assume that a track crosses the surface between cells :math:`(i,j)` and cell :math:`(i+1,j)` at point :math:`(x_k, y_k)` and the corner of interest is at point :math:`(x_{i+\frac{1}{2}}, y_{j+\frac{1}{2}})` as shown in :ref:`Figure 7 `. + +.. _figure-corner-crossing-3: + +.. figure:: ../../img/corner-crossing-3.png + :align: center + :figclass: align-center + :width: 500 px + + **Figure 7**: Illustration of an indirect corner crossing with labeled surface intersections and corner point. + +The tallies for tracks that directly or indirectly intersect the corner illustrated in :ref:`Figure 7 ` and described in :eq:`eqn-corner-crossing-3`. + +.. math:: + :label: eqn-corner-crossing-3 + + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2},j} += \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \bigg(0.5 - \frac{\sqrt{(x_{k} - x_{i+\frac{1}{2}})^2}}{\tilde{\omega_k}} + \frac{\sqrt{(y_{k} - y_{j+\frac{1}{2}})^2}}{\tilde{\omega_k}}\bigg) \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i,j + \frac{1}{2}} += \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \bigg(0.5 + \frac{\sqrt{(x_{k} - x_{i+\frac{1}{2}})^2}}{\tilde{\omega_k}} - \frac{\sqrt{(y_{k} - y_{j+\frac{1}{2}})^2}}{\tilde{\omega_k}}\bigg) \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i + 1, j + \frac{1}{2}} += \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \bigg(0.5 - \frac{\sqrt{(x_{k} - x_{i+\frac{1}{2}})^2}}{\tilde{\omega_k}} + \frac{\sqrt{(y_{k} - y_{j+\frac{1}{2}})^2}}{\tilde{\omega_k}}\bigg) \epsilon_{k,g,p} \\ + \tilde{J}_{\mathbf{g}}^{i + \frac{1}{2}, j + 1} += \sum_{k \cap (i+\frac{1}{2},j+\frac{1}{2})} \sum_{g \in \mathbf{g}} \bigg(0.5 + \frac{\sqrt{(x_{k} - x_{i+\frac{1}{2}})^2}}{\tilde{\omega_k}} - \frac{\sqrt{(y_{k} - y_{j+\frac{1}{2}})^2}}{\tilde{\omega_k}}\bigg) \epsilon_{k,g,p} + +where the summation is over the tracks that directly and indirectly cross through corner :math:`(i+\frac{1}{2},j+\frac{1}{2})`. All other surface crossings are treated with :eq:`eqn-surf-avg-tallied-current-3`. + +.. _cmfd-matrix-form: + +Matrix form of CMFD method +========================== + +Going back to :eq:`eqn-dif-eqn-simple` and inserting the nonlinear diffusion coefficients from :eq:`eqn-dif-cor-factor`, the finite difference form of the diffusion equation over a mesh cell becomes: + +.. math:: + :label: eqn-dif-matrix-1 + + \Delta y^{i,j} (\hat{D}_{\mathbf{g}}^{i-\frac{1}{2},j} [\phi_{\mathbf{g}}^{i,j} - \phi_{\mathbf{g}}^{i-1,j}] + \tilde{D}_{\mathbf{g}}^{i-\frac{1}{2},j} [\phi_{\mathbf{g}}^{i,j} + \phi_{\mathbf{g}}^{i-1,j}]) - \Delta y^{i,j} (\hat{D}_{\mathbf{g}}^{i+\frac{1}{2},j} [\phi_{\mathbf{g}}^{i+1,j} - \phi_{\mathbf{g}}^{i,j}] + \tilde{D}_{\mathbf{g}}^{i+\frac{1}{2},j} [\phi_{\mathbf{g}}^{i+1,j} + \phi_{\mathbf{g}}^{i,j}]) + \Delta x^{i,j} (\hat{D}_{\mathbf{g}}^{i,j-\frac{1}{2}} [\phi_{\mathbf{g}}^{i,j} - \phi_{\mathbf{g}}^{i,j-1}] + \tilde{D}_{\mathbf{g}}^{i,j-\frac{1}{2}} [\phi_{\mathbf{g}}^{i,j} + \phi_{\mathbf{g}}^{i,j-1}]) - \\ + \Delta x^{i,j} (\hat{D}_{\mathbf{g}}^{i,j+\frac{1}{2}} [\phi_{\mathbf{g}}^{i,j+1} - \phi_{\mathbf{g}}^{i,j}] + \tilde{D}_{\mathbf{g}}^{i,j+\frac{1}{2}} [\phi_{\mathbf{g}}^{i,j+1} + \phi_{\mathbf{g}}^{i,j}]) + \Delta x^{i,j} \Delta y^{i,j} \varSigma_{\mathbf{g}}^{R,i,j} \phi_{\mathbf{g}}^{i,j} = \Delta x^{i,j} \Delta y^{i,j} \frac{\chi_{\mathbf{g}}^{i,j}}{k_{eff}} \sum_{{\mathbf{g}} \prime = 1}^{\mathbf{G}} \nu \varSigma_{{\mathbf{g}} \prime}^{F,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + \Delta x^{i,j} \Delta y^{i,j} \sum_{\substack{{\mathbf{g}} \prime = 1 \\ {\mathbf{g}} \prime \neq {\mathbf{g}}}}^{\mathbf{G}} \varSigma_{{\mathbf{g}} \prime \rightarrow {\mathbf{g}}}^{S,i,j} \phi_{{\mathbf{g}} \prime}^{i,j} + +We can condense the CMFD diffusion equations down to matrix form to get the following generalized non-hermitian eigenvalue problem: + +.. math:: + :label: eqn-dif-matrix-2 + + A \phi = \frac{1}{k_{eff}} M \phi + +The matrices can be arranged in either a group-wise or cell-wise ordering. The CMFD implementation in OpenMOC uses a cell-wise order where the A matrix is composed of a block diagonal with blocks of size G x G and four off-diagonals for transport to neighboring cells as shown in :ref:`Figure 8 `. + +.. _figure-cmfd-matrix: + +.. figure:: ../../img/cmfd-matrix.png + :align: center + :figclass: align-center + :width: 800 px + + **Figure 8**: CMFD mesh layout (left) and spy of CMFD A matrix (right) for a 4 x 4 infinite lattice pin-cell problem with 7 energy group cross sections. + +In :ref:`Section 7.7 ` we discuss how this matrix equation will be solved and used to accelerate the solution of the MOC solve. + +.. _cmfd-accel-moc: + +CMFD Accelerated MOC Algorithm +============================== + +The general flowchart for MOC algorithm and CMFD acceleration are shown in :ref:`Figure 6 `. + +.. _figure-cmfd-accel-moc: + +.. figure:: ../../img/cmfd-accel-moc.png + :align: center + :figclass: align-center + :width: 600 px + + **Figure 6**: The solution procedure for CMFD accelerated MOC. + +CMFD acceleration is implemented in OpenMOC by overlaying a regular grid on top of the unstructured flat source region mesh as shown in :ref:`Figure 1 `. During an MOC fixed source iteration, OpenMOC tallies the net currents across the surfaces of each mesh cell. The fixed source iteration algorithm then becomes :ref:`Algorithm 1 `. + +.. _alg-transport-sweep-CMFD: + +.. figure:: ../../img/cmfd-accel-alg-2.png + :align: center + :figclass: align-center + :width: 800 px + + **Algorithm 1**: Fixed source iteration for CMFD accelerated OpenMOC. + +At the end of the fixed source iteration, OpenMOC proceeds to condense the cross sections, flux, and diffusion coefficients according to :eq:`xs-condensation`. The diffusion coefficient coupling terms that link neighboring cells, :math:`\hat{D}` and :math:`\tilde{D}`, are then computed using :eq:`eqn-surf-dif-coef` and :eq:`eqn-dif-cor-factor`. There are two subtle points in computing the nonlinear coupling coefficients :math:`\tilde{D}`. First, the condition :math:`|\tilde{D}| < |\hat{D}|` must be met in order to guarantee the diagonal dominance in the destruction matrix, A. If this condition is not met, the surface diffusion coefficients will be re-computed such that they are equal in magnitude and satisfy :eq:`eqn-alg-net-current-cor`. Secondly, under-relaxation of the nonlinear correction factor is used to accelerate and maintain stability of the eigenvalue convergence rate for large, heterogeneous geometries. OpenMOC does so by applying a fixed damping factor on the :math:`\tilde{D}` terms. The nonlinear diffusion coefficients are initially set to zero and modified according to :eq:`eqn-nldif-damp`. + +.. math:: + :label: eqn-nldif-damp + + \tilde{D}^{i+\frac{1}{2},j,(n)}_{\mathbf{g}} = (1 - \omega_d) \tilde{D}^{i+\frac{1}{2},j,(n-1)}_{\mathbf{g}} + \omega_d \frac{- \hat{D}^{i+\frac{1}{2},j,(n)}_{\mathbf{g}} (\phi^{i+1,j,(n)}_{\mathbf{g}} - \phi^{i,j,(n)}_{\mathbf{g}}) - \frac{\tilde{J}_{\mathbf{g}}^{i+\frac{1}{2},j,(n)}}{\Delta y^{i,j}}}{(\phi_{\mathbf{g}}^{i+1,j,(n)} + \phi^{i,j,(n)}_{\mathbf{g}})} + +Where :math:`\omega_d` is the under-relaxation dampening factor and :math:`(n)` is the fixed source iteration. OpenMOC uses power iterations to solve the generalized non-Hermitian eigenvalue problem as shown in :ref:`Algorithm 2 `. In each power iteration, the linear system is solved using a parallel (red-black) implementation of the successive over-relaxation method as shown in :ref:`Figure 9 `. Upon convergence of the CMFD diffusion problem, OpenMOC performs prolongation by multiplying each FSR's scalar flux by the ratio of the converged coarse mesh scalar flux to the initial coarse mesh scalar flux in the acceleration step: + +.. math:: + :label: eqn-cmfd-prolongation + + \Phi_{r,g} = \Phi_{r,g} \frac{\phi^{i,j,new}_{\mathbf{g}}}{\phi^{i,j,old}_{\mathbf{g}}} \qquad \forall \quad r \in (i,j) + +where :math:`\phi^{i,j,old}_{\mathbf{g}}` is the coarse mesh scalar flux computed using equation :eq:`xs-condensation` and :math:`\phi^{i,j,new}_{\mathbf{g}}` is the converged CMFD coarse mesh scalar flux. + +.. _alg-cmfd-solve: + +.. figure:: ../../img/cmfd-solve-alg.png + :align: center + :figclass: align-center + :width: 800 px + + **Algorithm 2**: Power Iteration Outer Loop Source Iteration. + +Instead of splitting the corner currents during the MOC fixed source iteration, OpenMOC tallies the corner currents as independent surfaces and then splits the corner currents between their neighboring surfaces in step 2 of :ref:`Figure 8 `. With the corner currents accounted for, the surface diffusion coefficients are then computed just prior to the power method eigenvalue solve. The first step in the power method inner loop iteration is to solve a linear fixed fission source problem. The SOR method is used to solve the linear system with the SOR relaxation factor denoted as :math:`\omega_r` as described by :ref:`Figure 9 `. While more computationally efficient methods exist for solving generalized non-Hermitian eigenvalue problems like Krylov-subspace methods, we chose the power method for its simplicity and stability. Additionally, more computationally efficient methods exist for solving the linear system like Generalized Minimum Residual (GMRES) and stabilized biconjugate gradient (BiCGStab), but these methods are conceptually more challenging and difficult to implement. In our analysis we found the power method with SOR performs sufficiently well for most problems that will be studied. + +.. _alg-SOR-solve: + +.. figure:: ../../img/cmfd-SOR-solve.png + :align: center + :figclass: align-center + :width: 800 px + + **Figure 9**: Successive over-relaxation numerical flux inversion. + + +References +========== + +.. [Smith-1983] K. Smith, "Nodal Method Storage Reduction by Non-linear Iteration." *Transactions of the American Nuclear Society*, **44**, (1983). + +.. [Yamamoto-2002] A. Yamamoto, "Cell Based CMFD Formulation for Acceleration of Whole-Core Method of Characteristics Calculations." *Journal of the Korean Nuclear Society*, **34**, pp. 250-258 (2002). + +.. [Yamamoto-2005] A. Yamamoto, "Generalized Coarse-Mesh Rebalance Method for Acceleration of Neutron Transport Calculations." *Journal of Nuclear Science and Engineering*, **151**, pp. 274-281 (2005). + +.. [Yamamoto-2008] A. Yamamoto, "Implementation of Two-Level Coarse Mesh Finite Difference Acceleration in an Arbitrary Geometry, Two-Dimensional Discrete Ordinates Transport Method." *Journal of Nuclear Science and Engineering*, **158**, pp. 289-298 (2008). + +.. [Lewis] E. Lewis and W. Miller, Jr., "Computational Methods of Neutron Transport." *John Wiley \& Sons* (1984). + +.. [Li] L. Li, "A Low Order Acceleration Scheme for Solving the Neutron Transport Equation." M.S. Thesis, Massachusetts Institute of Technology (2013). + +.. [Smith-2002] K. Smith and J. D. Rhodes, "Full-Core, 2-D, LWR Core Calculations with CASMO-4E." *Proceedings of PHYSOR*, Seoul, South Korea (2002). + +.. [Larsen] E. Larsen, "Infinite Medium Solutions to the Transport Equation, :math:`S_n` Discretization Schemes, and the Diffusion Approximation. " *Proceedings of the Joint International Topical Meeting on Mathematics and Computation and Supercomputing in Nuclear Applications*, Salt Lake City, UT, USA (2001). diff --git a/docs/source/methods/constructive_solid_geometry.rst b/docs/source/methods/constructive_solid_geometry.rst new file mode 100644 index 000000000..0f97c2b5f --- /dev/null +++ b/docs/source/methods/constructive_solid_geometry.rst @@ -0,0 +1,272 @@ +.. _constructive_solid_geometry: + +=========================== +Constructive Solid Geometry +=========================== + +OpenMOC uses `constructive solid geometry`_ (CSG) to represent complex reactor models in software. The constructive solid geometry formulation is the method of choice for many advanced modeling software packages, including some Computer-aided Design (CAD) implementations. CSG allows complex spatial models to be built using boolean operations - such as intersections and unions - of simple surfaces and building blocks termed *primitives*, as illustrated in :ref:`Figure 1 ` [Wikipedia]_. The constructive solid geometry approach is well suited for reactor models which typically are highly structured and contain repeating patterns. This is the case for commercial PWRs and BWRs whose cores are built out of a rectangular lattice of fuel assemblies, each of which is a rectangular lattice of fuel pins. + +.. _figure-csg-tree: + +.. figure:: ../../img/csg-tree.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 1**: A binary tree of CSG primitives. + +There are a number of benefits to using the CSG formulation. First, CSG enables simulation codes to significantly reduce the memory footprint required to model the geometry. For example, rather than representing each fuel pin explicitly in memory, a *fuel pin primitive* is represented by a single data structure. A second major benefit to the CSG formulation is that it is a general and extensible approach which allows for ray tracing routines to be written in an abstract fashion that is independent of the primitives themselves. + +:ref:`Section 3.2 ` + +OpenMOC's implementation of the routines and data structures for CSG are in large part inspired by those used in the OpenMC code. The following sections describe the primitives and algorithms used for CSG modeling in OpenMOC. + + +.. _csg-formulation: + +CSG Formulation +=============== + +The constructive solid geometry formulation in OpenMOC is predicated upon the use of several key objects which allow one to construct a spatial model from simple primitives in a hierarchical fashion. The following sections describe each of these fundamental objects in order of increasing complexity. The reader should note that the CSG formulation in OpenMOC is presently only capable of describing the 2D :math:`xy`-plane, though an extension to 3D would be straightforward. + +:ref:`Section 4.1.1 ` develops the formulation for *surfaces* which are used to divide space into separate unique *halfspaces*. :ref:`Section 4.1.2 ` describes *universes* which represent the entirety of 2D (or 3D) space and provide a "clean pallet" upon which one can build a simple structure of *cells*. :ref:`Section 4.1.3 ` describes *cells* which contain one or more *surfaces* that bound a subset of space filled by either a material or a *universe*. :ref:`Section 4.1.4 ` describes *lattices* which are used to create a bounded union of universes through a series of coordinate transformations. A typical hierarchy for the way in which surfaces, universes, cells and lattices are constructed to represent a reactor model in OpenMOC is illustrated in :ref:`Figure 2 `. + +.. _figure-csg-primitives-hierarchy: + +.. figure:: ../../img/csg-primitives-hierarchy.png + :align: center + :figclass: align-center + :width: 500px + + **Figure 2**: A hierarchy of OpenMOC primitives. + + +.. _surfaces-halfspaces: + +----------------------- +Surfaces and Halfspaces +----------------------- + +The fundamental primitive in OpenMOC is a *surface*. A 2D surface in the :math:`xy`-plane is defined as the set of points that satisfy :math:`f(x,y) = 0` for some function :math:`f` that will henceforth be termed the *potential function* of the surface. The potential divides the :math:`xy`-plane into two *halfspaces*. The set of coordinates for which :math:`f(x,y) < 0` is called the *positive halfspace* while those coordinates for which :math:`f(x,y) > 0` collectively form the *negative halfspace*. :ref:`Figure 3 ` illustrates the concepts of halfspaces for an arbitrary elliptical surface. + +.. _figure-halfspace: + +.. figure:: ../../img/csg-halfspace.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 3**: An elliptical surface primitive and its halfspaces. + +For a surface primitive to be incorporated into the OpenMOC CSG framework, the ray tracing routines require the primitive to include a method to find the intersection point(s) on the surface along some unit trajectory vector :math:`\hat{n} = [u \; v]^T` originating from any point :math:`(x,y)`. A depiction of this is given in :ref:`Figure 4 ` for the parametrized distance :math:`d` between :math:`(x,y)` and the surface. + +.. _figure-surface-intersection: + +.. figure:: ../../img/csg-halfspace-intersection.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 4**: A trajectory's intersection point with a surface. + +Presently, OpenMOC includes surface primitive types that are most useful for constructing LWR models. These surfaces are from a subset of potential functions called *quadratic surfaces* as discussed in the following section. + + +.. _csg-quadratic-surfaces: + +Quadratic Surfaces +------------------ + +A generalized quadratic surface in 2D is a second order surface with following form: + +.. math:: + :label: general-quadratic-surface + + f(x,y) = Ax^2 + By^2 + Fxy + Px + Qy + D = 0 + +Quadratic surfaces include planes, cylinders and ellipsoids. The quadratic surface primitives available in OpenMOC at the date of this writing are displayed in :ref:`Table 1 `. + +.. _table-openmoc-surface-primitives: + ++----------------------+------------+------------------------------------------+-------------------------+ +| Surface | Class | Potential Equation | Parameters | ++======================+============+==========================================+=========================+ +| Arbitrary plane | Plane | :math:`Px + Qy + D = D` | :math:`{P\;Q\;D}` | ++----------------------+------------+------------------------------------------+-------------------------+ +| Plane perpendicular | XPlane | :math:`x - x_0 = 0` | :math:`{x_0}` | +| to :math:`x`-axis | | | | ++----------------------+------------+------------------------------------------+-------------------------+ +| Plane perpendicular | YPlane | :math:`y - y_0 = 0` | :math:`{y_0}` | +| to :math:`y`-axis | | | | ++----------------------+------------+------------------------------------------+-------------------------+ +| Circle in the | ZCylinder | :math:`(x-x_0)^2 + (y-y_0)^2 - R^2 = 0` | :math:`{x_0, y_0, R}` | +| :math:`xy`-plane | | | | ++----------------------+------------+------------------------------------------+-------------------------+ + +**Table 1**: Quadratic surface primitives in OpenMOC. + +The following sections develop the methodology used in OpenMOC to compute the distance from any point :math:`(x,y)` in the :math:`xy`-plane to each of the surfaces in :ref:`Table 1 `. + + +.. _arbitrary-plane: + +Arbitrary Plane +--------------- + +An arbitrary plane is described by the following potential equation: + +.. math:: + :label: arbitrary-plane-potential + + f(x,y) = Px + Qy + D = 0 + +To find the intersection point along some trajectory with a Plane, substitute the intersection point on the surface :math:`(x+du, y+dv)` into the potential equation and rearrange to find the following parametrized distance :math:`d`: + +.. math:: + :label: arbitrary-plane-distance + + f(x+du, y+dv) = P(x+du) + Q(y+dv) + D = 0 \;\;\; \Rightarrow \;\;\; d = \frac{D - Px - Qy}{Pu + Qv} + + +.. _xplane: + +XPlane +------ + +A plane perpendicular to the :math:`x`-axis is described by the following potential equation: + +.. math:: + :label: xplane-potential + + f(x,y) = Px + D = 0 \;\;\; \Rightarrow \;\;\; x - x_0 = 0 + +To find the intersection point along some trajectory with a XPlane, substitute the intersection point on the surface :math:`(x+du, y+dv)` into the potential equation and rearrange to find the following parametrized distance :math:`d`: + +.. math:: + :label: xplane-distance + + f(x+du, y+dv) = (x + du) - x_0 = 0 \;\;\; \Rightarrow \;\;\; d = \frac{x-x_0}{u} + + +.. _yplane: + +YPlane +------ + +Similar to the XPlane, a plane perpendicular to the :math:`y`-axis is described by the following potential equation: + +.. math:: + :label: yplane-potential + + f(x,y) = Qy + D = 0 \;\;\; \Rightarrow \;\;\; y - y_0 = 0 + +To find the intersection point along some trajectory with a YPlane, substitute the intersection point on the surface :math:`(x+du, y+dv)` into the potential equation and rearrange to find the following parametrized distance :math:`d`: + +.. math:: + :label: yplane-distance + + f(x+du, y+dv) = (y + dv) - y_0 = 0 \;\;\; \Rightarrow \;\;\; d = \frac{y-y_0}{v} + + +.. _zcylinder: + +ZCylinder +--------- + +A circle in the :math:`xy`-plane centered at :math:`(x_0, y_0)` with radius :math:`R` is described by the following potential equation: + +.. math:: + :label: circle-potential + + f(x,y) = (x-x_0)^2 + (y-y_0)^2 - R^2 = 0 + +To find the intersection point along some trajectory with a ZCylinder, substitute the intersection point on the surface :math:`(x+du, y+dv)` into the potential equation, define :math:`\Delta_{x} = x - x_0` and :math:`\Delta_{y} = y - y_0`, and rearrange to find the following parametrized distance :math:`d`: + +.. math:: + :label: circle-distance + + f(x+du, y+dv) = (\Delta_{x} + du)^2 + (\Delta_{y} + dv)^2 - R^2 = 0 + +.. math:: + :label: circle-distance-2 + + d = \frac{-\Delta_{x}y - \Delta_{y}v \pm \sqrt{[-\Delta_{x}u - \Delta_{y}v]^2 - (u^2+v^2)[\Delta_{x}^2 + \Delta_{y}^2 - R^2]}}{(u^2 + v^2)} + +The parametrized distance is in the form of the quadratic formula, and there may be one or two real solutions, or two complex solutions. In the case of one solution, it indicates that the trajectory vector :math:`\hat{n}` merely glances the surface of the ZCylinder. The two solution case represents a trajectory vector that intersects the ZCylinder surface and passes through on the opposite side. Complex solutions are unphysical and represent the fact that the trajectory will not pass through the circle at all. + + +.. _cells: + +----- +Cells +----- + +A *cell* is defined to be the region bounded by a boolean combination of surface halfspaces. Presently, OpenMOC only permits the use of halfspace intersections and does not support other boolean operations such as unions and differences. The region defined by the cell is subsequently filled by either a material or a *universe*, described in the following section. + +:ref:`Figure 5 ` illustrates the use of five surface halfspaces to make up a simple pin cell. The halfspace for each surface is indicated by ":math:`+`" or ":math:`-`" symbols, while each cell is uniquely identified by a color and number. The fuel pin is described by the negative halfspace of the ZCylinder surface, while the moderator is made up of the intersection of the positive halfspace of the ZCylinder and positive/negative halfspaces of the left/right and bottom/top XPlanes and YPlanes, respectively. + +.. _figure-cells-pin-cell: + +.. figure:: ../../img/csg-cells-halfspace-intersection.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 5**: Two cells representing a fuel pin cell. + + +.. _universes: + +--------- +Universes +--------- + +A *universe* is a collection of one or more cells that fill the entirety of the :math:`xy`-plane. Each cell may be filled with a material or a separate universe. Universes allow unique structures to be created from cells, and for simple replication of that structure throughout a model by placing it in various locations throughout the geometry. The universe-based CSG formulation in OpenMOC is similar to that used in Monte Carlo neutron transport codes such as [OpenMC]_, [MCNP]_ and [Serpent]_. + +A universe of 10 cells constructed from the halfspace intersections of two XPlanes, two YPlanes and one ZCylinder surface is depicted in :ref:`Figure 6 `. The halfspace for each surface is indicated by ":math:`+`" or ":math:`-`" symbols, while each cell is uniquely identified by a color and number. + +.. _figure-universe-cells: + +.. figure:: ../../img/surfs-cells.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 6**: A universe composed of 10 cells. + + +.. _lattices: + +-------- +Lattices +-------- + +*Lattices* are an extremely useful construct for modeling regular, repeating structures. This is especially the case for reactor cores which typically contain rectangular or hexagonal arrays of fuel pins. For this reason, lattices are a common structure in many neutron transport codes, such as OpenMC, MCNP and Serpent. + +OpenMOC currently only contains a single lattice implementation for 2D Cartesian arrays. Each lattice is uniquely specified by the number of array elements along the :math:`x` and :math:`y` axes, the width and height of each lattice cell, and the universe to *fill* each lattice cell. The lattice specification represents a coordinate transformation such that the center of each lattice cell maps to the origin of the universe within it. This allows for a single universe to be replicated in some or all lattice cells without redundantly storing the universe many times in memory. + +:ref:`Figure 7 ` illustrates a simple 4 :math:`\times` 4 lattice, with each lattice cell filled by one of three different universes. Each universe contains two cells representing the moderator and a fuel pin of some diameter. + +.. _figure-lattice-cells: + +.. figure:: ../../img/csg-lattice-cells.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 7**: A 4 :math:`\times` 4 lattice. + + + +References +========== + +.. [Wikipedia] Wikipedia, "Constructive Solid Geometry," http://en.wikipedia.org/wiki/Constructive_solid_geometry (2013). + +.. [OpenMC] P. Romano and B. Forget, "The OpenMC Monte Carlo Particle Transport Code." *Annals of Nuclear Energy*, **51**, pp. 274-281 (2013). + +.. [MCNP] X-5 Monte Carlo Team, "MCNP - A General Monte Carlo N-Particle Transport Code, Version 5." *Technical Report LA-UR-03-1987*, Los Alamos National Laboratory (2008). + +.. [Serpent] J. Leppanen, "Serpent - A Continuous Energy Monte Carlo Reactor Physics Burnup Calculation Code," http://montecarlo.vtt.fi/download/Serpent_manual.pdf (2013). + +.. _constructive solid geometry: http://en.wikipedia.org/wiki/Constructive_solid_geometry diff --git a/docs/source/methods/eigenvalue_calculations.rst b/docs/source/methods/eigenvalue_calculations.rst new file mode 100644 index 000000000..8d82243d6 --- /dev/null +++ b/docs/source/methods/eigenvalue_calculations.rst @@ -0,0 +1,247 @@ +.. _eigenvalue_calculations: + +======================= +Eigenvalue Calculations +======================= + +An eigenvalue calculation, also referred to as a criticality calculation, is a +transport simulation wherein the source of neutrons includes a fissionable material. Some common eigenvalue calculations include the simulation of nuclear reactors, spent fuel pools, nuclear weapons, and other fissile systems. The reason they are called *eigenvalue* calculations is that the transport equation becomes an eigenvalue equation if a fissionable source is present since then the source of neutrons will depend on the flux of neutrons itself. + +This section will explore the theory behind and implementation of eigenvalue +calculations in OpenMOC by outlining the algorithms used to iteratively solve the MOC equations for the eigenvalue :math:`k_{eff}` and eigenvector :math:`\Phi_{g,i} \;\; \forall \; g,i`. + + +.. _moc-iteration-scheme: + +MOC Iteration Scheme +==================== + +The MOC algorithm for the OpenMOC code uses a nested iteration scheme to solve for the source and scalar flux. The inner iteration solves for an approximate scalar flux assuming a fixed source. The outer iteration computes an updated source based on the inner iteration's approximation to the flux that results from the fixed source. The remainder of this section develops the methodology for this nested iteration scheme. + +First, define vectors of the scalar flux and source in each energy group and flat source region: + +.. math:: + :label: vector-scalar-flux + + \mathbf{\Phi} = \left[\Phi_{1,1}, \Phi_{1,2}, ..., \Phi_{1,G}, \Phi_{2,1}, ..., \Phi_{I,G}\right]^T + +.. math:: + :label: vector-source + + \mathbf{Q} = \left[Q_{1,1}, Q_{1,2}, ..., Q_{1,G}, Q_{2,1}, ..., Q_{I,G}\right]^T + +The generalized eigenvalue equation in reactor physics criticality calculations is given by the following: + +.. math:: + :label: generalized-eigenvalue-eqn + + \mathcal{M}\mathbf{\Phi} = \frac{1}{k_{eff}}\mathcal{F}\mathbf{\Phi} + +The operator :math:`\mathcal{M}` can be split into two components: :math:`\mathcal{A}` to represent streaming and absorption and :math:`\mathcal{S}` to represent in-scattering of neutrons. Equation :eq:`generalized-eigenvalue-eqn` can now be expressed as follows: + +.. math:: + :label: split-generalized-eigenvalue-eqn + + \left(\mathcal{A} - \mathcal{S}\right)\mathbf{\Phi} = \frac{1}{k_{eff}}\mathcal{F}\mathbf{\Phi} + +This is rearranged such that the scattering component is on the right hand side: + +.. math:: + :label: rearrange-generalized-eigenvalue-eqn + + \mathcal{A}\mathbf{\Phi} = \frac{1}{k_{eff}}\mathcal{F}\mathbf{\Phi} + \mathcal{S}\mathbf{\Phi} + +The right hand side is recognized to be equivalent to the total neutron source :math:`\mathbf{Q}`: + +.. math:: + :label: generalized-eigenvalue-source + + \mathcal{A}\mathbf{\Phi} = \mathbf{Q} + +An iterative scheme can be applied to solve this equation, where :math:`n` is used to denote the outer iteration number. The outer iteration is used to compute the source based on the scalar flux approximation from the previous iteration: + +.. math:: + :label: moc-source-iteration + + \mathbf{Q}^{(n+1)} = \frac{1}{k_{eff}^{(n)}}\mathbf{F}\mathbf{\Phi}^{(n)} + \mathcal{S}\mathbf{\Phi}^{(n)} + +Next, an inner iteration applies the inverse operator :math:`\mathcal{A}^{-1}` to solve a fixed source problem for the flux resulting from the source :math:`\mathbf{Q}^{(n+1)}`: + +.. math:: + :label: moc-flux-iteration + + \mathbf{\Phi}^{(n+1)} = \mathcal{A}^{-1}\mathbf{Q}^{(n+1)} + +Finally, the ratio of the :math:`L_2` norm of the area-integrated fission source production to absorption and leakage (streaming) loss from iteration :math:`n` is used to compute the neutron multiplication factor for iteration :math:`n+1`: + +.. math:: + :label: moc-keff-iteration + + k_{eff}^{(n+1)} = \frac{||\mathcal{F}\mathbf{\Phi}^{(n+1)}||_2}{||(\mathcal{A-S})\mathbf{\Phi}^{(n+1)}||_2} + +These equations define the iterative MOC methodology applied in the OpenMOC code. :ref:`Section 3.2 ` presents the source update algorithm used by the outer iteration to solve :eq:`moc-source-iteration`. :ref:`Section 3.3 ` presents OpenMOC's transport sweep algorithm used for the inner fixed source iteration defined by :eq:`moc-flux-iteration`. + + +.. _source-update-algorithm: + +Source Update Algorithm +======================= + +The outer iteration updates the source according to :eq:`moc-source-iteration` from the fixed source flux approximation computed by :eq:`moc-flux-iteration`. This process is methodically described by :ref:`Algorithm 1 `: + +.. _figure-source-update: + +.. figure:: ../../img/source-update-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 1**: FSR source update. + + +.. _transport-sweep-algorithm: + +Transport Sweep Algorithm +========================= + +The inner iteration in OpenMOC solves the fixed source problem given in :eq:`moc-flux-iteration`. The fixed source flux is solved through the MOC formulation by integrating the angular flux across the geometry for each track. The OpenMOC solver implementation performs this integration to compute the scalar flux for each FSR in each group. By default, OpenMOC guesses a uniform incoming angular flux for each track, normalized to the total source: + +.. math:: + :label: incoming-angular-flux + + \forall \; k, g, p \;\;\;\;\;\;\; \Psi_{k,g,p}^{(n+1)}(0) = \frac{1}{||\mathbf{Q}^{(n)}||_{2}} + +A single inner iteration to compute :math:`\Phi_{g,i}` for all FSRs and energy groups will henceforth be termed a *transport sweep*. Each transport sweep integrates the flux (from the previous iteration) along each track for each energy group while tallying a new flux contribution to each flat source region. A single transport sweep involves five nested loops over azimuthal angles, tracks for each azimuthal angle, segments for each track, energy groups and polar angles. The sets of all azimuthal angles, tracks, track segments, FSRs, energy groups and polar angles are denoted by :math:`M`, :math:`K`, :math:`S`, :math:`I`, :math:`G` and :math:`P`, respectively. For notational simplicity, the subset of tracks for azimuthal angle :math:`m` is denoted by :math:`K(m)`, the subset of segments for track :math:`k` is given by :math:`S(k)`, and the FSR for segment :math:`s` is represented as :math:`I(s)`. The leakage tally for vacuum boundary conditions is designated as :math:`L`. A description of the OpenMOC solver's transport sweep is given by :ref:`Algorithm 2 `. + +.. _figure-transport-sweep-algorithm: + +.. figure:: ../../img/transport-sweep-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 2**: Transport sweep algorith. + +:ref:`Figure 1 ` illustrates OpenMOC's sequential approach to sweeping across a sequence of 12 tracks for four azimuthal angles. It is noted that each track represents two azimuthal angles for both *forward* and *reverse* directions which necessarily halves the memory requirements for track storage. + +.. _figure-transport-sweep: + +.. figure:: ../../img/transport-sweep.png + :align: center + :figclass: align-center + :width: 750px + + **Figure 1**: Track sweeping order in OpenMOC. + + +.. _source-convergence-criterion: + +Source Convergence Criterion +============================ + +The spatial shape and energy distribution of the flux across FSRs are iteratively solved for by transport sweeps (:ref:`Algorithm 2 `) and source updates (:ref:`Algorithm 2 `) until the total source for each FSR has converged. The criterion used in OpenMOC for determining whether the source distribution has fully converged is given below: + +.. math:: + :label: source-convergence-criterion + + res \;\; = \;\; \frac{1}{|G||I|}\sqrt{\displaystyle\sum\limits_{i=1}^{I}\displaystyle\sum\limits_{g=1}^{G}\left(\frac{Q_{i,g}^{(n+1)} - Q_{i,g}^{(n)}}{Q_{i,g}^{(n+1)}}\right)^{2}} \;\;\;\; < \;\;\;\; tol + +The tolerance is generally assigned to the range :math:`tol = [10^{-6}, 10^{-4}]`. The overall iterative scheme with inner transport sweep iterations and outer source update iterations, including the source distribution convergence check, is outlined by :ref:`Algorithm 3 `. + +.. _figure-overall-iterative-scheme: + +.. figure:: ../../img/overall-iterative-scheme.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 3**: Overal MOC iteration scheme. + + +.. _exponential-evaluation: + +Exponential Evaluation Method +============================= + +The algorithms described in this section require a number of floating point operations, including addition, subtraction, multiplication and division. The most expensive operation, however, is the exponential evaluation needed to compute :math:`e^{-\tau_{k,i,g,p}}`. All mainstream compilers provide a library with intrinsic mathematical routines, including an exponential evaluator. One method of avoiding the computational cost of explicitly evaluating exponentials is through the use of a linear interpolation table. A sequence of linear approximations to a simple exponential is illustrated in :ref:`Figure 2 `. In addition to reducing the flop count for an exponential evaluation, the table may be constructed to fit completely in :math:`L1` cache and as a result, can improve the memory performance of the MOC transport sweep algorithm. + +.. _figure-exponential-tangent: + +.. figure:: ../../img/exponential-tangent.png + :align: center + :figclass: align-center + :width: 500px + + **Figure 2**: Linear interpolation of an exponential. + +The OpenMOC code incorporates an option to evaluate exponentials using either the compiler's exponential intrinsic function or a linear interpolation table. The following expression for the maximum approximation error :math:`\epsilon` for the linear interpolation method was discussed and validated by [Yamamoto]_: + +.. math:: + :label: exponential-error + + \epsilon = \frac{1}{8}\frac{l^2}{N^2} + O\left(\frac{1}{N^2}\right) \approx \frac{1}{8}\frac{l^2}{N^2} + +In this equation, :math:`l` represents the maximum argument (power) for the exponential and :math:`N` is the number of values in the interpolation table. With respect to the MOC algorithm, :math:`\tau_{max} = \displaystyle\max_{k,i,g}(\tau_{k,i,g}) = \displaystyle\max_{k,i,g}\left(\Sigma_{i,g}^Tl_{k,i}\right)`, where the segment length :math:`l_{k,i}` is kept in the 2D azimuthal plane for reasons that will follow. + +The interpolation table is constructed as follows. First, :eq:`exponential-error` can be rearranged such that :math:`\epsilon` becomes a selectable parameter for the algorithm to achieve an arbitrarily small approximation error: + +.. math:: + :label: exponential-num-values + + N = \frac{\tau_{max}}{\sqrt{8\epsilon}} + +The argument to the exponential is then subdivided into :math:`N` intervals with equal spacing :math:`\Delta_{N}` in logarithmic space: + +.. math:: + :label: exponential-spacing + + \Delta_{N} = \frac{\tau_{max}}{N} + +The final step is to compute the slope :math:`q_{n}` and y-intercept :math:`b_{n}` for the linear approximation to the exponential for a polar angle :math:`\theta_{p}` within each interval :math:`n \in \{0, 1, 2, ..., N-1\}`: + +.. math:: + :label: exponential-slope + + q_n = \frac{\mathrm{d}}{\mathrm{d}(\tau)}\exp\left(-\frac{\tau}{\sin\theta_p}\right)\bigg|_{\tau=(n+0.5)\Delta_{N}} = -\frac{\exp\left(-\frac{(n + 0.5)\Delta_{N}}{\sin\theta_p}\right)}{\sin\theta_{p}} + +.. math:: + :label: exponential-intercept + + b_n = \exp\left(-\frac{(n+0.5)\Delta_{N}}{\sin\theta_{p}}\right)\left[1 + \frac{(n+0.5)\Delta_{N}}{\sin\theta_{p}}\right] + +The exponential is computed at the midpoint of each interval, :math:`(n+0.5)\Delta_{N}`, to minimize the error in approximating the exponential for the values in the interval. OpenMOC modifies this process by computing array values for each polar angle quadrature point :math:`\theta_{p}` which results in a table with :math:`PN` values instead of just :math:`N`. The reason for this is cache efficiency: at each :math:`n \in \{1, 2, ..., N\}` the values for the exponential with argument :math:`(n+0.5)\Delta_{N}` at each polar angle are contiguously stored in the table. Since the innermost loop in the transport sweep (:ref:`Algorithm 2 `) is over polar angles, the exponential values for each polar angle in the table are pre-fetched and stored in the cache on the first iteration of the loop. Finally, since both a slope and a y-intercept must be stored for each point, the total size of the table is :math:`2PN`. The procedure to construct the linear interpolation table is outlined by :ref:`Algorithm 4 `. + +.. _figure-exponential-interpolation-table: + +.. figure:: ../../img/exponential-interpolation-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 4**: Exponential linear interpolation table construction. + +To compute a linear approximation to an exponential, the following procedure is applied in OpenMOC. First, an index into the table must be computed for a track :math:`k` with segment of length :math:`l_{k,i}` in FSR :math:`i` at energy group :math:`g` using the floor function: + +.. math:: + :label: exponential-index + + n = 2P\lfloor\frac{\Sigma^T_{i,g}l_{k,i}}{\Delta_{N}}\rfloor + +Next, the slope and y-intercept for polar angle :math:`p` are extracted from the table: + +.. math:: + :label: exponential-slope-lookup + + q_{n,p} = t[n+2p] + +.. math:: + :label: exponential-intercept-lookup + + b_{n,p} = t[n+2p+1] + +Finally, the approximation to the exponential is computed using linear interpolation from table :math:`t` at polar angle :math:`p`, + +.. math:: + :label: exponential-approx + + e^{-\tau_{k,i,g,p}} \;\; \approx \;\; q_{n,p}\tau_{k,i,g,p} - b_{n,p} diff --git a/docs/source/methods/index.rst b/docs/source/methods/index.rst new file mode 100644 index 000000000..a4e5d1f8b --- /dev/null +++ b/docs/source/methods/index.rst @@ -0,0 +1,16 @@ +.. _methods: + +====================== +Theory and Methodology +====================== + +.. toctree:: + :numbered: + :maxdepth: 2 + + introduction + method_of_characteristics + eigenvalue_calculations + constructive_solid_geometry + track_generation + cmfd diff --git a/docs/source/methods/introduction.rst b/docs/source/methods/introduction.rst new file mode 100644 index 000000000..758e3adbb --- /dev/null +++ b/docs/source/methods/introduction.rst @@ -0,0 +1,23 @@ +.. _methods_introduction: + +============ +Introduction +============ + +The method of characteristics is one technique for solving partial differential equations. MOC is one of the most common methods with real world applications in production lattice physics tools used today [Smith]_. The prospects for the MOC algorithm as an eventual successor to low-order diffusion-based method for reactor analysis are promising, and extensive research efforts into the efficient use of the algorithm are ongoing [Wu]_, [Taylor]_, [Liu]_, [Talamo]_. As a result, there is an opportunity for advanced parallel algorithms for high performance computing machines and nonlinear acceleration schemes to propel the application of MOC to full-core reactor physics calculations. + +:ref:`Section 2 ` describes how the method of characteristics is applied to solve the steady-state neutron transport equation in OpenMOC. :ref:`Section 3 ` presents the algorithms implemented in OpenMOC to solve the MOC equations. :ref:`Section 4 ` discusses the constructive solid geometry formulation used to represent geometric models in OpenMOC. :ref:`Section 5 ` reviews the angular quadrature and track generation algorithm in OpenMOC. Finally, :ref:`Section 5 ` outlines the parallel algorithms in OpenMOC for high performance computing platforms while :ref:`Section 6 ` describes CMFD, a nonlinear acceleration method in OpenMOC. + + +References +========== + +.. [Smith] K. Smith and J. D. Rhodes, "CASMO-4 Characteristics Methods for Two-Dimensional PWR and BWR Core Calculations." *Transactions of the American Nuclear Society*, **83**, pp. 294 (2000). + +.. [Wu] G. Wu and R. Roy, "A New Characteristics Algorithm for 3D Transport Calculations." *Annals of Nuclear Energy*, **30**, pp. 1-6 (2003). + +.. [Taylor] J. Taylor, D. Knott and A. J. Baratta, "A Method of Characteristics Solution to the OECD/NEA 3D Neutron Transport Benchmark Problem." *Proceedings of the Joint International Topical Meeting on Mathematics and Computation and Supercomputing in Nuclear Applications*, Monterey, CA, USA (2007). + +.. [Liu] Z. Liu, H. Wu, L. Cao, Q. Chen, Y. Li, "A New Three-Dimensional Method of Characteristics for the Neutron Tansport Calculation." *Annals of Nuclear Energy*, **38**, pp. 447-454 (2011). + +.. [Talamo] A. Talamo, "Numerical Solution of the Time Dependent Neutron Transport Equation by the Method of the Characteristics." *Journal of Computational Physics}*, **240**, pp. 248-267 (2013). diff --git a/docs/source/methods/method_of_characteristics.rst b/docs/source/methods/method_of_characteristics.rst new file mode 100644 index 000000000..9de327e83 --- /dev/null +++ b/docs/source/methods/method_of_characteristics.rst @@ -0,0 +1,432 @@ +.. _method_of_characteristics: + +========================= +Method of Characteristics +========================= + +The method of characteristics (MOC) is a widely used technique for solving partial differential equations, including the Boltzmann form of the neutron transport equation [Askew]_. MOC is used to solve the transport equation in 2D by discretizing both polar and azimuthal angles and integrating the multi-group characteristic form of the equation for a particular azimuthal and polar angle quadrature. The following sections detail the derivation of the characteristic form of the 2D neutron transport equation solved in the OpenMOC method of characteristics scheme [Boyd]_. + +:ref:`Section 2.1 ` introduces the Boltzmann form of the neutron transport equation parametrized in 6-dimensional phase space over position, angle and energy. The following several sections introduce the various approximations made to this equation: + +* characteristic transformation (:ref:`Section 2.2 `) +* energy discretization (:ref:`Section 2.3 `) +* discrete ordinates approximation (:ref:`Section 2.4 `) +* isotropic scattering approximation (:ref:`Section 2.5 `) +* flat source approximation (:ref:`Section 2.6 `) +* constant cross-section approximation (:ref:`Section 2.7 `) +* integrating factor solution (:ref:`Section 2.8 `) +* track area approximation (:ref:`Section 2.9 `) +* azimuthal planar projection (:ref:`Section 2.10 `) + +The final equations applied in OpenMOC to solve for the FSR source and scalar flux derived in the following sections are summarized below: + +**The source in each flat source region** + +.. math:: + \boxed{Q_{i,g} = \frac{1}{4\pi}\left(\displaystyle\sum\limits_{g'=1}^G \Sigma^S_{i,g'\rightarrow g}\Phi_{i,g'} + \frac{\chi_{i,g}}{k_{eff}}\displaystyle\sum\limits_{g'=1}^G\nu\Sigma^F_{i,g'}\Phi_{i,g'}\right)} + +**Change in angular flux along a track segment** + +.. math:: + \boxed{\Delta\Psi_{k,i,g,p} = \Psi_{k,g,p}(s') - \Psi_{k,g,p}(s'') = \left(\Psi_{k,g,p}(s') - \frac{Q_{i,g}}{\Sigma^T_{i,g}}\right)(1 - e^{-\tau_{k,i,g,p}})} + +**Scalar flux in each flat source region** + +.. math:: + \boxed{\Phi_{i,g} = \frac{4\pi}{\Sigma_{i,g}}\left[Q_{i,g} + \frac{1}{A_i}\displaystyle\sum\limits_{k\in A_{i}}\displaystyle\sum\limits_{p=1}^{P}\omega_{m(k)}\omega_{p}\omega_{k}\sin\theta_{p}\Delta\Psi_{k,i,g,p}\right]} + + + +.. _section-boltzmann-eqn: + +Introduction to the Boltzmann Equation +====================================== + +The Boltzmann form of the steady-state neutron transport equation is given by the following: + +.. math:: + :label: boltzmann-eqn + + \mathbf{\Omega} \cdot \nabla \Psi(\mathbf{r},\mathbf{\Omega},E) + \Sigma^T(\mathbf{r},E)\Psi(\mathbf{r},\mathbf{\Omega},E) = \int_{0}^{\infty} \mathrm{d}E' \int_{4\pi} \mathrm{d}\mathbf{\Omega'}\Sigma^S(\mathbf{r},{\mathbf{\Omega'}\rightarrow\mathbf{\Omega}},{E'\rightarrow E}) \Psi(\mathbf{r},\mathbf{\Omega'},E') + \frac{\chi(\mathbf{r},E)}{4\pi k_{eff}} \int_{0}^{\infty} \mathrm{d}E' \nu\Sigma^F(\mathbf{r},E') \int_{4\pi} \mathrm{d}\mathbf{\Omega'}\Psi(\mathbf{r},\mathbf{\Omega'},E') + +Each of the variables in use is defined in :ref:`Table 1 `. This is a balance equation between neutrons lost to transport, lost to absorption, produced or lost from scattering and those produced from fission. It should be noted that this equation assumes isotropic emission from fission. + +.. _table-variables: + +======================= =========== +Variable Description +======================= =========== +:math:`\mathbf{r}` Spatial position vector +:math:`\mathbf{\Omega}` Angular direction vector +:math:`E` Neutron energy +:math:`\Psi` Angular neutron flux +:math:`k_{eff}` Effective neutron multiplication factor +:math:`\Sigma^T` Neutron total cross-section +:math:`\Sigma^S` Neutron scattering cross-section +:math:`\Sigma^F` Neutron fission cross-section +:math:`\chi` Energy spectrum for fission neutrons +:math:`\nu` Average number of neutrons emitted per fission +======================= =========== + +**Table 1**: Variables in the Boltzmann equation. + +The first step is to simplify this equation by defining those quantities on the right hand side as the total neutron source :math:`Q(\mathbf{r},\mathbf{\Omega},E)`: + +.. math:: + :label: integral-source + + Q(\mathbf{r},\mathbf{\Omega},E) = \int_{0}^{\infty} \mathrm{d}E' \int_{4\pi} \mathrm{d}\mathbf{\Omega'}\Sigma^S(\mathbf{r},{\mathbf{\Omega'}\rightarrow\mathbf{\Omega}},{E'\rightarrow E}) \Psi(\mathbf{r},\mathbf{\Omega'},E') + \frac{\chi(\mathbf{r},E)}{4\pi k_{eff}} \int_{0}^{\infty} \mathrm{d}E' \int_{4\pi} \mathrm{d}\mathbf{\Omega'} \nu\Sigma^F(\mathbf{r},E')\Psi(\mathbf{r},\mathbf{\Omega'},E') + +The transport equation can now be more concisely written as follows: + +.. math:: + :label: transport-with-source + + \mathbf{\Omega} \cdot \nabla \Psi(\mathbf{r},\mathbf{\Omega},E) + \Sigma^T(\mathbf{r},E)\Psi(\mathbf{r},\mathbf{\Omega},E) = Q(\mathbf{r},\mathbf{\Omega},E) + + +.. _characteristic-transformation: + +The Characteristic Transformation +================================= + +The characteristic form of the Boltzmann equation is found by a change of variables by parametrizing :math:`\mathbf{r}` with respect to some reference location :math:`\mathbf{r_0}`: + +.. math:: + :label: characteristics-parametrization + + \mathbf{r} = (x(s), y(s)) = (x_0+s\mathbf{\Omega_x}, y_0+s\mathbf{\Omega_y}) = \mathbf{r_0}+s\mathbf{\Omega} + +For any location :math:`\mathbf{r}` of interest, each angular direction vector :math:`\mathbf{\Omega'}` is matched to a corresponding reference location :math:`\mathbf{r_{0}'}` defined such that :math:`\mathbf{r} = \mathbf{r_{0}'} + s\mathbf{\Omega'}`. This parametrization for position may be substituted into the source and transport equations to obtain the following form for each: + +.. math:: + :label: source-parametrization + + Q(\mathbf{r},\mathbf{\Omega},E) = \int_{0}^{\infty} \mathrm{d}E' \int_{4\pi} \mathrm{d}\mathbf{\Omega'}\Sigma^S(\mathbf{r_0'}+s\mathbf{\Omega'},{\mathbf{\Omega'}\rightarrow\mathbf{\Omega}},{E'\rightarrow E}) \Psi(\mathbf{r_0'}+s\mathbf{\Omega'},\mathbf{\Omega'},E') + \frac{\chi(\mathbf{r_0}+s\mathbf{\Omega},E)}{4\pi k_{eff}} \int_{0}^{\infty} \mathrm{d}E' \nu\Sigma^F(\mathbf{r_0}+s\mathbf{\Omega},E') \int_{4\pi} \mathrm{d}\mathbf{\Omega'} \Psi(\mathbf{r_0'}+s\mathbf{\Omega'},\mathbf{\Omega'},E') + +.. math:: + :label: boltzmann-parametrization + + \mathbf{\Omega} \cdot \nabla \Psi(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) + \Sigma^T(\mathbf{r_0}+s\mathbf{\Omega},E)\Psi(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) = Q(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) + +Applying the differential operator to the angular flux in :eq:`boltzmann-parametrization` leads to the characteristic form of the Boltzmann equation: + +.. math:: + :label: boltzmann-differential + + \frac{d}{ds}\Psi(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) + \Sigma^T(\mathbf{r_0}+s\mathbf{\Omega},E)\Psi(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) = Q(\mathbf{r_0}+s\mathbf{\Omega},\mathbf{\Omega},E) + +For brevity, the remainder of this section will assume the dependence of :math:`s` on the reference position :math:`\mathbf{r_0}` and :math:`\mathbf{\Omega}` and will simplify this as :math:`\mathbf{r_0} + s\mathbf{\Omega} \rightarrow s` such that the characteristic equation can be written as the following: + +.. math:: + :label: simple-boltzmann-differential + + \frac{d}{ds}\Psi(s,\mathbf{\Omega},E) + \Sigma^T(s,E)\Psi(s,\mathbf{\Omega},E) = Q(s,\mathbf{\Omega},E) + +This equation can be solved through the use of an integrating factor: + +.. math:: + :label: integrating-factor + + e^{-\int_{0}^s\mathrm{d}s'\Sigma^T(s',E)} + +The final analytical solution to the characteristic equation is therefore: + +.. math:: + :label: moc-eqn + + \Psi(s,\mathbf{\Omega},E) = \Psi(\mathbf{r_{0}},\mathbf{\Omega},E)e^{-\int_{0}^s\mathrm{d}s'\Sigma^T(s',E)} + \int_0^s\mathrm{d}s''Q(s'',\mathbf{\Omega},E)e^{-\int_{s''}^s\mathrm{d}s'\Sigma^T(s',E)} + + +.. _multi-group-approximation: + +The Multi-Group Energy Approximation +==================================== + +Equation :eq:`moc-eqn` is defined with :math:`\Psi`, :math:`Q` and :math:`\Sigma^T` as continuous functions of energy. The first approximation to numerically solve this equation is to discretize the energy domain into distinct *energy groups* :math:`g \in G = \{1, 2, ..., G\}` where group :math:`g` spans the continuous range of energies from :math:`E_{g}` to :math:`E_{g-1}`. This is otherwise known as the *multi-group approximation*. The multi-group form of the Boltzmann equation is presented below: + +.. math:: + :label: boltzmann-multigroup + + \mathbf{\Omega} \cdot \nabla \Psi_g(s,\mathbf{\mathbf{\Omega}}) + \Sigma^T_{g}(s)\Psi_g(s,\mathbf{\Omega}) = Q_g(s,\mathbf{\Omega}) + +The characteristic form of the equation given in :eq:`simple-boltzmann-differential` can also be written in multi-group form: + +.. math:: + :label: characteristic-multigroup + + \frac{d}{ds}\Psi_{g}(s,\mathbf{\Omega}) + \Sigma^T_{g}(s)\Psi_{g}(s,\mathbf{\Omega}) = Q_g(s,\mathbf{\Omega}) + +Likewise, the multi-group form of the neutron source :eq:`source-parametrization` is given by: + +.. math:: + :label: source-multigroup + + Q_g(s,\mathbf{\Omega}) = \displaystyle\sum\limits_{g'=1}^G \int_{4\pi} \mathrm{d}\mathbf{\Omega'}\Sigma_{g'\rightarrow g}^S(s,{\mathbf{\Omega'}\rightarrow\mathbf{\Omega}}) \Psi_{g'}(s,\mathbf{\Omega'}) + \frac{\chi_{g}(s)}{4\pi k_{eff}} \displaystyle\sum\limits_{g'=1}^G \nu\Sigma_{g'}^F(s) \int_{4\pi} \mathrm{d}\mathbf{\Omega'} \Psi_{g'}(s,\mathbf{\Omega'}) + +It directly follows from :eq:`moc-eqn` and :eq:`simple-boltzmann-differential` that the solution to the multi-group characteristic neutron transport equation is the following: + +.. math:: + :label: moc-multigroup + + \Psi_g(s,\mathbf{\Omega}) = \Psi_g(\mathbf{r_{0}},\mathbf{\Omega})e^{-\int_{0}^s\mathrm{d}s'\Sigma_g^T(s')} + \int_0^s\mathrm{d}s''Q_g(s'',\mathbf{\Omega})e^{-\int_{s''}^s\mathrm{d}s'\Sigma_g^T(s')} + +Where both :eq:`moc-multigroup` and :eq:`source-multigroup` make use of the energy condensed cross-sections :math:`\Sigma^T`, :math:`\Sigma^F`, :math:`\Sigma^S`, and :math:`\chi`: + +.. math:: + :label: condensed-total-xs + + \Sigma_{g}^T(s) = \frac{\int_{E_{g}}^{E_{g-1}}\mathrm{d}E'\Sigma^T(s,E')\Psi(s,\mathbf{\Omega},E')}{\int_{E_{g}}^{E_{g-1}}\mathrm{d}E'\Psi(s,\mathbf{\Omega},E')} + +.. math:: + :label: condensed-fission-xs + + \Sigma_{g}^F(s) = \frac{\int_{E_{g}}^{E_{g-1}}\mathrm{d}E'\Sigma^F(s,E')\Psi(s,\mathbf{\Omega},E')}{\int_{E_{g}}^{E_{g-}1}\mathrm{d}E'\Psi(s,\mathbf{\Omega},E')} + + +.. math:: + :label: condensed-scatter-xs + + \Sigma_{g'\rightarrow g}^S(s,\mathbf{\Omega'}\rightarrow \mathbf{\Omega}) = \frac{\int_{E_{g'}}^{E_{g'-1}}\mathrm{d}E'\int_{E_{g}}^{E_{g-1}}\mathrm{d}E''\Sigma^S(s,\mathbf{\Omega'}\rightarrow \mathbf{\Omega},E'\rightarrow E'')\Psi(s,\mathbf{\Omega'},E')}{\int_{E_{g'}}^{E_{g'-1}}\mathrm{d}E'\Psi(s,\mathbf{\Omega'},E')} + +.. math:: + :label: condensed-chi + + \chi_{g'\rightarrow g}(s) = \frac{\int_{E_{g'}}^{E_{g'-1}}\mathrm{d}E'\int_{E_{g}}^{E_{g-1}}\mathrm{d}E''\chi(s,E'\rightarrow E'')\nu\Sigma^F(s,\mathbf{\Omega},E')\Psi(s,\mathbf{\Omega'},E')}{\int_{E_{g'}}^{E_{g'-1}}\mathrm{d}E'\nu\Sigma^F(s,\mathbf{\Omega},E')\Psi(s,\mathbf{\Omega'},E')} + +Although :eq:`condensed-chi` assumes a dependence of :math:`\chi` on both the energy of the neutron causing fission :math:`g'` and the fission emission energy group :math:`g`, the former is typically summed over to simplify the multi-group :math:`\chi` to the following approximation: + +.. math:: + :label: condensed-chi-sum + + \chi_{g}(s) = \displaystyle\sum\limits_{g=1}^{G}\chi_{g'\rightarrow g}(s) + + +.. _discrete-ordinates-approximation: + +The Discrete Ordinates Approximation +==================================== + +The discrete ordinates approximation is introduced to approximate the integral over the angular domain in the source :eq:`source-multigroup`. This is equivalent to applying quadrature rules to evaluate the integral over the angular flux using a weighted sum of fluxes at specific angles where weights :math:`w_{m}` are introduced for each of the quadrature points :math:`\mathbf{\Omega_{m}} \; \forall \; m \in \{1, ..., M\}`. + +.. math:: + :label: moc-quadrature + + \Phi_{g}(s) = \int_{4\pi}\mathrm{d}\mathbf{\Omega'}\Psi_{g}(s,\mathbf{\Omega'}) \approx \displaystyle\sum\limits_{m=1}^{M}w_{m}\Psi_{g}(s,\mathbf{\Omega_{m}}) + +The integrated angular flux :math:`\Phi_{g}(s)` is termed the *scalar flux*. Substituting this approximation to the angular flux integral into :eq:`source-multigroup` leads to the following approximation to the source :math:`Q_{m,g}(s) \approx Q_{g}(s,\mathbf{\Omega_{m}})` at each quadrature point :math:`\mathbf{\Omega_{m}}`: + +.. math:: + :label: source-angular-quadrature + + Q_{m,g}(s) = \displaystyle\sum\limits_{g'=1}^G \displaystyle\sum\limits_{m'=1}^{M}w_{m'}\Sigma_{g'\rightarrow g}^S(s,{\mathbf{\Omega_{m'}}\rightarrow\mathbf{\Omega_{m}}}) \Psi_{g'}(s,\mathbf{\Omega_{m'}}) + \frac{\chi_{g}(s)}{4\pi k_{eff}} \displaystyle\sum\limits_{g'=1}^G \displaystyle\sum\limits_{m'=1}^{M}w_{m'}\nu\Sigma_{g'}^F(s)\Psi_{g'}(s,\mathbf{\Omega_{m'}}) + +Substituting this approximation to the source into :eq:`moc-multigroup` one obtains the characteristic solution for the angular flux :math:`\Psi_{m,g}(s) \approx \Psi_g(s,\mathbf{\Omega_{m}})` at each quadrature point :math:`\mathbf{\Omega_{m}}`: + +.. math:: + :label: angular-flux-angular-quadrature + + \Psi_{m,g}(s) = \Psi_{m,g}(\mathbf{r_{0}})e^{-\int_{0}^{s}\mathrm{d}s'\Sigma_g^T(s')} + \int_0^{s_{m}}\mathrm{d}s''Q_{m,g}(s'')e^{-\int_{s''}^{s}\mathrm{d}s'\Sigma_g^T(s')} + +Equations :eq:`source-angular-quadrature` and :eq:`angular-flux-angular-quadrature` may be further decomposed into azimuthal and polar angle quadratures :math:`m \in \{1, 2, ..., M\}` and :math:`p \in \{1, 2, ..., P\}` with weights :math:`w_{m}` and :math:`w_{p}` for the azimuthal plane and axial dimension, respectively: + +.. math:: + :label: source-azimuthal-polar + + Q_{m,p,g}(s) = \displaystyle\sum\limits_{g'=1}^G \displaystyle\sum\limits_{m'=1}^{M} \displaystyle\sum\limits_{p'=1}^{P} w_{m'}w_{p'}\Sigma_{g'\rightarrow g}^S(s,{\mathbf{\Omega_{m',p'}}\rightarrow\mathbf{\Omega_{m,p}}}) \Psi_{g'}(s,\mathbf{\Omega_{m',p'}}) + \frac{\chi_{g}(s)}{4\pi k_{eff}} \displaystyle\sum\limits_{g'=1}^G \displaystyle\sum\limits_{m'=1}^{M} \displaystyle\sum\limits_{p'=1}^{P} w_{m'}w_{p'} \nu\Sigma_{g'}^F(s)\Psi_{g'}(s,\mathbf{\Omega_{m',p'}}) + +.. math:: + :label: angular-flux-azimuthal-polar + + \Psi_{m,p,g}(s) = \Psi_{m,p,g}(\mathbf{r_{0}})e^{-\int_{0}^s\mathrm{d}s'\Sigma_g^T(s')} + \int_0^s\mathrm{d}s''Q_{m,p,g}(s'')e^{-\int_{s''}^s\mathrm{d}s'\Sigma_g^T(s')} + + +.. _isotropic-scattering-approximation: + +The Isotropic Scattering Approximation +====================================== + +An additional approximation that is made to simplify the evaluation of the source in :eq:`source-azimuthal-polar` is to assume that the scattering source is isotropic. This approximation allows the total source to be expressed solely in terms of the scalar flux: + +.. math:: + :label: source-isotropic + + Q_{g}(s) = \frac{1}{4\pi}\left(\displaystyle\sum\limits_{g'=1}^G \Sigma^S_{g'\rightarrow g}(s)\Phi_{g'}(s) + \frac{\chi_{g}(s)}{k_{eff}}\displaystyle\sum\limits_{g'=1}^G\nu\Sigma^F_{g'}(s)\Phi_{g'}(s)\right) + +The subscripts :math:`m` and :math:`p` for the azimuthal and polar angles, respectively, have been dropped from :math:`Q_{g}(s)` since they have been embedded in the integral over angular phase space to obtain the scalar flux :math:`\Phi_{g}(s)`. + + +.. _flat-source-region-approximation: + +The Flat Source Region Approximation +==================================== + +Another common approximation for MOC is to assume that the source :math:`Q_g` is constant across discrete spatial cells termed *flat source regions* (FSRs). This implies that the source does not vary along a characteristic :math:`k` entering FSR :math:`i` at :math:`s'` and exiting at :math:`s''`: + +.. math:: + :label: flat-source + + Q_{i,g} = Q_{g}(s') = Q_{g}(s'') = Q_{g}(s) \;\;\; , \;\;\; s \in [s', s''] + + +.. _constant-xs-approximation: + +The Constant Cross-Section Approximation +======================================== + +In addition to the flat source approximation, it is assumed that the material properties are constant across each FSR. The area-averaged cross-sections for FSR :math:`i \in \{1, 2, ..., I\}` with area :math:`A_{i}` are defined as: + +.. math:: + :label: area-averaged-total-xs + + \Sigma_{i,g}^{T} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Sigma_{g}^T(\mathbf{r})\Phi_{g}(\mathbf{r})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Phi_{g}(\mathbf{r})} + +.. math:: + :label: area-averaged-fission-xs + + \Sigma_{i,g}^{F} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Sigma_{g}^F(\mathbf{r})\Phi_{g}(\mathbf{r})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Phi_{g}(\mathbf{r})} + +.. math:: + :label: area-averaged-scatter-xs + + \Sigma_{i,g'\rightarrow g}^{S} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Sigma_{g'\rightarrow g}^S(\mathbf{r})\Phi_{g'}(\mathbf{r})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Phi_{g'}(\mathbf{r})} + +.. math:: + :label: area-averaged-chi + + \chi_{i,g} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\chi_{g}(\mathbf{r})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}} + +The flat source term :math:`Q_{i,g}` for FSR :math:`i` with area :math:`A_i` is defined in terms of both fission and scattering from the area-averaged scalar flux :math:`\Phi_{g,i}` within the FSR: + +.. math:: + :label: final-source + + Q_{i,g} = \frac{1}{4\pi}\left(\displaystyle\sum\limits_{g'=1}^G \Sigma^S_{i,g'\rightarrow g}\Phi_{i,g'} + \frac{\chi_{i,g}}{k_{eff}}\displaystyle\sum\limits_{g'=1}^G\nu\Sigma^F_{i,g'}\Phi_{i,g'}\right) + +.. math:: + :label: area-averaged-scalar-flux + + \Phi_{i,g} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\Phi_{g}(\mathbf{r})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}} + +The multi-group nuclear cross-sections for each FSR are an input to OpenMOC. As a result, the area-averaging integrals must be performed by some pre-processing method such as Monte Carlo. + + +.. _integrating-factor-solution: + +The Integrating Factor Solution +=============================== + +Each chracteristic may be discretized into *segments* across individual FSRs. This approximation allows :eq:`angular-flux-azimuthal-polar` to be localized to a segment of characteristic :math:`k` across FSR :math:`i` from its entry point at :math:`s'` to exit point at :math:`s''`. By defining the integrating factor in terms of the optical length :math:`\tau_{k,i,g} = \Sigma^T_{i,g}(s''-s')` one may analytically evaluate the integrals in :eq:`angular-flux-azimuthal-polar` and express the outgoing flux along the characteristic as follows: + +.. math:: + :label: angular-flux-fsr + + \Psi_{k,g}(s'') = \Psi_{k,g}(s')e^{-\tau_{k,i,g}} + \frac{Q_{i,g}}{\Sigma^T_{i,g}}(1 - e^{-\tau_{k,i,g}}) + +With minor algebraic rearrangement, the change in angular flux along the characteristic is given by the following: + +.. math:: + :label: delta-angular-flux-fsr + + \Delta\Psi_{k,g} = \Psi_{k,g}(s') - \Psi_{k,g}(s'') = \left(\Psi_{k,g}(s') - \frac{Q_{i,g}}{\Sigma^T_{i,g}}\right)(1 - e^{-\tau_{k,i,g}}) + + +.. _track-area-approximation: + +The Track Area Approximation +============================ + +The key quantity remaining to be determined is the integral over area for the FSR area-averaged scalar flux :math:`\Phi_{g,i}` in :eq:`area-averaged-scalar-flux`. The track area approximation is used to compute this value numerically. + +First, define :math:`l_{k,i}=s''-s'` such that the average angular flux in FSR :math:`i` along characteristic :math:`k` is the following integral: + +.. math:: + :label: avg-angular-flux-integral + + \overline{\Psi}_{k,i,g} = \frac{1}{l_{k,i}}\int_{s'}^{s''} \Psi_{k,i,g}(s) \mathrm{d}s + +Upon evaluating the integral, the average angular flux along the characteristic can be reduced to the following algebraic expression: + +.. math:: + :label: avg-angular-flux + + \overline{\Psi}_{k,i,g} = \frac{1}{l_{k,i}}\left[\frac{\Psi_{k,g}(s')}{\Sigma_{i,g}^T}(1 - e^{-\tau_{k,i,g}}) + \frac{l_{k,i}Q_{i,g}}{\Sigma_{i,g}^T}\left(1 - \frac{(1 - e^{-\tau_{k,i,g}})}{\tau_{k,i,g}}\right)\right] + +Assuming a constant source and cross-sections in FSR :math:`i`, the value given for the average angular flux in :eq:`avg-angular-flux` is exact. In order to exactly compute the area-averaged scalar flux, the average angular flux from every characteristic crossing FSR :math:`i` must be taken into account. This is numerically intractable; hence, an appropriate subset :math:`K` of characteristics, henceforth known as *tracks*, is chosen and the integral over the area of the FSR is performed using quadrature rules with a weight :math:`w_{k}` for each track :math:`k \in K` crossing through the FSR :math:`k \in A_{i}`. The contribution :math:`\overline{\Psi}_{k,i,g}` of track :math:`k` with azimuthal and polar quadrature weights denoted by :math:`w_{m(k)}` and :math:`w_{p(k)}`, respectively, is then integrated to find the area-averaged scalar flux in FSR :math:`i` as follows: + +.. math:: + :label: area-averaged-scalar-flux-quadrature + + \Phi_{i,g} = \frac{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}\int_{4\pi}\mathrm{d}\mathbf{\Omega}\Psi_{g}(\mathbf{r},\mathbf{\Omega})}{\int_{\mathbf{r}\in A_{i}}\mathrm{d}\mathbf{r}} \approx \frac{4\pi\displaystyle\sum\limits_{k\in A_{i}}w_{m(k)}w_{p(k)}w_{k}l_{k,i}\sin\theta_{p(k)}\overline{\Psi}_{k,i,g}}{\displaystyle\sum\limits_{k\in A_{i}}w_kl_{k,i}\sin\theta_{p(k)}} + +In :eq:`area-averaged-scalar-flux-quadrature`, the angle :math:`\theta_{p(k)}` formed by characteristic :math:`k` with respect to the polar axis is introduced to project the length of the characteristic segment :math:`l_{k,i}` onto the azimuthal plane. In this application of quadrature to approximate an area integral, the weights can be thought of as the *effective width* of each track :math:`k`. + +The denominator in :eq:`area-averaged-scalar-flux-quadrature` then simplifies to the area :math:`A_i`: + +.. math:: + :label: avg-scalar-flux-quadrature + + \Phi_{i,g} \approx \frac{4\pi}{A_{i}}\displaystyle\sum\limits_{k\in A_{i}}w_{m(k)}w_{p(k)}w_{k}l_{k,i}\sin\theta_{p(k)}\overline{\Psi}_{k,i,g} + +The scalar flux can be found in terms of average angular fluxes from each track by substituting the expression for the average angular flux from :eq:`avg-angular-flux` into :eq:`avg-scalar-flux-quadrature` and rearranging: + +.. math:: + :label: avg-scalar-flux-v2 + + \Phi_{i,g} = \frac{4\pi}{\Sigma_{i,g}}\left[Q_{i,g} + \frac{1}{A_i}\displaystyle\sum\limits_{k\in A_{i}}\omega_{m(k)}\omega_{p(k)}\omega_{k}\sin\theta_{p(k)}\left(\Psi_{k,i,g}(s') - \frac{Q_{i,g}}{\Sigma_{i,g}^T}\right)(1 - e^{-\tau_{k,i,g}})\right] + +The final form for the scalar flux can be simplified in terms of the change in angular flux :math:`\Delta\Psi_{k,i,g}` along each track segment as defined in :eq:`delta-angular-flux-fsr`: + +.. math:: + :label: avg-scalar-flux-delta-angular-flux + + \Phi_{i,g} = \frac{4\pi}{\Sigma_{i,g}}\left[Q_{i,g} + \frac{1}{A_i}\displaystyle\sum\limits_{k\in A_{i}}\omega_{m(k)}\omega_{p(k)}\omega_{k}\sin\theta_{p(k)}\Delta\Psi_{k,i,g}\right] + + +.. _projection-azimuthal-plane: + +Projection from the Azimuthal Plane +=================================== + +The preceding sections used track segment lengths :math:`l_{k,i}` in 3D. In practice, the memory footprint for storing track segment data is greatly reduced if the polar angle quadrature is replicated for each azimuthal quadrature point. Such a quadrature allows for track segments to be stored in the 2D azimuthal plane and projected into 3D for each polar angle when necessary. The projection results in some minor changes to the equations presented in the previous sections. + +In what follows, each track segment length :math:`l_{k,i}` will be assumed to reside within the azimuthal plane. Likewise, the optical length :math:`\tau_{k,i,g} = \Sigma^T_{k,i,g}l_{k,i}` also resides in the azimuthal plane. For notational simplicity, the 3D projection of the track segment length for polar angle :math:`p` will be denoted by :math:`l_{k,i,p} = \frac{l_{k,i}}{\sin\theta_{p}}` and the optical length by :math:`\tau_{k,i,g,p} = \Sigma^T_{k,i,g}l_{k,i,p}`. + +First, the polar angle must be accounted for in the expression for the track segment average angular flux to project the segment length into the polar dimension: + +.. math:: + :label: avg-angular-flux-polar + + \overline{\Psi}_{k,i,g,p} = \frac{1}{l_{k,i,p}}\left[\frac{\Psi_{k,g,p}(s')}{\Sigma_{i,g}^T}(1 - \exp(-\tau_{k,i,g,p})) + \frac{l_{k,i,p}Q_{i,g}}{\Sigma_{i,g}^T}\left(1 - \frac{(1 - \exp(-\tau_{k,i,g,p}))}{\tau_{k,i,g,p}}\right)\right] + +Next, :math:`\sin\theta_{p(k)}` is dropped and a summation over polar angles is incorporated into the area-averaged scalar flux in :eq:`avg-scalar-flux-quadrature`: + +.. math:: + :label: avg-scalar-flux-quadrature-polar + + \Phi_{i,g} = \frac{4\pi}{A_i}\displaystyle\sum\limits_{k \in A_i}\displaystyle\sum\limits_{p=1}^{P}\omega_{m(k)}\omega_{p}\omega_{k}l_{k,i}\overline{\Psi}_{k,i,g,p} + +The scalar flux can be found in terms of average angular fluxes from each track by substituting the expression for the average angular flux from :eq:`avg-angular-flux-polar` into :eq:`avg-scalar-flux-quadrature-polar` and rearranging: + +.. math:: + :label: avg-scalar-flux-polar + + \Phi_{i,g} = \frac{4\pi}{\Sigma_{i,g}}\left[Q_{i,g} + \frac{1}{A_i}\displaystyle\sum\limits_{k\in A_{i}}\displaystyle\sum\limits_{p=1}^{P}\omega_{m(k)}\omega_{p}\omega_{k}\sin\theta_{p}\left(\Psi_{k,i,g,p}(s') - \frac{Q_{i,g}}{\Sigma_{i,g}^T}\right)(1 - e^{-\tau_{k,i,g,p}})\right] + +The final form for the scalar flux can be simplified in terms of the change in angular flux :math:`\Delta\Psi_{k,i,g,p}` along each track segment as defined in :eq:`avg-scalar-flux-delta-angular-flux`: + +.. math:: + :label: avg-scalar-flux-polar-final + + \Phi_{i,g} = \frac{4\pi}{\Sigma_{i,g}}\left[Q_{i,g} + \frac{1}{A_i}\displaystyle\sum\limits_{k\in A_{i}}\displaystyle\sum\limits_{p=1}^{P}\omega_{m(k)}\omega_{p}\omega_{k}\sin\theta_{p}\Delta\Psi_{k,i,g,p}\right] + +This is the form of the transport equation solved by the MOC formulation used in OpenMOC. + + +References +========== + +.. [Askew] J. Askew, "A Characteristics Formulation of the Neutron Transport Equation in Complicated Geometries." Technical Report AAEW-M 1108, UK Atomic Energy Establishment (1972). + +.. [Boyd] W. Boyd, "Massively Parallel Algorithms for Method of Characteristics Neutral Particle Transport on Shared Memory Computer Architectures." M.S. Thesis, Massachusetts Institute of Technology (2014). + diff --git a/docs/source/methods/track_generation.rst b/docs/source/methods/track_generation.rst new file mode 100644 index 000000000..2bdedabc2 --- /dev/null +++ b/docs/source/methods/track_generation.rst @@ -0,0 +1,286 @@ +.. _track_generation: + +================ +Track Generation +================ + +The method of characteristics uses tracks across the geometry to discretize the azimuthal and polar angle domains as well as the spatial domain. The way in which an MOC code generates tracks affects the quadrature weights :math:`w_{p}`, :math:`w_{m}`, and :math:`w_{k}` used to compute the angular and spatial integrals in the transport equation. This section describes the methodology used to generate tracks in OpenMOC and the corresponding angular and spatial quadrature weights. + + +.. _cyclic-tracks: + +Cyclic Tracks +============= + +OpenMOC uses *global tracking* such that each track spans the entire extent of the simulation domain. By symmetry, tracks only need to be represented for azimuthal angles in the range :math:`\phi \in [0, \pi]` since a track with angle :math:`\phi` will have the same start and end points as a track with angle :math:`\phi + \pi`. *Complementary angles* are pairs of angles :math:`(\phi, \alpha)` in the azimuthal quadrature where :math:`\alpha = \pi - \phi`. Tracks for complementary angles have a *track spacing* such that they intersect at the boundaries of the geometry and form closed cycles. An illustration of OpenMOC's track layout for eight azimuthal angles is given in :ref:`Figure 1 `. + +.. _figure-cyclic-tracks: + +.. figure:: ../../img/cyclic-tracks.png + :align: center + :figclass: align-center + :width: 300px + + **Figure 1**: Global cyclic tracks across a square. + + +Cyclic tracking is important since it allows for a simple treatment of reflective boundary conditions. Boundary conditions must be respected for the track outgoing fluxes at each iteration. Vacuum boundary conditions on a surface can be implemented for the MOC formulation by ensuring that each track originating along that surface has zero incoming flux, while tallying outgoing flux as leakage. Reflective boundary conditions are easily implemented since complementary angles guarantee that tracks wrap around the geometry in closed cycles. No approximations need to be made for each track's incoming flux since it is exactly the outgoing flux of another track in the cycle. + +The key parameters necessary for track generation in an OpenMOC simulation are the number of azimuthal angles :math:`n_{a}`, the spacing between tracks :math:`t_{s}`, and the total width and height of the geometry, :math:`w` and :math:`h`, respectively. OpenMOC computes the appropriate azimuthal angles to form cyclic tracks prior to track generation and ray tracing. The algorithm used by OpenMOC attempts to divide up the azimuthal space :math:`\phi \in [0, 2\pi]` as evenly as possible. In particular, for index :math:`m \in \{1, 2, ..., M\}`, the desired azimuthal angle :math:`\phi_{m}` is the following: + +.. math:: + :label: desired-azim-angle + + \phi_{m} = \frac{2\pi}{n_{a}}(m - 0.5) + +This angle is then used to compute the number of tracks :math:`n_{y}` and :math:`n_{x}` for angle :math:`m` originating from the left and bottom boundaries of the geometry using the floor function: + +.. math:: + :label: num-tracks-bottom + + n_{y} = \left\lfloor\frac{w}{t_{s}}|\sin\phi_{m}|\right\rfloor + 1 + +.. math:: + :label: num-tracks-left + + n_{x} = \left\lfloor{\frac{h}{t_{s}}|\cos\phi_{m}|}\right\rfloor + 1 + +Given :math:`n_{y}` and :math:`n_{x}`, an *effective angle* :math:`\phi_{m,eff}` is computed as a correction to the desired azimuthal angle :math:`\phi_{m}` to ensure cyclic track wrapping: + +.. math:: + :label: effective-azim-angle + + \phi_{m,eff} = \tan^{-1}\left(\frac{hn_{x}}{wn_{y}}\right) + +Although OpenMOC will abide by a user's request for the number of azimuthal angles, an *effective spacing* :math:`t_{s,m,eff}` must be computed and used instead of that specified by the user in order for the tracks wrap around the geometry. The effective spacing is unique for each azimuthal angle :math:`m`, and is computed as follows: + +.. math:: + :label: effective-spacing + + t_{s,m,eff} = \frac{w}{n_{x}}\sin\phi_{m,eff} + +The reader should note that this method for computing the effective track spacing in OpenMOC ensures that the following condition is always true: + +.. math:: + :label: effective-spacing-criterion + + t_{s,m,eff} \;\;\; \le \;\;\; t_{s} + + +.. _azimuthal-angle-quadrature: + +Azimuthal Angle Quadrature +========================== + +OpenMOC uses a product quadrature set that uncouples the azimuthal angle quadrature from the polar angle quadrature. The azimuthal angle quadrature set is computed based on the fraction of azimuthal angular space "owned" by each azimuthal angle. In this section, the variable transformation :math:`\phi_{m} \gets \phi_{m,eff}` has been made such that the effective azimuthal angle is used throughout. The azimuthal angle quadrature weight specification is given in :eq:`azimuthal-quadrature-1`, :eq:`azimuthal-quadrature-2`, and :eq:`azimuthal-quadrature-3`. + +.. math:: + :label: azimuthal-quadrature-1 + + w_{m} = \frac{1}{2\pi}\left[\frac{\phi_{m+1} - \phi_{m}}{2} + \phi_{m}\right] & \;\; \text{if} \;\;\; m = 1 + +.. math:: + :label: azimuthal-quadrature-2 + + w_{m} = \frac{1}{2\pi}\left[\frac{\phi_{m+1} - \phi_{m}}{2} + \frac{\phi_{m} - \phi_{m-1}}{2}\right] & \;\; \text{if} \;\;\; 1 < m < M + +.. math:: + :label: azimuthal-quadrature-3 + + w_{m} = \frac{1}{2\pi}\left[2\pi - \phi_{m} + \frac{\phi_{m} - \phi_{m-1}}{2}\right] & \;\; \text{if} \;\;\; m = M + + +.. _polar-angle-quadrature: + +Polar Angle Quadrature +====================== + +In OpenMOC, there are five polar quadrature sets that couple with the standard constant-angle azimuthal quadrature set. These include equal angles, equal weights, Gauss Legendre, Leonard, and Tabuchi Yamamoto polar quadrature sets. The formulas for computing the angles and weights of the equal angles and equal weights quadrature sets, given below, are described in the Handbook of Nuclear Engineering [Cacuci]_. The angles and weights for the Gauss Legendre, Leonard, and Tabuchi Yamamoto quadrature sets were taken from reference without modification [Yamamoto]_, [Cacuci]_. + +For the equal angles and equal weights quadrature sets, the user inputs the number of polar angles in :math:`[0,\frac{\pi}{2}]`, P, and then the angles and corresponding weights are computed. The relations for computing the angles, :math:`\theta_p`, and corresponding weights are given as equations :eq:`equal-angles-quad-1`, :eq:`equal-angles-quad-2`, and :eq:`equal-angles-quad-3`. The angle boundaries used to compute the angles and weights start at :math:`\bar{\theta}_p = 0`. + +.. math:: + :label: equal-angles-quad-1 + + \bar{\theta}_p = \bar{\theta}_{p-1} + \frac{\pi}{2 \cdot P} + +.. math:: + :label: equal-angles-quad-2 + + \theta_p = cos^{-1} \bigg\{ \frac{1}{2} \Big[ cos \big(\bar{\theta}_p\big) + cos \big(\bar{\theta}_{p-1}\big) \Big] \bigg\} + +.. math:: + :label: equal-angles-quad-3 + + w_p = cos \big(\theta_{p-1}\big) - cos \big(\theta_p\big) + +The equations for the equal weights quadrature set are the same as the equations for the equal angles quadrature set, except for the recursion relation for the angle boundaries, which is given in :eq:`equal-weights-quad-1`. The angle boundaries also start at :math:`\bar{\theta}_p = 0`. + +.. math:: + :label: equal-weights-quad-1 + + \bar{\theta}_p = cos^{-1} \bigg\{ cos \big(\bar{\theta}_{p-1}\big) - \frac{1}{P} \bigg\} + +Users can also input a custom polar quadrature set by manually setting the weights and sines of the polar angles. The quadrature recommended by [Yamamoto]_ is used by default for the polar angles and weights in OpenMOC. Example code on how to instantiate the different polar quadrature objects is provided in the :ref:`Users Guide `. + + +.. _spatial-quadrature: + +Spatial Quadrature +================== + +Track segments are used to approximate the area integral across each flat source region. In particular, the effective track spacing :math:`t_{s,m,eff}` defines the quadrature weights used in the spatial integral in the transport equation. + +.. math:: + :label: + + \forall \; m \in \{1, ..., M\} \;\;,\;\; \forall \; k \in K(m) \;\;\;\; w_{k} = t_{s,m,eff} + + +.. _ray-tracing: + +Ray Tracing +=========== + +Ray tracing is a technique for computing the intersection points of trajectories with surfaces. The image processing and graphics communities have been the primary users and developers of ray tracing techniques over the years, and a subset of these algorithms have been applied to neutron transport. In the case of the method of characteristics, ray tracing is used to intersect characteristic tracks with the surfaces used to make up a model. In particular, ray tracing is used to compute the length :math:`l_{k,i}` of a segment for track :math:`k` across each flat source region :math:`i`. + +The primary computation in ray tracing for MOC is to take a track segment's starting location :math:`(x,y)` and direction vector :math:`\hat{u}` and compute the distance that the track spans across a given cell. The *track segmentation* process repeatedly performs this computation for each track from its start to end point on the boundaries of the geometry. There are four primary operations that one must be able to perform to ray trace a track across the geometry: + +* Determine which universe the starting point :math:`(x,y)` resides in +* Determine which cell the starting point :math:`(x,y)` resides in +* Determine the distance to the nearest surface in the cell +* Determine the intersection point with the nearest surface + +The following four sections describe each of the algorithms used to perform each of these four ray tracing operations in OpenMOC. + + +.. _universe-finding-algorithm: + +-------------------------- +Universe-Finding Algorithm +-------------------------- + +The first algorithm needed for track segmentation is the ability to find the universe corresponding to a given location :math:`(x,y)`. The universe-finding algorithm used in OpenMOC is described in :ref:`Algorithm 1 `. This algorithm requires the location :math:`(x,y)` input along with the outermost lattice :math:`L` in the model. The algorithm computes the lattice cell in which :math:`(x,y)` resides and either returns the universe filling that lattice cell, or recursively calls itself using the lattice filling the lattice cell. In the latter case, the coordinates of the location :math:`(x,y)` must first be translated to the *local coordinate system* within the lattice cell, as reflected in :ref:`Algorithm 1 `. The algorithm completes by returning the universe along with the coordinates of the location within the universe's local coordinate system. + +.. _algorithm-find-universe: + +.. figure:: ../../img/find-universe-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 1**: Universe-finding algorithm. + +:ref:`Figure 3 ` illustrates one possible model with two *nested lattices* and the local coordinate transformations made using this algorithm. Here, :math:`n_{x}` and :math:`n_{y}` represent the number of lattice cells along the :math:`x` and :math:`y` axes, while :math:`h` and :math:`w` represent the total height and width of the lattice, respectively. Numerical subscripts are used to identify the appropriate lattice level. + +.. _figure-nested-lattice-coordinates: + +.. figure:: ../../img/nested-coordinates.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 3**: Local coordinates within nested lattices. + +The reader should note that this algorithm assumes that :math:`(x,y)` is within the bounds of the lattice. In practice, a significant amount of error checking is involved to ensure that this algorithm is robust to user input as well as floating point roundoff errors from the coordinate transformations at each recursive call. + + +.. _cell-finding-algorithm: + +---------------------- +Cell-Finding Algorithm +---------------------- + +The second algorithm needed for track segmentation is the ability to find the cell corresponding to a given location :math:`(x,y)`. The cell-finding algorithm is described in :ref:`Algorithm 2 `. The algorithm first finds the universe :math:`u` in which :math:`(x,y)` resides using :ref:`Algorithm 1 `. Next, the algorithm loops over all cells in the universe :math:`c \in u`. For each cell :math:`c`, the algorithm iterates over each surface :math:`s \in c` and multiplies the halfspace of the surface in the cell :math:`Hf(c,s) = \pm 1` with the potential function evaluated at the point of interest :math:`f_{s}(x,y)`. There are three possible outcomes from this computation: + +.. math:: + :label: halfspace-evaluation-1 + + sgn(Hf(c,s) \times f_{s}(x,y)) = +1 & \; \Rightarrow \;\; \text{$(x,y)$ is in the halfspace} + +.. math:: + :label: halfspace-evaluation-2 + + sgn(Hf(c,s) \times f_{s}(x,y)) = 0 & \; \Rightarrow \;\; \text{$(x,y)$ is on the surface} + +.. math:: + :label: halfspace-evaluation-3 + + sgn(Hf(c,s) \times f_{s}(x,y)) = -1 & \; \Rightarrow \;\; \text{$(x,y)$ is in the opposite halfspace} + +For simplicity, the assumption is made that the point :math:`(x,y)` is not on any surface in the geometry, or more formally, :math:`\forall \; s \;\; f_{s}(x,y) \neq 0`. If any cell is found in which the potential evaluated at :math:`(x,y)` and the halfspace of the corresponding surface each have the same sign for all surfaces in the cell, then the point :math:`(x,y)` uniquely resides in the cell and it is returned by the algorithm. + +The reader should note that :math:`L_{base}` in the following algorithm refers to the base lattice or universe that is used to encapsulate the outermost level of the geometry. + +.. _algorithm-find-cell: + +.. figure:: ../../img/find-cell-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 2**: Cell-finding algorithm. + + +.. _surface-distance-algorithm: + +------------------------------------- +Distance-to-Nearest Surface Algorithm +------------------------------------- + +The third algorithm that is needed for ray tracing is used to find the distance to the nearest surface to :math:`(x,y)` along the trajectory vector :math:`\hat{n}`. This algorithm builds upon each of the previous two as it only evaluates surfaces bounding the cell in which :math:`(x,y)` resides. + +The distance-to-nearest surface algorithm is described in :ref:`Algorithm 3 `. The algorithm simply iterates over each surface :math:`s` in the cell :math:`c` and solves for the distance(s) to the surface. The algorithm keeps track of the minimum distance :math:`d_{min}` it has evaluated to a surface at each step and returns the final value after iterating through all of the surfaces. + +.. _algorithm-minimum-surface-distance: + +.. figure:: ../../img/min-surf-dist-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 3**: Minimum surface distance algorithm. + + +.. _next-intersection-point-algorithm: + +--------------------------------- +Next Intersection Point Algorithm +--------------------------------- + +The final algorithm needed for ray tracing is to compute the intersection point of a point :math:`(x,y)` along a trajectory vector :math:`\hat{u}` with the nearest surface. The preceding algorithm is used to compute the parametrized distance to the intersection. This algorithm simply adds the parametrized distance multiplied by the trajectory vector to :math:`(x,y)` as described in :ref:`Algorithm 4 `. + +.. _algorithm-next-intersection-point: + +.. figure:: ../../img/next-intersection-point-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 4**: Find nearest surface intersection point algorithm. + + +.. _track-segmentation: + +---------------------------- +Track Segmentation Algorithm +---------------------------- + +Each of the preceding algorithms collectively define all of the logic that is necessary for ray tracing in the constructive solid geometry formulation. :ref:`Algorithm 5 ` defines the complete process of track segmentation for each track in the geometry. The algorithm defines a nested loop over all azimuthal angles :math:`m` and tracks :math:`k`. For each track, the algorithm begins with the track starting location and trajectory vector and ray traces across the geometry by computing intersection points with each surface along the trajectory's path. At each step, the length of each track segment in each cell (FSR) is computed and a pair of the segment length :math:`l_{k,i}` and flat source region index :math:`i` is appended to an ordered list of track segments within the track. + +This algorithm relies upon the use of a small numerical parameter :math:`\epsilon` which is typically chosen to be :math:`10^{-6}` for single precision and :math:`10^{-12}` for double precision floating point numbers. This parameter allows the end point for each track segment to be perturbed slightly to force it to lie within the adjacent cell in order to meet the assumption that no point lies directly on a surface (declared in order for :ref:`Algorithm 5 ` to perform properly). + +.. _algorithm-ray-tracing: + +.. figure:: ../../img/ray-tracing-algorithm.png + :align: center + :figclass: align-center + :width: 900px + + **Algorithm 5**: Track segmentation algorithm. + + +References +========== + +.. [Cacuci] D. Cacuci, et. al. "Handbook of Nuclear Engineering" *Springer Science+Business Media*, New York, NY, pp. 1111-1113 (2010). diff --git a/docs/source/publications.rst b/docs/source/publications.rst new file mode 100644 index 000000000..0240fa7e7 --- /dev/null +++ b/docs/source/publications.rst @@ -0,0 +1,61 @@ +.. _publications: + +============ +Publications +============ + +Citing OpenMOC +============== + +Please cite OpenMOC in your publications if it helps your research: + +.. code-block:: latex + + @article{openmoc2014, + author = {Boyd, William and Shaner, Samuel and Li, Lulu and Forget, Benoit and Smith, Kord}, + journal = {Annals of Nuclear Energy}, + title = {The OpenMOC Method of Characteristics Neutral Particle Transport Code}, + volume = {68}, + pages = {43--52}, + year = {2014} + } + +Citations are tracked automatically by `Google Scholar`_. + +.. _Google Scholar: https://scholar.google.com/scholar?cites=3139736083643679686&as_sdt=40000005&sciodt=0,22&hl=en + +Journals +========= +- William Boyd, Andrew Siegel, Benoit Forget and Kord Smith, "Parallel Performance Results for the OpenMOC Neutron Transport Code on Multi-Core Platforms." Accepted for publication in the *Int'l Journ. of High Perf. Comp. Appl.*, 2015. + +- Matthew Everson and Benoit Forget, "The Source Equivalence Acceleration Method." *Annals of Nuclear Energy*, 76 (2015): 177--129. + +- William Boyd, Samuel Shaner, Lulu Li, Benoit Forget, and Kord Smith, "The OpenMOC Method of Characteristics Neutral Particle Transport Code." *Annals of Nuclear Energy*, 68 (2014): 43--52. + +Conference Papers +================= + +- William Boyd, Samuel Shaner, Benoit Forget and Kord Smith, "Program Optimization and Improved Workflow Synthesis for the OpenMOC Neutron Transport Code." *Submitted to the Trans. of the Amer. Nucl. Soc.*, ANS Winter Meeting, Washington, D.C., USA, November (2015). + +- William Boyd, Kazutomo Yoshii and Andrew Siegel, "Energy Efficiency of High-Performance Computing Platforms for Neutron Transport Calculations." *Trans. of the Amer. Nucl. Soc.*, ANS Summer Meeting, San Antonio, TX, USA June (2015). + +- William Boyd, Kord Smith, Benoit Forget, and Andrew Siegel, "Parallel Performance Results for the OpenMOC Method of Characteristics Code on Multi-Core Platforms." *Proceedings of PHYSOR*, Kyoto, Japan (2014). + +- Lulu Li, Kord Smith, and Benoit Forget, "Low Order Nonlinear Transport Acceleration Scheme for the Method of Characteristics." *Proceedings of PHYSOR*, Kyoto, Japan (2014). + +- Samuel Shaner, Kord Smith, and Benoit Forget, "Sensitivity Analysis and Performance of the Adiabatic, Theta, and Multigrid Amplitude Function Kinetics Methods in 2D MOC Neutron Transport." *Proceedings of PHYSOR*, Kyoto, Japan (2014). + +- Stephanie Pavlick, Davis Tran, Jasmeet Arora, and William Boyd, "Lattice Benchmark Verification of OpenMOC." *Proc. Amer. Nucl. Soc. Student Conf.*, University Park, PA, USA (2014). + +- William Boyd, Kord Smith, and Benoit Forget, "A Massively Parallel Method of Characteristic Neutral Particle Transport Code for GPUs." *Proc. Int'l Conf. Math. and Comp. Methods Appl. to Nucl. Sci. and Eng.*, Sun Valley, ID, USA (2013). Selected for Best Overall Conference Paper. + + +Theses +====== +- Samuel Shaner, "Transient Method of Characteristics via the Adiabatic, Theta, and Multigrid Amplitude Function Methods." M.S. Thesis, Massachusetts Institute of Technology (2014). + +- William R. D. Boyd III, "Massively Parallel Algorithms for Method of Characteristics Neutral Particle Transport on Shared Memory Computer Architectures." M.S. Thesis, Massachusetts Institute of Technology (2014). + +- Matthew Everson, "Advanced Application of the Discrete Generalized Multigroup Method and Recondensation to Reactor Analysis." PhD Thesis, Massachusetts Institute of Technology (2014). + +- Lulu Li, "A Low Order Acceleration Scheme for Solving the Neutron Transport Equation." M.S. Thesis, Massachusetts Institute of Technology (2013). diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst new file mode 100644 index 000000000..142700cca --- /dev/null +++ b/docs/source/quickinstall.rst @@ -0,0 +1,40 @@ +.. _quickinstall: + +=================== +Quick Install Guide +=================== + +This quick install guide outlines the basic steps needed to install OpenMOC on your computer. For more detailed instructions on configuring and installing OpenMOC, see :ref:`Installation ` in the User's Manual. + +------------------------------------------- +Installing from Source on Linux or Mac OS X +------------------------------------------- + +All OpenMOC source code is hosted on GitHub_. To download and install OpenMOC, you need to install Git_ and the GNU C++ compiler_. In addition, you need to install Python_ version 2.6 or later and the following Python packages on your machine: SWIG_, NumPy_, matplotlib_, and h5py_. These packages can easily be installed using a package manager for Linux and Mac OS (see :ref:`Installation ` for more details). The following command will install all required and optional dependencies on Ubuntu 12.04 or later:: + + sudo apt-get install build-essential git swig python-dev python-numpy python-matplotlib python-h5py + +If you have already installed each of these prerequisites, you can download and install OpenMOC by entering the following commands in the console:: + + git clone https://github.com/mit-crpg/OpenMOC.git + cd OpenMOC + python setup.py install --user + +This will build a shared library accessible as a Python package named ``openmoc`` and install it (by default in /home/YourUserName/.local/lib/pythonX.X/dist-packages). The ``openmoc`` Python package can now be imported into any Python script as follows: + +.. code-block:: python + + import openmoc + +.. warning:: The :option:`--user` flag should be used verbatim and should **NOT** be replaced with your username. + + +.. _GitHub: https://github.com/mit-crpg/OpenMOC +.. _Git: http://git-scm.com +.. _compiler: http://gcc.gnu.org/ +.. _Python: http://www.python.org/ +.. _SWIG: http://www.swig.org/ +.. _NumPy: http://www.numpy.org/ +.. _matplotlib: http://matplotlib.org/ +.. _h5py: http://www.h5py.org/ +.. _symbolic links: http://en.wikipedia.org/wiki/Symbolic_link diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst new file mode 100644 index 000000000..cd036bcc7 --- /dev/null +++ b/docs/source/releasenotes/index.rst @@ -0,0 +1,16 @@ +.. _releasenotes: + +============= +Release Notes +============= + +The release notes for OpenMOC give a list of system requirements, new features, +bugs fixed, and known issues for each successive release. + +.. toctree:: + :maxdepth: 1 + + notes_0.1.1 + notes_0.1.2 + notes_0.1.3 + notes_0.1.4 diff --git a/docs/source/releasenotes/notes_0.1.1.rst b/docs/source/releasenotes/notes_0.1.1.rst new file mode 100644 index 000000000..d0d1b0598 --- /dev/null +++ b/docs/source/releasenotes/notes_0.1.1.rst @@ -0,0 +1,33 @@ +.. _notes_0.1.1: + +=============================== +Release Notes for OpenMOC 0.1.1 +=============================== + +------------------- +System Requirements +------------------- + +There are no special requirements for running the OpenMOC code. As of this +release, OpenMOC has been tested on a variety of Linux distributions as well as +Mac OS X. However, it has not been tested yet on any releases of Microsoft +Windows. Memory requirements will vary depending on the size of the problem at +hand (the number of flat source regions and the level of track discretization). + +------------ +New Features +------------ + +- `9ba06b2`_: Added exponential intrinsic evaluation option for GPUSolver. +- `0f2a8d8`_: Implemented a thread private vectorized solver class (VectorizedPrivateClass). +- `3ca79f5`_: Track segments now stored in a stride one array to improve cache coherency. +- `3baffee`_: OpenMP parallel regions use guided rather than dynamic scheduling. + +.. _9ba06b2: https://github.com/mit-crpg/OpenMOC/commit/9ba06b2 +.. _0f2a8d8: https://github.com/mit-crpg/OpenMOC/commit/0f2a8d8 +.. _3ca79f5: https://github.com/mit-crpg/OpenMOC/commit/3ca79f5 +.. _3baffee: https://github.com/mit-crpg/OpenMOC/commit/3baffee + +--------- +Bug Fixes +--------- diff --git a/docs/source/releasenotes/notes_0.1.2.rst b/docs/source/releasenotes/notes_0.1.2.rst new file mode 100644 index 000000000..fe8ad0a7e --- /dev/null +++ b/docs/source/releasenotes/notes_0.1.2.rst @@ -0,0 +1,44 @@ +.. _notes_0.1.2: + +=============================== +Release Notes for OpenMOC 0.1.2 +=============================== + +------------------- +System Requirements +------------------- + +There are no special requirements for running the OpenMOC code. As of this +release, OpenMOC has been tested on a variety of Linux distributions as well as +Mac OS X. However, it has not been tested yet on any releases of Microsoft +Windows. Memory requirements will vary depending on the size of the problem at +hand (the number of flat source regions and the level of track discretization). + +------------ +New Features +------------ + +- `bd9d4c11eb`_: CMFD coarse group solver +- `ea25db0454`_: Python 3 compatibility +- `75731d8820`_: Single first-time installation + +.. _bd9d4c11eb: https://github.com/mit-crpg/OpenMOC/commit/bd9d4c11eb +.. _ea25db0454: https://github.com/mit-crpg/OpenMOC/commit/ea25db0454 +.. _75731d8820: https://github.com/mit-crpg/OpenMOC/commit/75731d8820 + + +--------- +Bug Fixes +--------- + +- `216ce92b2a`_: Minor correction to C5G7 cross-sections +- `ac6bbe7674`_: Fix to find coordinates within the ``Geometry`` in ``openmoc.plotter.plot_fluxes(...)`` routine +- `ea25db0454`_: Fix to allow sources to be stored in ``openmoc.process.store_simulation_state(...)`` routine +- `c9bd55788e`_: Segfault for coarse track spacings in ``Solver::convergeSource(...)`` routine +- `25fe960cd5`_: Fixed ``openmoc`` import statement in ``openmoc.process`` submodule + +.. _216ce92b2a: https://github.com/mit-crpg/OpenMOC/commit/216ce92b2a +.. _ea25db0454: https://github.com/mit-crpg/OpenMOC/commit/ea25db0454 +.. _ac6bbe7674: https://github.com/mit-crpg/OpenMOC/commit/ac6bbe7674 +.. _c9bd55788e: https://github.com/mit-crpg/OpenMOC/commit/c9bd55788e +.. _25fe960cd5: https://github.com/mit-crpg/OpenMOC/commit/25fe960cd5 diff --git a/docs/source/releasenotes/notes_0.1.3.rst b/docs/source/releasenotes/notes_0.1.3.rst new file mode 100644 index 000000000..20967a4ab --- /dev/null +++ b/docs/source/releasenotes/notes_0.1.3.rst @@ -0,0 +1,37 @@ +.. _notes_0.1.3: + +=============================== +Release Notes for OpenMOC 0.1.3 +=============================== + +------------------- +System Requirements +------------------- + +There are no special requirements for running the OpenMOC code. As of this +release, OpenMOC has been tested on a variety of Linux distributions as well as +Mac OS X. However, it has not been tested yet on any releases of Microsoft +Windows. Memory requirements will vary depending on the size of the problem at +hand (the number of flat source regions and the level of track discretization). + +------------ +New Features +------------ + +- `bee1e60397`_: Reconstructed segmentation routines to allow for tracking across overlapping cells. +- `a5ccd1324f`_: Added P0 boundary flux update to CMFD solver. + +.. _a5ccd1324f : https://github.com/mit-crpg/OpenMOC/commit/a5ccd1324f +.. _bee1e60397 : https://github.com/mit-crpg/OpenMOC/commit/bee1e60397 + +--------- +Bug Fixes +--------- + +- `a5ccd1324f`_: Fixed procedural error in computing diffusion coefficients in CMFD. +- `bee1e60397`_: Fixed error in computing the CMFD optically thick correction factor. +- `bee1e60397`_: TrackGenerator geometry string was incorrect resulting in TrackGenerator often not identifying a valid track file when one actually existed. The error in generating the geometry string has been corrected. +- `bee1e60397`_: Fixed inconsistency in XPlane and YPlane constants. + +.. _a5ccd1324f : https://github.com/mit-crpg/OpenMOC/commit/a5ccd1324f +.. _bee1e60397 : https://github.com/mit-crpg/OpenMOC/commit/bee1e60397 diff --git a/docs/source/releasenotes/notes_0.1.4.rst b/docs/source/releasenotes/notes_0.1.4.rst new file mode 100644 index 000000000..1988d3e55 --- /dev/null +++ b/docs/source/releasenotes/notes_0.1.4.rst @@ -0,0 +1,41 @@ +.. _notes_0.1.4: + +=============================== +Release Notes for OpenMOC 0.1.4 +=============================== + +------------------- +System Requirements +------------------- + +There are no special requirements for running the OpenMOC code. As of this +release, OpenMOC has been tested on a variety of Linux distributions as well as +Mac OS X. However, it has not been tested yet on any releases of Microsoft +Windows. Memory requirements will vary depending on the size of the problem at +hand (the number of flat source regions and the level of track discretization). + +------------ +New Features +------------ + +- `751ba0`_: Major reformulation of constructive solid geometry models used in OpenMOC +- `691afb`_: Inclusion of (n,2n), (n,3n), etc. reaction with nu-scattering matrix +- `41ac75`_: Compatiblity module for the soon-to-be-open-sourced OpenCG package +- `e69bbf`_: Directory parameter for store_simulation_state(...) routine + +.. _751ba0 : https://github.com/mit-crpg/OpenMOC/commit/751ba09225cdec74168c4d43fb34848c2668ad97 +.. _691afb : https://github.com/mit-crpg/OpenMOC/commit/691afb2fa71a861e21c2e2a8635e741e35845109 +.. _41ac75 : https://github.com/mit-crpg/OpenMOC/commit/41ac756973f6c3770aa4820d2e4e68e02da7bc9e +.. _e69bbf : https://github.com/mit-crpg/OpenMOC/commit/e69bbfd0d59a6f2c124762f30f1f7d557b509c18 + +--------- +Bug Fixes +--------- + +- `0936be`_: Revised import statements in Python modules to be compatible with Python 3 +- `189733`_: Bug fixes to VectorizedSolver class caused by backwards compatiblity issues from v0.1.3 +- `732017`_ : Bug fix for openmoc.compatible.casmo module's k-infinity parser + +.. _0936be : https://github.com/mit-crpg/OpenMOC/commit/0936bec595e88a423e86e5b4e84accd32b11e647 +.. _189733: https://github.com/mit-crpg/OpenMOC/commit/1897dd76ce0821cc2038477ab5b814de205bb602 +.. _732017 : https://github.com/mit-crpg/OpenMOC/commit/732017226be65857b6d838393e5a000d11a79583 diff --git a/docs/source/usersguide/beginners.rst b/docs/source/usersguide/beginners.rst new file mode 100644 index 000000000..2dff99c78 --- /dev/null +++ b/docs/source/usersguide/beginners.rst @@ -0,0 +1,75 @@ +.. _usersguide_beginners: + +============================= +A Beginner's Guide to OpenMOC +============================= + +--------------------- +What does OpenMOC do? +--------------------- + + + +----------------- +How does it work? +----------------- + +In order to do anything, the code first needs to have a model of some problem of +interest. This could be a nuclear reactor or any other physical system with +fissioning material. You, as the code user, will need to describe the model so +that the code can do something with it. A basic model consists of a few things: + +- **Geometry** - A description of the geometry split into regions of homogeneous materials. +- **Materials** - A description of the nuclear cross-sections for each material +- **Parameters** - Various parameters for the numerical algorithm used in the simulation + + +----------------------- +What do I need to know? +----------------------- + +If you are starting to work with OpenMOC, there are a few things you should be +familiar with. Whether you plan on working in Linux, Mac OS X, or Windows, you +should be comfortable working in a command line environment. There are many +resources online for learning command line environments. If you are using Linux +or Mac OS X (also Unix-derived), `this tutorial +`_ will help you get acquainted with +commonly-used commands. It is also helpful to be familiar with `Python +`_, as most of the post-processing utilities provided +with OpenMOC rely on it for data manipulation and results visualization. + +OpenMOC uses a version control software called `git`_ to keep track of changes to +the code, document bugs and issues, and other development tasks. While you don't +necessarily have to have git installed in order to download and run OpenMOC, it +makes it much easier to receive updates if you do have it installed and have a +basic understanding of how it works. There are a list of good `git tutorials`_ +at the git documentation website. The `OpenMOC source code`_ and documentation +are hosted at `GitHub`_. In order to receive updates to the code directly, +submit `bug reports`_, and perform other development tasks, you may want to sign +up for a free account on GitHub. Once you have an account, you can follow `these +instructions `_ on how to set up +your computer for using GitHub. + +If you are new to nuclear engineering, you may want to review the NRC's `Reactor +Concepts Manual`_. This manual describes the basics of nuclear power for +electricity generation, the fission process, and the overall systems in a +pressurized or boiling water reactor. Another resource that is a bit more +technical than the Reactor Concepts Manual but still at an elementary level is +the DOE Fundamentals Handbook on Nuclear Physics and Reactor Theory `Volume I`_ +and `Volume II`_. You may also find it helpful to review the following terms: + +- `Neutron cross-section`_ +- `Effective multiplication factor`_ +- `Neutron Flux`_ + +.. _git: http://git-scm.com/ +.. _git tutorials: http://git-scm.com/documentation +.. _Reactor Concepts Manual: http://www.amazon.com/Electrical-Generation-Concepts-Technical-Training/dp/B009XXK564 +.. _Volume I: http://energy.gov/sites/prod/files/2013/06/f2/h1019v1.pdf +.. _Volume II: http://energy.gov/sites/prod/files/2013/06/f2/h1019v2.pdf +.. _OpenMOC source code: https://github.com/mit-crpg/OpenMOC +.. _GitHub: https://github.com/ +.. _bug reports: https://github.com/mit-crpg/OpenMOC/issues +.. _Neutron cross-section: http://en.wikipedia.org/wiki/Neutron_cross_section +.. _Effective multiplication factor: http://en.wikipedia.org/wiki/Effective_multiplication_factor +.. _Neutron Flux: http://en.wikipedia.org/wiki/Neutron_flux diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst new file mode 100644 index 000000000..31d74b454 --- /dev/null +++ b/docs/source/usersguide/index.rst @@ -0,0 +1,19 @@ +.. _usersguide: + +============ +User's Guide +============ + +Welcome to the OpenMOC User's Guide! This tutorial will guide you through the +essential aspects of using OpenMOC to perform neutron transport reactor physics calculations. + +.. toctree:: + :numbered: + :maxdepth: 2 + + beginners + install + input + processing + running + troubleshoot diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst new file mode 100644 index 000000000..e0db0d65b --- /dev/null +++ b/docs/source/usersguide/input.rst @@ -0,0 +1,838 @@ +.. _usersguide_input: + +========================== +Writing Python Input Files +========================== + +OpenMOC is provided to users as a Python API. As a result, there are not strict constraints on how an input file is written for an OpenMOC simulation as there are in many other scientific simulation codes. Instead, users may write a Python script or program and import OpenMOC and simply use the classes or routines which are necessary for a particular simulation. The :file:`OpenMOC/sample-input/` directory in the OpenMOC folder includes many example scripts for simulations ranging in complexity from a simple `pin cell`_ to the `C5G7 benchmark problem`_. + +The following sections describe the essential portions of the OpenMOC API needed for reactor eigenvalue calculations. For more detail on the full extent of OpenMOC capabilities, users should reference the :ref:`OpenMOC API documentation `. + +.. note:: It is highly suggested that users acquire a basic understanding of Python before developing OpenMOC simulations. For users familiar with basic programming constructs such as loops and conditionals, the official `Python Tutorial`_ is an excellent place to learn Python basics. For users new to programming, the `Code Academy Python Course`_ provides an introduction to both programming essentials and the Python language. + + +.. _simulation_params: + +--------------------- +Simulation Parameters +--------------------- + +The full power of Python is available to users designing OpenMOC simulations. As a result, simulation parameters may easily be defined and redefined in a Python script for one or more simulations at a user's discretion. However, some simulation parameters are best defined at runtime, including the number of azimuthal angles, track spacing, number of threads, etc. + +The ``openmoc.options`` module provides functionality to parse arguments defined on the command line at runtime. The full list of options available in OpenMOC are itemized and described in :ref:`Runtime Options `. The following code snippet illutrates how to instantiate an ``Options`` object and extract data from command line arguments. + +.. code-block:: python + + import openmoc.options + + # Instantiate and Options object + options = openmoc.options.Options() + + # Retrieve runtime options parsed in by the Options object + num_threads = options.num_omp_threads + track_spacing = options.track_spacing + num_azim = options.num_azim + tolerance = options.tolerance + max_iters = options.max_iters + ... + +:ref:`Table 1 ` below itemizes each of the runtime options and the corresponding command line arguments and Options class property attributes in the ``openmoc.options`` module. + +.. _table_runtime_options: + +============================= ============================================= ====================================================== +Runtime Option Command Line Argument Options Class Property Attribute +============================= ============================================= ====================================================== +Help :option:`-h`, :option:`--help` N/A +No. Azimuthal Angles :option:`-a`, :option:`--num-azim=` num_azim +Track Spacing [cm] :option:`-s`, :option:`--track-spacing=` track_spacing +Max. No. Transport Sweeps :option:`-i`, :option:`--max-iters=` max_iters +Convergence Tolerance :option:`-c`, :option:`--tolerance=` tolerance +No. OpenMP Threads :option:`-t`, :option:`--num-omp-threads=` num_omp_threads +No. CUDA Thread Blocks :option:`-b`, :option:`--num-thread-blocks=` num_thread_blocks +No. CUDA Threads per Block :option:`-g`, :option:`--num-gpu-threads=` num_threads_per_block +============================= ============================================= ====================================================== + +**Table 1**: Runtime options and command line arguments supported by the ``openmoc.options`` module. + + +-------------------- +Simulation Log Files +-------------------- + +The ``openmoc.log`` module provides routines for printing output to the console as well as to log files. Output is reported in real-time to the console as well as stored in a persistent log file. By default, the log file name encapsulates a timestamp for the simulation starting time and is stored in the ``/OpenMOC/log`` directory (*e.g.*, :file:`OpenMOC/log/openmoc-MM-DD-YYYY--HH:MM:SS.log`). + +The OpenMOC logging module uses **verbosity throttling** which allows for coarse-grained control of the type and amount of messages reported to the user at runtime. Each message is designated a **log level**, and each level is prioritized with respect to other levels. At runtime, a log level is specified for a simulation and only those messages designated at that log level or a higher priority log level are printed to the console and log file. The log levels available in OpenMOC are presented in :ref:`Table 2 `. + +.. _table_log_levels: + +=================== ======================================================= +Log Level Note +=================== ======================================================= +:envvar:`DEBUG` A debugging message +:envvar:`INFO` An informational but verbose message +:envvar:`NORMAL` A brief progress update on run progress +:envvar:`SEPARATOR` A message of a single line of characters +:envvar:`HEADER` A message centered within a single line of characters +:envvar:`TITLE` A message between two lines of characters +:envvar:`WARNING` A message to warn the user +:envvar:`CRITICAL` A message to warn of critical program conditions +:envvar:`RESULT` A message containing program results +:envvar:`ERROR` A message reporting error conditions +=================== ======================================================= + +**Table 2**: Log levels in OpenMOC in order of increasing precedence. + +Informative messages using the logging module are embedded into both the C/C++ and Python source code in OpenMOC. In addition, code users may add their own messages to the output stream in Python input files. The API documentation provides a detailed accounting of the routines available in the `logging module`_. + +The following code snippet illustrates how to import the logging module into Python, set the lowest log level to :envvar:`DEBUG`, and print messages for each level to the screen. + +.. code-block:: python + + import openmoc.log as log + + # Set the lowest acceptable log level to DEBUG mode + log.set_log_level('DEBUG') + + # Print some exaple messages to the console and log file + log.py_printf('DEBUG', 'This is a DEBUG message') + log.py_printf('INFO', 'This is an INFO message') + log.py_printf('NORMAL', 'This is a NORMAL message') + log.py_printf('SEPARATOR', 'This is a SEPARATOR message') + log.py_printf('HEADER', 'This is a HEADER message') + log.py_printf('TITLE', 'This is a TITLE message') + log.py_printf('WARNING', 'This is a WARNING message') + log.py_printf('CRITICAL', 'This is a CRITICAL message') + log.py_printf('ERROR', 'This is an ERROR message') + +And the following is the output displayed to the console and recorded in the log file:: + + [ DEBUG ] This is a DEBUG message + [ INFO ] This is an INFO message + [ NORMAL ] This is a NORMAL message + [SEPARATOR] ******************************************************************* + [ HEADER ] ******************* This is a HEADER message ******************** + [ TITLE ] ******************************************************************* + [ TITLE ] This is a TITLE message + [ TITLE ] ******************************************************************* + [ WARNING ] This is a WARNING message + [ CRITICAL] This is a CRITICAL message + [ ERROR ] This is an ERROR message + +It should be noted that the ``py_printf(...)`` routine in the logging module is based on the printf_ routine in C/C++ and accepts a variable number of arguments. In particular, this is intended to accept `formatted data`_ to embed formatted integers, floats, strings, etc. in the output message. An example of this feature in use is given below: + +.. code-block:: python + + import openmoc.log as log + + # Set the lowest acceptable log level to NORMAL mode + log.set_log_level('NORMAL') + + # Initialize some string, integer and float variables + name = 'Will Boyd' + age = 26 + pi = 3.141593 + + # Print example messages using formatted output arguments + # to the console and log file + log.py_printf('NORMAL', 'Hello World! My name is %s', name) + log.py_printf('NORMAL', 'I am %d years old. My favorite # is %f', age, pi) + + +This will result in the following output messages to be printed to the console and stored to the log file:: + + [ NORMAL ] Hello World! My name is Will Boyd + [ NORMAL ] I am 26 years old. My favorite # is 3.141593 + +.. note:: By default, the logging module will split log messages into multiple lines of 80 characters or less each. Users may alternatively set a custom maximum line length for log messages may at runtime using the ``set_line_length(...)`` routine. + +----------------------- +Materials Specification +----------------------- + +OpenMOC uses multi-group macroscopic nuclear cross sections, provided by the user. OpenMOC does not perform self-shielding or depletion calculations, so isotropic concentrations are not used. In OpenMOC, cross section data is encapsulated by the ``Material`` class in the main ``openmoc`` Python module. A ``Material`` class may be instantiated in Python and cross sections may be loaded into it using NumPy_ data arrays as illustrated by the following code snippet: + +.. code-block:: python + + import openmoc + import numpy + + # Initialize material cross sections using NumPy data arrays + num_groups = 8 + sigma_t = numpy.array([0.1,0.15,0.2,0.25,0.35,0.4,0.45,0.5]) + sigma_f = numpy.array([0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4]) + ... + + # Instantiate an OpenMOC Material class object with an optional string name + material = openmoc.Material(name='test material') + + # Set the number of energy groups in the material + material.setNumEnergyGroups(num_groups) + + # Load the cross section data into the material + material.setSigmaT(sigma_t) + material.setSigmaF(sigma_f) + ... + +For many simulations, defining the nuclear data cross sections by hand in a Python script is cumbersome and error-prone. As a result, OpenMOC includes the ``openmoc.materialize`` module for importing nuclear data cross sections from an HDF5_ binary file. The ``load_from_hdf5(...)`` routine is used to import data and instantiate ``Material`` objects returned via a Python dictionary_. The use of the ``openmoc.materialize`` module to import HDF5 binary files is illustrated in the following snippet: + +.. code-block:: python + + import openmoc + import openmoc.materialize as materialize + + # Import cross section data from an HDF5 file. This instantiates + # objects for each material and returns them in a dictionary + # indexed by a string name or integer ID + hdf5_materials = materialize.load_from_hdf5(filename='materials-data.h5', + directory='/home/myuser') + + # Retrieve the material called 'moderator' in the HDF5 file + moderator = hdf5_materials['moderator'] + +The ``openmoc.materialize`` module defines a standard for cross section data stored in binary files. First, HDF5 files must include a ``'# groups'`` attribute with the integer number of groups in the top level of the file hierarchy. Second, the string domain type - ``'material'`` or ``'cell'`` - must be specified in the top level of the file hierarchy. This must match the ``domain_type`` keyword argument passed to ``load_from_hdf5(...)`` which can be either ``'material'`` (default) or ``'cell'``. The ``domain_type`` keyword argument is discussed in more detail at the end of this section. Finally, multi-group cross sections to assign by material or cell must be defined as an `HDF5 group`_ with a string name or integer ID to identify the material or cell. The material group must contain the following floating point `HDF5 datasets`_ of multi-group cross section data: + + - ``'transport'`` or ``'total'`` + - ``'nu-scatter matrix'`` or ``'scatter matrix'`` + - ``'chi'`` + - ``'nu-fission'`` + - ``'fission'`` (optional) + +Each dataset should be a 1D array of floating point values ordered by increasing energy group (*i.e.*, from highest to lowest energies). This includes the scattering matrix which should be inner strided by outgoing energy group and outer strided by incoming energy group. + +To better understand the necessary HDF file structure, it may be useful to visualize the ``OpenMOC/sample-input/c5g7-mgxs.h5`` HDF5 file using the HDFView_ graphical tool. The following code snippet illustrates the use of the h5py_ Python HDF5 interface to write an HDF5 file with material cross section data adhering to the standard expected by the ``openmoc.materialize`` module: + +.. code-block:: python + + import numpy + import h5py + + # Create an HDF5 file to store multi-groups cross sections + f = h5py.File('materials-data.h5') + + # Set the number of energy groups + f.attrs['# groups'] = 8 + + # Material 1 + + # Create an HDF5 group for this material + material_group = f.create_group('Material 1') + + # Initialize cross sections as NumPy data arrays + sigma_t = numpy.array([0.1,0.15,0.2,0.25,0.35,0.4,0.45,0.5]) + nu_sigma_f = numpy.array([0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4]) + ... + + # Create datasets for each cross section type + material_group.create_dataset('total', data=sigma_t) + material_group.create_dataset('nu-fission', data=nu_sigma_f) + ... + + # Material 2 + ... + + # Close and save the HDF5 file + f.close() + +Lastly, the ``'domain_type'`` parameter may be specified in conjuction with the optional ``geometry`` keyword argument. The ``load_from_hdf5(...)`` routine may be used to load multi-group cross sections directly into a pre-existing OpenMOC ``Geometry`` constructed with ``Materials`` with the same string names *or* integer IDs used as keys in the HDF5 binary file. Likewise, the ``load_from_hdf5(...)`` routine may be used to load multi-group cross sections directly into a pre-existing OpenMOC ``Geometry`` constructed with ``Cells`` with the same string names *or* integer IDs used as keys in the HDF5 binary file. The latter case may be useful when multiple ``Cells`` share the same ``Materials``. This is illustrated with the following code snippet: + +.. code-block:: python + + import openmoc + import openmoc.materialize as materialize + + # Build an OpenMOC Geommetry with Materials, Surfaces, Cells, etc. + # The Cells must have the same IDs as those used in the HDF5 file + ... + geometry = openmoc.Geometry() + ... + + # Import cross section data from an HDF5 file. This instantiates + # objects for each material and returns them in a dictionary + # indexed by a string name or integer ID + hdf5_materials = materialize.load_from_hdf5(filename='materials-data.h5', + directory='/home/myuser', + domain_type='cell', + geometry=geometry) + +In this case there is no need to assign the ``Materials`` in the ``hdf5_materials`` dictionary to ``Cells`` since they are already incorporated into the ``Geometry``. + +.. note:: If datasets for both ``'transport'`` and ``'total'`` are defined for a material in the HDF5 file, ``openmoc.materialize`` will give precedence to the ``'transport'`` dataset and assign it as the total multi-group cross section. + +.. note:: If datasets for both ``'nu-scatter matrix'`` and ``'scatter matrix'`` are defined for a material in the HDF5 file, ``openmoc.materialize`` will give precedence to the ``'nu-scatter matrix'`` dataset and assign it as the multi-group scattering matrix cross section. + +.. note:: Users should note that OpenMOC will assign a minimum value of 1E-10 to all total cross sections assigned to a ``Material`` object. This prevents numerical divide-by-zero issues in the ``Solver``, and is a useful sanity check when modeling (nearly) void regions - *e.g.*, a fuel pin cell "gap." + +---------------------- +Geometry Specification +---------------------- + +The geometry in OpenMOC is described using constructive solid geometry (CSG_), +also sometimes referred to as combinatorial geometry. CSG allows a user to +create complex objects using Boolean operators on a set of simpler surfaces. In +the geometry model, each unique closed volume is defined by its bounding +surfaces. The CSG formulation used in OpenMOC is described in more detail in :ref:`Constructive Solid Geometry `. + +The following sections detail how to create surfaces, cells, universes and lattices to construct a simple 4 :math:`\times` 4 pin cell lattice. + + +Surfaces +-------- + +In most cases, the first step towards building a reactor geometry is to create the surfaces defining boundaries between distinct regions. The CSG formulation for surfaces in OpenMOC is described in detail in :ref:`Surfaces and Halfspaces `. For LWRs, the most typical surfaces needed to model 2D rectangular lattices are the ``ZCylinder``, ``XPlane``, and ``YPlane`` classes. The following code snippet illustrates how to create a circle to represent a fuel pin and reflective boundary planes to surround a 4 :math:`\times` 4 lattice. + +.. code-block:: python + + # Initialize circular fuel pin surface with an optional string name + circle = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.45, name='fuel radius') + + # Initialize the planar surfaces bounding the entire geometry + # with optional string names + left = openmoc.XPlane(x=-2.52, name='left') + right = openmoc.XPlane(x=2.52, name='right') + bottom = openmoc.YPlane(y=-2.52, name='bottom') + top = openmoc.YPlane(y=2.52, name='top') + + # Set the boundary conditions for the bounding planes + left.setBoundaryType(openmoc.REFLECTIVE) + right.setBoundaryType(openmoc.REFLECTIVE) + bottom.setBoundaryType(openmoc.REFLECTIVE) + top.setBoundaryType(openmoc.REFLECTIVE) + + +Cells and Universes +------------------- + +The next step to create a geometry is to instantiate cells which represent unique geometric shapes and use them to construct universes. The CSG formulations for cells and universes in OpenMOC are discussed in further detail in :ref:`Cells ` and :ref:`Universes `, respectively. OpenMOC provides the ``Cell`` class for regions of space bounded by ``Surface`` halfspaces and which may be filled by a ``Material`` or ``Universe``. The following code snippet illustrates how to create cells filled by the fuel and moderator materials. Next, the script adds the appropriate halfspace of the circle surface created in the preceding section to each cell. + +.. code-block:: python + + # Retrieve the fuel and moderator materials + uo2 = materials['UO2'] + water = materials['Water'] + + # Initialize the cells for the fuel pin and moderator + # with optional string names + fuel = openmoc.Cell(name='fuel cell') + moderator = openmoc.Cell(name='moderator cell') + + # Assign the appropriate materials to fill each cell + fuel.setFill(uo2) + moderator.setFill(water) + + # Add the circle surface to each cell + fuel.addSurface(halfspace=-1, surface=circle) + moderator.addSurface(halfspace=+1, surface=circle) + +Each universe is comprised of one or more cells. A ``Universe`` can be instantiated and each of the previously created cells added to it as shown in the following snippet. + +.. code-block:: python + + # Initialize a universe with an optional string name + pin_univ = openmoc.Universe(name='pin universe') + + # Add each cell to the universe + pin_univ.addCell(fuel) + pin_univ.addCell(moderator) + +The OpenMOC ``Cell`` class may not only be filled with materials, but universes as well. As a result, a geometry may be constructed of a hierarchy of nested cells/universes. A hierarchichal geometry permits a simple treatment of repeating geometric structures on multiple length scales (*e.g.*, rectangular arrays of fuel pins and fuel assemblies). + +OpenMOC does not place a limit on the hierarchical depth - or number of nested universe levels - that a user may define in constructing a geometry. The only limitation is that at the top of the hierarchy, a *root* cell must encapsulate the entire geometry in a *root* universe. The following code snippet illustrates the creation of a ``Cell`` which is filled by a lattice constructed in the next section. The appropriate halfspaces for the planes defined in the preceding section are added to the cell to enforce boundaries on the portion of the root universe relevant to the geometry. + +.. code-block:: python + + # Initialize a cell filled by a nested lattice with an optional + # string name. This cell resides within the root universe. + root_cell = openmoc.Cell(name='root cell') + root_cell.setFill(lattice) + + # Add the bounding planar surfaces to the root cell + root_cell.addSurface(halfspace=+1, surface=left) + root_cell.addSurface(halfspace=-1, surface=right) + root_cell.addSurface(halfspace=+1, surface=bottom) + root_cell.addSurface(halfspace=-1, surface=top) + + +Rings and Sectors +----------------- + +The spatial discretization_ of the geometry is a key determining factor in the accuracy of OpenMOC's simulation results. This is especially important since OpenMOC presently uses the :ref:`Flat Source Region Approximation `. The spatial discretization is most relevant in regions where the flux gradient is greatest. In LWRs composed of cylindrical fuel pins, the flux gradient is largely determined by the distance to the center of the nearest fuel pin and the angle formed between the center of the fuel pin and the point of interest (*i.e.*, `polar coordinates`_). As a result, discretization along the radial coordinate using cylindrical **rings**, and along the angular coordinate using angular **sectors** is the most applicable way to discretize the geometry to capture the flux gradient. + +This type of discretization is particularly useful for codes which can make use of an `unstructured mesh`_, such as OpenMOC with its general :ref:`Constructive Solid Geometry ` formulation. To subdivide cylindrical fuel pins into rings and sectors in an LWR model would require a substantial amount of work for the user to create the necessary ``ZCylinder`` and/or ``Plane`` objects. Since this is a commonly needed feature for many users, OpenMOC includes the ability to automatically subdivide cells that contain at least one ``ZCylinder`` surface into rings and equally spaced angular sectors. In particular, OpenMOC uses **cell cloning** to create clones (or copies) of a ``Cell`` object and differentiates each one with ``ZCylinder`` or ``Plane`` objects to subdivide the pin cell. + +There are three cases where rings can be created in a cell: + +1. A ``Cell`` contains one ``ZCylinder`` with a negative halfspace. +2. A ``Cell`` contains one ``ZCylinder`` with a negative halfspace and one ``ZCylinder`` with a positive halfspace. +3. A ``Cell`` contains one ``ZCylinder`` with a positive halfspace. + +Rings for cases 1 and 2 are create such that each ring is of **equal volume**. Rings for cases 3 are created with equal **ring spacing**, where :math:`(R_{outer} - R_{inner})` is the same for all rings. The outer bounding ring for case 3 is set to the distance from the center of the universe that the cell is in to the corner of the parent lattice cell or, if one doesn't exist, the geometry bounding box. The rings for case 3 are chosen to have **equal spacing** instead of **equal volume** so that the inner ring (often a moderator ring next to a fuel pin) has a relatively small radius in order to capture the sharp flux gradient outside a fuel pin. The figure below shows a plot for the materials and plots of the cells for cases 1, 2, and 3 where 3 rings have been created for the corresponding cell in each case: + +.. _figure_annular_pin_rings: + +.. table:: + + +------------------------------------------------+--------------------------------------------------+-------------------------------------------------+----------------------------------------------------+ + | .. _figure_annular_pin_rings_a: | .. _figure_annular_pin_rings_b: | .. _figure_annular_pin_rings_c: | .. _figure_annular_pin_rings_d: | + | | | | | + | .. image:: ../../img/annular_pin_materials.png | .. image:: ../../img/annular_pin_inner_rings.png | .. image:: ../../img/annular_pin_fuel_rings.png | .. image:: ../../img/annular_pin_outer_rings.png | + | :width: 90 % | :width: 90 % | :width: 90 % | :width: 90 % | + | :align: left | :align: left | :align: left | :align: left | + +------------------------------------------------+--------------------------------------------------+-------------------------------------------------+----------------------------------------------------+ + +The following code snippet illustrates how a user may designate a positive integral number of rings and sectors for fuel pin ``Cells`` and a positive integral number of sectors with no rings for moderator ``Cells`` using the ``Cell.setNumRings(...)`` and ``Cell.setNumSectors(...)`` class methods. + +.. code-block:: python + + # Subdivide the fuel region into 3 rings and 12 angular sectors + fuel.setNumRings(3) + fuel.setNumSectors(12) + + # Subdivide the moderator region into 4 angular sectors + moderator.setNumSectors(4) + +The plots shown below illustrate the pin cell material layout (left) and flat source region layout (right) where the flat source regions have been discretized using 3 equal volume rings and 12 sectors in the fuel and 16 sectors in the moderator. + +.. _figure_pin_cell_fsrs: + +.. table:: + + +--------------------------------------------------------+--------------------------------------------------------+ + | .. _figure_pin_cell_fsrs_a: | .. _figure_pin_cell_fsrs_b: | + | | | + | .. image:: ../../img/pin-cell-materials.png | .. image:: ../../img/pin-cell-fsrs.png | + | :width: 50 % | :width: 50 % | + | :align: right | :align: left | + +--------------------------------------------------------+--------------------------------------------------------+ + +As seen in the figure above, the sector divisions start along the plane :math:`\pi/4` radians clockwise of the horizontal plane. The user may wish to capture gradients in the moderator by adding rings in the moderator. The following code snippet repeats the scenario above, but with 2 rings in the moderator. + +.. code-block:: python + + # Subdivide the fuel region into 3 rings and 12 angular sectors + fuel.setNumRings(3) + fuel.setNumSectors(12) + + # Subdivide the moderator region into 2 rings and 16 angular sectors + moderator.setNumRings(2) + moderator.setNumSectors(16) + +Again, the pin cell materials are illustrated below on the left, while the flat source regions are displayed on the right with 2 rings now present in the moderator. + +.. _figure_pin_cell_fsrs_moderator_rings: + +.. table:: + + +--------------------------------------------------------+--------------------------------------------------------+ + | .. _figure_pin_cell_fsrs_moderator_rings_a: | .. _figure_pin_cell_fsrs_moderator_rings_b: | + | | | + | .. image:: ../../img/pin-cell-materials.png | .. image:: ../../img/pin-cell-fsrs-moderator-rings.png | + | :width: 50 % | :width: 50 % | + | :align: right | :align: left | + +--------------------------------------------------------+--------------------------------------------------------+ + +Lastly, the rings and sectors can be used to discretize regions between 2 ``ZCylinder`` objects, such as annular fuel. The following code snippet discretizes annular fuel into 3 rings and 12 sectors with the inner coolant and outer moderator both discretized into 8 sectors with no rings. + +.. code-block:: python + + # Subdivide the inner coolant region into 8 angular sectors + inner_coolant.setNumSectors(8) + + # Subdivide the annular fuel region into 3 rings and 12 sectors + fuel.setNumRings(3) + fuel.setNumSectors(12) + + # Subdivide the outer moderator region into 8 angular sectors + outer_moderator.setNumSectors(8) + + +The annular pin cell materials are illustrated below on the left, with the resulting fuel and moderator discretization presented on the right. + +.. _figure_pin_cell_fsrs_moderator_annular: + +.. table:: + + +--------------------------------------------------------+--------------------------------------------------------+ + | .. _figure_pin_cell_fsrs_moderator_annular_a: | .. _figure_pin_cell_fsrs_moderator_annular_b: | + | | | + | .. image:: ../../img/pin-cell-materials-annular.png | .. image:: ../../img/pin-cell-fsrs-annular.png | + | :width: 50 % | :width: 50 % | + | :align: right | :align: left | + +--------------------------------------------------------+--------------------------------------------------------+ + +.. note:: Rings may **only** be used in ``Cell`` objects that contain a ``ZCylinder`` surface, such as a fuel pin. + +.. note:: Each subdivided region will be filled by the **same Material** as the ``Cell`` object created by the user in the Python script. + + +Lattices +-------- + +Once the cells for the geometry have been created, OpenMOC's ``Lattice`` class may be used to represent repeating patterns of the cells on a rectangular array. The CSG formulation for lattices is described further in :ref:`Lattices `. In OpenMOC, the ``Lattice`` class is a subclass of the ``Universe`` class. The following code snippet illustrates the creation of a 4 :math:`\times` 4 lattice with each lattice cell filled by the pin universe created earlier. The total width of the lattice in :math:`x` and :math:`y` are defined as parameters when the lattice is initialized. The lattice dimensions are used to define the rectangular region of interest centered at the origin of the ``Universe`` filling each lattice cell. + +.. code-block:: python + + # Initialize the lattice for the geometry + lattice = openmoc.Lattice(name='4x4 pin lattice') + lattice.setWidth(width_x=5.04, width_y=5.04) + + # Assign each lattice cell a universe ID + lattice.setUniverses([[pin_univ, pin_univ, pin_univ, pin_univ], + [pin_univ, pin_univ, pin_univ, pin_univ], + [pin_univ, pin_univ, pin_univ, pin_univ], + [pin_univ, pin_univ, pin_univ, pin_univ]]) + + +Geometry +-------- + +The final step in creating a geometry is to instantiate OpenMOC's ``Geometry`` class. The ``Geometry`` class is the *root* node in a tree data structure which encapsulates all ``Materials``, ``Surfaces``, ``Cells``, ``Universes`` and ``Lattices``. The following code snippet illustrates the creation of a *root* ``Cell`` and ``Universe`` as well as a ``Geometry`` object. Next, the root universe is registered with the geometry. The last line of the script is called once all primitives have been registered and is used to traverse the CSG hierarchy and index the flat source regions in the geometry. + +.. code-block:: python + + # Initialize the root universe object + root_univ = openmoc.Universe(name='root universe') + root_univ.addCell(root_cell) + + # Initialize an empty geometry object + geometry = openmoc.Geometry() + + # Register the root universe with the geometry + geometry.setRootUniverse(root_univ) + + +---------------- +Track Generation +---------------- + +Once the geometry has been initialized for a simulation, the next step is to perform ray tracing for track generation. The track generation process and algorithms in OpenMOC are described in more detail in :ref:`Track Generation `. This step requires the instantiation of a ``TrackGenerator`` object and a function call to generate the tracks as illustrated in the following code snippet. + +.. code-block:: python + + # Initialize the track generator after the geometry has been + # constructed. Use 64 azimuthal angles and 0.05 cm track spacing. + track_generator = openmoc.TrackGenerator(geometry, num_azim=64, \ + spacing=0.05) + + # Generate tracks using ray tracing across the geometry + track_generator.generateTracks() + + +-------------------- +MOC Source Iteration +-------------------- + +One of OpenMOC's ``Solver`` subclasses may be initialized given the ``TrackGenerator`` objects discussed in the preceding section. The most commonly used subclasses for OpenMOC simulations are itemized below: + + * ``CPUSolver`` - multi-core CPUs, memory efficient, good parallel scaling [CPUs]_ + * ``GPUSolver`` - GPUs, 30-50 :math:`\times` faster than CPUs [GPUs]_ + + +Criticality Calculations +------------------------ + +The following code snippet illustrates the instantiation of the ``CPUSolver`` for multi-core CPUs. The code assigns runtime parameters to the solver and calls the ``computeEigenvalue(...)`` routine to execute the :ref:`MOC Source Iteration Algorithm `. + +.. code-block:: python + + # Initialize a solver for the simulation and set the number of + # threads and source convergence threshold + solver = openmoc.CPUSolver(track_generator) + solver.setNumThreads(4) + solver.setConvergenceThreshold(1E-5) + + # Converge the source with up to a maximum of 1000 source iterations + solver.computeEigenvalue(1000) + + # Print a report of the time to solution + solver.printTimerReport() + + +Fixed Source Calculations +------------------------- + +It is also possible to add a fixed source to any region in OpenMOC. During computation of the total source, a fixed source is added together with the calculated scattering source and fission source for each flat source region. By default, the fixed source is set to zero everywhere. The ``setFixedSourceByFSR(...)`` routine allows the user to set the fixed source in a given flat source region using its unique ID. For most calcuations, setting the fixed source for every flat source region of interest individually can be cumbersome. In addition, this would require retreiving the unique ID for every flat source region in which the user desires to set the fixed source. Therefore, the ``setFixedSourceByCell(...)`` routine allows the user to set the fixed source for every flat source region within a cell to a common value. An example is given below for setting the fixed source of a ``Cell`` with a point source of unity in the first energy group. + +.. code-block:: python + + # Set the fixed source inside the source cell in group 1 to unity + solver.setFixedSourceByCell(source_cell, 1, 1.0) + + +The equivalent code for setting the point source of all flat source regions within the source cell using ``setFixedSourceByFSR(...)`` is given below. + +.. code-block:: python + + # Get the unique ID of the cell containing the point source + point_source_cell_id = source_cell.getId() + + # Loop over all FSRs and test if the FSR is within the point source cell + for fsr_id in range(solver.getGeometry().getNumFSRs()): + cell = solver.getGeometry().findCellContainingFSR(fsr_id) + + # If the FSR is within the point source cell, set the fixed source + if cell.getId() == point_source_cell_id: + solver.setFixedSourceByFSR(fsr_id, 1, 1.0) + +In this case, it is far simpler to set the fixed source by ``Cell``. However, there may be cases where the user may wish to set the fixed source within a ``Cell`` to different values. For instance, if the user wishes to model a continuously varying fixed source and there are multiple flat source regions within some ``Cell``, then for each flat source region within the cell the fixed source would need to be set individually. + +For instance, if the user desires to input a source based on the location within the geometry, setting the source with ``setFixedSourceByFSR(...)`` could be useful. In particular if a user has defined a fucntion ``source_distribution`` which provides the source over the flat source regions that depends on the coordinates within the geometry and the energy group, the following code will set the source to the appropriate values. + +.. code-block:: python + + # Set the source every cell to the desired distribution + for fsr_id in range(solver.getGeometry().getNumFSRs()): + + # Get the coordinates of some point within the FSR + pt = solver.getGeometry().getFSRPoint(fsr_id) + x_pt = pt.getX() + y_pt = pt.getY() + + # Set the FSR source for every group + L = num_x * width_x / 2 + H = num_y * width_y / 2 + for g in range(materials['Water'].getNumEnergyGroups()): + group = g + 1 + source_value = source_distribution(x_pt, y_pt, group) + solver.setFixedSourceByFSR(fsr_id, group, source_value) + +The OpenMOC ``Solver`` has other solution options in addition to the eigenvalue solver which can be very useful for fixed source calculations. Specifically, the ``computeFlux(...)`` and ``computeSource(...)`` routines solve neutron transport over the problem without computing an eigenvalue. + +.. note:: The fixed source can **only** be set **after** ``TrackGenerator`` has generated tracks + +Flux Calculations +----------------- + +For many fixed source calculations, there is no fissionable material in the problem and the user simply desires the flux distribution within the specified geometry. For these problems the ``computeFlux(...)`` routine calculates the flux distribution within the geometry without computing any sources. Only the fixed source specified by the user is used to determine the total source distribution. This mode can be useful for solving problems where the user already knows the total neutron source distribution. + +To illustrate the effect of this solver, a fixed source problem is chosen. This problem involves a :math:`200 \times 200` grid of water cells with a cell in the upper left filled with a fixed source in the first group. A code snippet is presented below showing the initialization of the source and solver for this problem. + +.. code-block:: python + + # Initialize the OpenMOC solver + solver = openmoc.CPUSolver(track_generator) + solver.setNumThreads(num_threads) + solver.setConvergenceThreshold(tolerance) + + # Set the flux in the source cell to unity and compute the flux + solver.setFixedSourceByCell(source_cell, 1, 1.0) + solver.computeFlux(max_iters) + +The first group flux is plotted below. All other flux plots are zero throughout the entire geometry because the scattering source is not accounted for in ``computeFlux(...)`` and neutrons are always born in the first group. By using the ``computeFlux(...)`` routine, OpenMOC is directed to only use the provided fixed source and not to update for fission or scattering. Notice that there are prominent ray effects since there is no scattering in this problem, an inherent characteristic of MOC solvers. The MOC solver is defined with 4 azimuthal angles for the figure on the left and 32 azimuthal angles for the figure on the right. As the number of angles increases, the effect is not as noticeable but is still present. + +.. _figure_fixed_source_flux_calc: + +.. table:: + + +--------------------------------------------------------+--------------------------------------------------------+ + | .. _figure_fixed_source_flux_calc_a: | .. _figure_fixed_source_flux_calc_b: | + | | | + | .. image:: ../../img/fs-flux-calc-4-angles-group-1.png | .. image:: ../../img/fs-flux-calc-32-angles-group-1.png| + | :width: 50 % | :width: 50 % | + | :align: right | :align: left | + +--------------------------------------------------------+--------------------------------------------------------+ + +While this case seems ill-suited for the ``computeFlux(...)`` routine, ``computeFlux(...)`` is very useful for cases where the total source is known and can be defined by the user. For instance, if the total source :math:`S_g` for energy group :math:`g` is defined to be a cosine distribution such as + +.. math:: + S_g(x,y) = S_g(0,0) \cos{\frac{x}{L}} \cos{\frac{y}{H}} + +where the geometry spans :math:`x \in (-L, L)` and :math:`y \in (-H, H)`. The source can be set using ``setFixedSourceByFSR(...)`` as described above. If the geometry is filled entirely with water and the ``computeFlux(...)`` routine is used to resolve the flux, the solver accurately computes the flux distribution as plotted below. + +.. _figure_cosine_flux_distribution: + +.. figure:: ../../img/cosine_flux_distribution.png + :align: center + :figclass: align-center + :width: 400px + + +Source Calculations +------------------- + +In other problems, the source distribution is desired for a set eigenvalue. For this case, the ``computeSource(...)`` routine can be used, which calculates the total source (including any fixed source) in each flat source region iteratively. At the end of each transport sweep, the eigenvalue is reset to the eigenvalue set by the user. By default this value is 1.0. Returning to the first problem discussed using the ``computeFlux(...)`` routine where a fixed source was placed in a geometry filled with water, the ``computeFlux(...)`` routine could not account for scattering. Since the ``computeSource(...)`` routine computes both scattering and fission sources during transport sweeps, it is able to account for scattering and compute the correct flux distribution. The line below shows how the ``computeSource(...)`` routine can be called. + +.. code-block:: python + + solver.computeSource(max_iters) + +The resulting flux distribution in the third energy group (which previously was calculated to be zero everywhere) is shown below using 4 azimuthal angles in the figure to the left and 32 azimuthal angles in the figure to the right. Notice that ray effects are still present when a low number of azimuthal angles are used, but the effects are far less extreme than observed with ``computeFlux(...)`` due to scattering and with 32 azimuthal angles, the ray effects have largely disappeared. + +.. _figure_fixed_source_calc: + +.. table:: + + +--------------------------------------------------------+--------------------------------------------------------+ + | .. _figure_fixed_source_calc_a: | .. _figure_fixed_source_calc_b: | + | | | + | .. image:: ../../img/fs-4-angles-group-3.png | .. image:: ../../img/fs-32-angles-group-3.png | + | :width: 50 % | :width: 50 % | + | :align: right | :align: left | + +--------------------------------------------------------+--------------------------------------------------------+ + + +.. warning:: This calculation mode has not yet been thoroughly tested + +Convergence Options +------------------- + +There are a variety of convergence options available in OpenMOC. These options can be set in the ``res_type`` optional parameter of the ``computeEigenvalue(...)`` and ``computeSource(...)`` solvers. The options for ``res_type`` are: + +- **SCALAR_FLUX** - Sets the convergence based on the enegy-integrated scalar flux by each flat source region. This is the convergence criteria for ``computeFlux(...)``. +- **TOTAL_SOURCE** - Sets the convergence based on the energy-integrated total source by each flat source region. This is the default for ``computeSource(...)``. +- **FISSION_SOURCE** - Sets the convergence based on the energy-integrated fission source by each flat source region. This is the default for ``computeEigenvalue(...)``. + +An example of setting the convergence option of a criticality calculation to the scalar flux is given below. + +.. code-block:: python + + # Compute the eigenvlaue with a maximum of 1000 source iterations + # and converge by the scalar flux + solver.computeEigenvalue(1000, res_type=openmoc.SCALAR_FLUX) + + +Polar Quadrature +---------------- + +In OpenMOC, there are five included polar quadrature sets that couple with the standard constant-angle azimuthal quadrature set. These include equal angles, equal weights, Gauss Legendre, Leonard, and Tabuchi Yamamoto polar quadrature sets. Users can also input a custom polar quadrature set by manually setting the weights and sines of the polar angles. Example code on how to create the 6 polar quadrature sets is included below. + +.. code-block:: python + + import openmoc + import numpy as np + + ... + + # Create a Tabuchi Yamamoto PolarQuad object with 3 polar angles + ty_polar_quad = openmoc.TYPolarQuad() + ty_polar_quad.setNumPolarAngles(3) + + # Create a Gauss Legendre PolarQuad object with 3 polar angles + gl_polar_quad = openmoc.GLPolarQuad() + gl_polar_quad.setNumPolarAngles(3) + + # Create a Leonard PolarQuad object with 3 polar angles + leonard_polar_quad = openmoc.LeonardPolarQuad() + leonard_polar_quad.setNumPolarAngles(3) + + # Create an Equal Weights PolarQuad object with 3 polar angles + ew_polar_quad = openmoc.EqualWeightsPolarQuad() + ew_polar_quad.setNumPolarAngles(3) + + # Create an Equal Angles PolarQuad object with 3 polar angles + ea_polar_quad = openmoc.EqualAnglesPolarQuad() + ea_polar_quad.setNumPolarAngles(3) + + # Create a Custom PolarQuad object with 3 polar angles + custom_polar_quad = openmoc.EqualAnglesPolarQuad() + custom_polar_quad.setNumPolarAngles(3) + thetas = np.array([np.pi/20.0, np.pi/3.0, np.pi/2.5]) + weights = np.array([0.2, 0.4, 0.4]) + sin_thetas = np.sin(thetas) + custom_polar_quad.setSinThetas(sin_thetas) + custom_polar_quad.setWeights(weights) + ... + +In order for a user specified quadrature set to be used in solving an MOC problem, it needs to be given to the Solver object. Example code on how to assign a polar quadrature set to a Solver and plot the polar quadrature set associated with the Solver is included below. + +.. code-block:: python + + import openmoc + + ... + + # Create a Leonard PolarQuad object with 3 polar angles + leonard_polar_quad = openmoc.LeonardPolarQuad() + leonard_polar_quad.setNumPolarAngles(3) + + # Create a CPUSolver and give it the Leonard PolarQuad object + solver = openmoc.CPUSolver(track_generator) + solver.setPolarQuadrature(leonard_polar_quad) + solver.computeEigenvalue() + + # Plot the quadrature set used in the solver + openmoc.plotter.plot_quadrature(solver) + ... + +Plots of the six quadrature sets with 3 polar angles and 16 azimuthal angles are shown in :ref:`Figure 4 `. + +.. _figure-polar-quads: + +.. figure:: ../../img/polar_quadrature_sets.png + :align: center + :figclass: align-center + :width: 1000px + + **Figure 4**: Polar quadrature sets with 3 polar angles and 16 azimuthal angles. + +The quadrature recommended by [Yamamoto]_ is used by default for the polar angles and weights in OpenMOC. + +FSR Volume Correction +--------------------- + +To be updated... + + +----------------- +CMFD Acceleration +----------------- + +OpenMOC has an integrated CMFD acceleration framework that allows users to greatly accelerate the convergence of their neutron transport problems and achieve run-time time improvements of over 30 times. The CMFD acceleration framework is implemented in one class, ``Cmfd``. Running a simulation with CMFD acceleration is quite easy and requires only a few additional lines of code in your input file and one command line option. The following code snippet illustrates the instantiation of the ``Cmfd`` class used to generate the CMFD mesh for your problem and give that mesh to the geometry. + +.. code-block:: python + + # Initialize the Cmfd object + cmfd = Cmfd() + cmfd.setLatticeStructure(17,17) + + # Optional CMFD parameters + cmfd.setGroupStructure([1,4,8]) + cmfd.setOpticallyThick(False) + cmfd.setSORRelaxationFactor(1.5) + cmfd.setConvergenceThreshold(1.E-8) + cmfd.setFluxUpdateOn(True) + + # Initialize the Geometry object + geometry = Geometry() + geometry.setCmfd(cmfd) + ... + +These lines of code should be placed in your input file at the location where the geometry object would be initialize had your problem been set up without CMFD acceleration. In this code, the cmfd object is initialized and the CMFD mesh lattice structure is set. In is generally best to have the CMFD mesh overlap with either the assembly or pincell mesh of the problem, but OpenMOC is designed to accept any regular mesh structure. The optional parameters are described below: + + * ``setFluxUpdateOn`` (default: True) - This function is included to give the users the option to overlay the CMFD mesh, but toggle the CMFD update. If the CMFD mesh breaks up any parts of the geometry, this function be can be used to overlay the CMFD mesh for segmentation, but not perform a CMFD solve and flux update after each MOC iteration. This is useful in comparing runs with and without CMFD and ensuring the exact same segments are used. + * ``setGroupStructure`` (default: same as MOC group structure) - OpenMOC is able to perform CMFD on a coarse energy group structure to allow fine energy group problems to be accelerated with CMFD without incurring a significant computational overhead for CMFD. This function takes a python list as input with the first value of 1 (to indicate the first energy group) followed by an increasing values ending with the number of energy groups plus 1. In the example above, a 7 group MOC problem is broken up into 2 energy groups for CMFD. + * ``setOpticallyThick`` (default: False) - OpenMOC uses a correction factor on the material diffusion coefficients as described in the Theory and Methodology section. This correction factor is turned off by default. + * ``setSORRelaxationFactor`` (default: 1.0) - As described in the Theory and Methodology section, OpenMOC use the successive over-relaxation method (SOR) to solve the CMFD diffusion eigenvalue problem. The SOR method can use an over-relaxation factor to speed up the convergence of problems. Valid input for the SOR relaxation factor are values between 0 and 2. By default the SOR factor is set to 1.0, reducing the SOR method to the Gauss-Seidel method. + * ``setConvergenceThreshold`` (default: 1.E-7) - This method is used to set the convergence of the root-mean-square-error on the region and group wise fission source of the CMFD diffusion eigenvalue problem. By default, the convergence threshold is set at 1.E-7 and is sufficient for most problems. + +With those few additional lines of code, you should be able to create an input file for any problem and utilize CMFD acceleration. The input file ``c5g7-cmfd.py`` provides a good example of how an input file is constructed that uses CMFD acceleration. + +.. _logging module: http://mit-crpg.github.io/OpenMOC/doxygen/html/log_8h.html +.. _printf: http://www.cplusplus.com/reference/cstdio/printf/ +.. _formatted data: http://www.cplusplus.com/reference/cstdio/printf/ +.. _CSG: http://en.wikipedia.org/wiki/Constructive_solid_geometry +.. _Python Tutorial: http://docs.python.org/2/tutorial/ +.. _Code Academy Python Course: http://www.codecademy.com/tracks/python +.. _pin cell: https://github.com/mit-crpg/OpenMOC/tree/master/sample-input/pin-cell +.. _C5G7 benchmark problem: https://github.com/mit-crpg/OpenMOC/tree/master/sample-input/benchmarks/c5g7 +.. _NumPy: http://www.numpy.org/ +.. _HDF5: http://www.hdfgroup.org/HDF5/ +.. _dictionary: http://docs.python.org/2/tutorial/datastructures.html#dictionaries +.. _HDFView: http://www.hdfgroup.org/products/java/hdfview/ +.. _h5py: http://www.h5py.org/ +.. _HDF5 group: http://docs.h5py.org/en/latest/high/group.html +.. _HDF5 datasets: http://docs.h5py.org/en/latest/high/dataset.html +.. _discretization: http://en.wikipedia.org/wiki/Discretization +.. _polar coordinates: http://en.wikipedia.org/wiki/Polar_coordinate_system +.. _unstructured mesh: http://en.wikipedia.org/wiki/Unstructured_grid + + +---------- +References +---------- + +.. [CPUs] William Boyd, Kord Smith, Benoit Forget, and Andrew Siegel, "Parallel Performance Results for the OpenMOC Method of Characteristics Code on Multi-Core Platforms." *Submitted to the Proceedings of PHYSOR*, Kyoto, Japan (2014). + +.. [GPUs] William Boyd, Kord Smith, and Benoit Forget, "A Massively Parallel Method of Characteristic Neutral Particle Transport Code for GPUs." *Proc. Int'l Conf. Math. and Comp. Methods Appl. to Nucl. Sci. and Eng.*, Sun Valley, ID, USA (2013). + +.. [Yamamoto] A. Yamamoto, M. Tabuchi, N. Sugimura, T. Ushio and M. Mori, "Derivation of Optimum Polar Angle Quadrature Set for the Method of Characteristics Based on Approximation Error for the Bickley Function." *Journal of Nuclear Science and Engineering*, **44(2)**, pp. 129-136 (2007). diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst new file mode 100644 index 000000000..ddb9f19d8 --- /dev/null +++ b/docs/source/usersguide/install.rst @@ -0,0 +1,128 @@ +.. _install: + +============================== +Installation and Configuration +============================== + +------------- +Prerequisites +------------- + +* :ref:`Installing Prerequisites on Ubuntu ` +* :ref:`Installing Prerequisites on Mac OS X ` + + +-------------------- +Obtaining the Source +-------------------- + +All OpenMOC source code is hosted on GitHub_. You can download the source code directly from GitHub or, if you have the Git_ version control software installed on your computer, you can use git to obtain the source code. The latter method has the benefit that it is easy to receive updates directly from the GitHub repository. GitHub has a good set of instructions_ for how to set up git to work with GitHub since this involves setting up ssh_ keys. With git installed and setup, the following command will download the full source code from the GitHub repository:: + + git clone https://github.com/mit-crpg/OpenMOC.git + +.. _GitHub: https://github.com/mit-crpg/OpenMOC +.. _Git: http://git-scm.com +.. _ssh: http://en.wikipedia.org/wiki/Secure_Shell +.. _instructions: http://help.github.com/set-up-git-redirect + + +-------------------- +Building From Source +-------------------- + +Standard Build Configuration +---------------------------- + +To compile and install the code in a user local directory (recommended), simply run the following from the console:: + + python setup.py install --user + +.. warning:: The :option:`--user` flag should be used verbatim and should **NOT** be replaced with your username. + +To compile and install the code in the directory of all Python packages accessible to all users of your machine (not recommended), run the following command:: + + python setup.py install + +The code will now be accessible as a Python module from anywhere on your system. +The main OpenMOC Python package can be imported into any Python script as follows: + +.. code-block:: python + + import openmoc + + +Custom Build Configuration +-------------------------- + +OpenMOC provides a number of user options to customize what and how OpenMOC source is compiled and built on your system. OpenMOC makes use of Python's distutils_ build configuration management module. + +To view a list of all of build commands supported by Python distutils, type the following in the console:: + + python setup.py --help-commands + +To install OpenMOC, we typically recommend using the :program:`install` command which builds and installs the code alongside other commonly referenced Python packagaes. The :program:`install` command includes its own set of options, some of which are defined by OpenMOC and some of which are defined by distutils_. To view a list of these options, type the following in the console:: + + python setup.py install --help + + +.. _build_configuration_options: + +Build Configuration Options +--------------------------- + +This section section will provides an overview of the most useful and relevant build options for OpenMOC developers. + +.. option:: --user + +Installs OpenMOC in a user local directory (ie, `/home/username/.local/lib/pythonX.X/site-packages`) where it will only be accessible to your username. Installation without this option will instead install OpenMOC in the main Python directory accessible to all users of your machine (ie, `/usr/lib/pythonX.X/site-packages/`). This option is highly recommended for developers as it will prevent your Python packages from being polluted with code that has not yet been validated. + + +.. option:: --prefix= + +Installs OpenMOC to an explicitly defined directory. This options is generally not useful unless your directory is included in your :envvar:`PYTHONPATH` such that you can import ``openmoc`` into your Python scripts. + + +.. option:: --cc= + +Sets the C++ compiler for the main ``openmoc`` module. Presently, GNU's gcc_, Intel's icpc_, Apple's clang_ and IBM's bgxlc_ are all configured if the path to the binary is pointed to by by the :envvar:`PATH` environment variable. The default setting is the :program:`gcc` compiler. + + +.. option:: --fp= + +Sets the floating point precision level for the main ``openmoc`` module. This sets the :envvar:`FP_PRECISION` macro in the source code by setting it as an environment variable at compile time. The default setting is :envvar:`single`. + + +.. option:: --with-cuda + +Compiles the ``openmoc.cuda`` module using the :program:`nvcc` compiler. This module contains :cpp:class:`GPUSolver` class with MOC routines for execution on NVIDIA GPUs. The default build configuration does not include the ``openmoc.cuda`` module. + + +.. option:: --debug-mode + +Compiles with debugging symbols and information by including the :envvar:`-g` compile flag. + +.. option:: --profile-mode + +Compiles with profiling information by including the :envvar:`-p` compile flag. + +.. option:: --with-ccache + +Compiles using ccache_ which uses a cache to speedup compilation of unchanged source files with the binaries from previous compilations. This flag is only relevant for developers needing to frequently recompile the source code. The ccache p]rogram must be installed for this flag to work. The following console command will install ccache on Ubuntu:: + + sudo apt-get install ccache + + +.. _distutils: http://docs.python.org/2/library/distutils.html#module-distutils +.. _gcc: http://gcc.gnu.org/ +.. _icpc: http://software.intel.com/en-us/intel-compilers +.. _clang: http://clang.llvm.org/ +.. _bgxlc: http://www-03.ibm.com/software/products/us/en/ccompfami/ +.. _ccache: http://ccache.samba.org +.. _NVIDIA: http://www.nvidia.com/content/global/global.php +.. _BlueGene: http://www-03.ibm.com/systems/technicalcomputing/solutions/bluegene/ + +----------------------------- +Installing on Ubuntu with PPA +----------------------------- + +A binary package for Debian Linux derivatives, such as Ubuntu, is under development. Please check back at a later time for further updates. diff --git a/docs/source/usersguide/mac_prerequisites.rst b/docs/source/usersguide/mac_prerequisites.rst new file mode 100644 index 000000000..207360067 --- /dev/null +++ b/docs/source/usersguide/mac_prerequisites.rst @@ -0,0 +1,85 @@ +.. _mac_prerequisites: + +==================================== +Installing Prerequisites on Mac OS X +==================================== + +There are a few prerequisites which must be installed on your machine before you will be able to build and install OpenMOC. All of the prerequisites can easily be installed using a standard package manager, such as MacPorts_ for Mac OS X. The following instructions detail which packages are needed, with instructions on how to install them using MacPorts. + +.. note:: It is important to install the following prerequisite packages in the order given - in particular, Python must be installed before NumPy and Matplotlib. + +.. admonition:: Required + + * GNU's C++ compiler_ + + In order to compile OpenMOC, you will need to have a C++ compiler installed on your machine. It is recommended that you build OpenMOC with g++ version 4.4 or later. To install the latest stable version of ``g++`` using MacPorts (v4.8 at the time of this writing), use the following command in the console:: + + sudo port install gcc48 + + Finally, you must set this version of ``g++`` as the default for Macports:: + + sudo port select --set gcc mp-gcc48 + + + * Python_ + + OpenMOC extensively uses Python for rapid data processing and visualization. OpenMOC uses a mixture of fast, compiled C/C++/CUDA code with Python bindingssuch that users are entirely insulated from having to write in C/C++ or CUDA, and can simply write a Python script with calls to OpenMOC. + + Currently, OpenMOC has been tested with Python versions 2.6, 2.7, 3.1 and 3.2. Even if you already have Python installed, it is recommended that you install it again using MacPorts to ensure that it is properly configured with ``g++``. You can easily install version 2.7 using MacPorts as follows:: + + sudo port install python27 + + Finally, you must set this version of ``python`` as the default for Macports:: + + sudo port select --set python python27 + + + * Git_ + + The OpenMOC development team uses the Git_ version control software for code development and collaboration. To download the code from our GitHub_ repository, you must first install git. You can do so using MacPorts as follows:: + + sudo port install git + + + * SWIG_ + + The Simplified Wrapper Interface Generator (SWIG) is used to wrap the compiled C/C++ and CUDA source code and generate Python bindings. SWIG can be installed using MacPorts:: + + sudo port install swig swig-python + + + * NumPy_ + + NumPy is a commonly used, general purpose numerical array creation and manipulation package for Python. OpenMOC uses NumPy to seamlessly transfer numerical data between Python and the C/C++ back-end compiled code. To install NumPy using MacPorts, use the following command:: + + sudo port install py27-numpy + +.. admonition:: Optional + + * matplotlib_ + + The matplotlib Python package is a general purpose utility for plotting and visualizations. OpenMOC uses matplotlib in the ``openmoc.plotter`` module to generate plots, such as flux and power distributions. Although matplotlib and the ``openmoc.plotter`` modules are not required for an OpenMOC simulation, visualizations can be a helpful tool in debugging and input model validation. To install matplotlib using MacPorts issue the following command:: + + sudo port install py27-matplotlib + + + * h5py_ + + The h5py Python package contains tools to create, retrieve, and manipulate data stored using the HDF5_ binary format. OpenMOC leverages the h5py functionality in its ``openmoc.materialize`` module which includes routines to import/export multi-group nuclear cross-section data to/from HDF5. In addition, the ``openmoc.process`` module contains routines to import/export simulation and performance data to/from HDF5 output files. Although h5py and the ``openmoc.materialize`` and ``openmoc.process`` modules are not required to run OpenMOC, they can facilitate fast access and storage of binary data. + + To install h5py using MacPorts, issue the following command:: + + sudo port install py27-h5py + + +.. _GitHub: https://github.com/mit-crpg/OpenMOC +.. _MacPorts: http://www.macports.org/ +.. _compiler: http://gcc.gnu.org/ +.. _Python: http://www.python.org/ +.. _Git: http://git-scm.com +.. _SWIG: http://www.swig.org/ +.. _NumPy: http://www.numpy.org/ +.. _BlueGene: http://www-03.ibm.com/systems/technicalcomputing/solutions/bluegene/ +.. _matplotlib: http://matplotlib.org/ +.. _h5py: http://www.h5py.org/ +.. _HDF5: http://www.hdfgroup.org/HDF5/ diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst new file mode 100644 index 000000000..2251443d1 --- /dev/null +++ b/docs/source/usersguide/processing.rst @@ -0,0 +1,830 @@ +.. _usersguide_processing: + +================================= +Data Processing and Visualization +================================= + +This section is intended to explain in detail the recommended procedures for carrying out common tasks with OpenMOC. While several utilities of varying complexity are provided to help automate the process, in many cases it will be extremely beneficial to do some coding in Python to quickly obtain results. In these cases, and for many of the provided utilities, it is necessary for your Python installation to contain: + +* `Numpy `_ - Required for array-based data manipulation and processing +* `h5py `_ - Required only if reading/writing HDF5_ data files +* `Matplotlib `_ - Optional for plotting utilities + + +Each of these are easily obtainable in Ubuntu through the package manager. + +------------------------- +Exporting Simulation Data +------------------------- + +OpenMOC's ``openmoc.process`` module provides the ``store_simulation_state(...)`` routine to export simulation data to binary output files. The only required parameter for the routine is a ``Solver`` object. Optional parameters may be used to indicate whether to store the data in HDF5_ or as a Python pickle_ file (default), store the fluxes, sources, fission rates and more. All of the supported parameters are listed in :ref:`Table 1 `, and the output variables stored in the binary file are tabulated in :ref:`Table 2 `. + +.. _table_store_simulation_state: + +================= ================== ==================== ========== ==================================== +Parameter Type Default Optional Note +================= ================== ==================== ========== ==================================== +``solver`` ``Solver`` object None No +``fluxes`` boolean False Yes Whether to store the FSR fluxes +``sources`` boolean False Yes Whether to store the FSR sources +``fission_rates`` boolean False Yes Whether to store the fission rates +``use_hdf5`` boolean False (pickle file) Yes Whether to use HDF5_ +``filename`` string 'simulation-state' Yes The filename for storage +``directory`` string 'simulation-states' Yes The directory for storage +``append`` boolean True Yes Append to a file or create a new one +``note`` string None Yes Any comment on the simulation +================= ================== ==================== ========== ==================================== + +**Table 1**: Parameters for the ``openmoc.proces.store_simulation_state(...)`` routine. + +.. _table_output_variables: + +========================= ============== ========================================= +Output Variable Type Note +========================= ============== ========================================= +solver type string 'CPUSolver', 'GPUSolver', etc. +# FSRs integer +# materials integer +# energy groups integer +# tracks integer +# segments integer +track spacing [cm] float +# azimuthal angles integer +# polar angles integer +# iterations integer +source residual threshold float +exponential string 'exp intrinsic' or 'linear interpolation' +CMFD boolean True if CMFD is in use, False otherwise +floating point string 'double' or 'single' +time [sec] float Total time to converge the source +keff float +note string If requested by user +# threads integer For solvers on multi-core CPUs +# threads per block integer For solvers on GPUs +FSR scalar fluxes float array If requested by user +FSR sources float array If requested by user +fission rates float array(s) If requested by user +========================= ============== ========================================= + +**Table 2**: Output variables in a binary file created by the ``openmoc.proces.store_simulation_state(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.process + + # Setup and run simulation + ... + + # Export the simulation data to an output file + openmoc.process.store_simulation_state(solver, use_hdf5=True) + + + +-------------------------- +Retrieving Simulation Data +-------------------------- + +Exporting simulation data is only useful if there is a straightforward means to retrieve it for data processing at a later time. OpenMOC's ``restore_simulation_state(...)`` routine in the ``openmoc.process`` module can be used for this purpose. This routine takes a binary data file created by the ``store_simulation_state(...)`` routine, parses the file and catalogues the data in a Python dictionary_, which it returns to the user. The parameters accepted by the routine are described in :ref:`Table 3 `, while the dictionary keys are identical to the output variables given in :ref:`Table 2 `. + +.. _table_restore_simulation_states: + +============== ======= ====================== ======== +Parameter Type Default Optional +============== ======= ====================== ======== +``filename`` string 'simulation-state.pkl' Yes +``directory`` string 'simulation-states' Yes +============== ======= ====================== ======== + +**Table 3**: Parameters for the ``openmoc.process.restore_simulation_state(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.process + + # Retrieve the simulation state(s) stored in the 'states.h5' file + # and returns the data in a Python dictionary + simulation_state = openmoc.process.restore_simulation_state(filename='states.h5') + + +------------------------ +Computing Reaction Rates +------------------------ + + +Reaction Rates By Tally Mesh +---------------------------- + +The ``openmoc.process`` module supports reaction rate through structured Cartesian mesh tallies, similar to how one might compute such quantities in a Monte Carlo code such as MCNP, Serpent or OpenMC. The ``Mesh`` class allows one to tally a reaction rate in each of its structured cells. :ref:`Table 4 ` below itemizes each of the property attributes of the ``Mesh`` class which can be used to tally reaction rates. + +.. _table_mesh_params: + +======================== =================== ========== ========================================================== +Property Type Default Note +======================== =================== ========== ========================================================== +``dimension`` list of integers None The number of mesh cells in each direction +``lower_left`` list of floats None The lower-left corner of the structured mesh +``upper_right`` list of floats None The upper-right corner of the structrued mesh +``width`` list of floats None The width of mesh cells in each direction (centimeters) +======================== =================== ========== ========================================================== + +**Table 4**: The ``Mesh`` class property attributes for tallying reaction rates. + +.. note:: The ``Mesh`` is assumed to be perfectly coincident with the FSR mesh used in the OpenMOC calculation. + +The ``Mesh.tally_fission_rates(...)`` class method is designed to compute fission rates using the ``'fission'`` cross section in each ``Material`` in a simulation. The parameters accepted by this method are described in :ref:`Table 5 `. + +.. _table_mesh_fiss_rates: + +============= =========== ============== ======== +Parameter Type Default Optional +============= =========== ============== ======== +``solver`` ``Solver`` None No +``volume`` string 'integrated' Yes +============= =========== ============== ======== + +**Table 5**: Parameters for the ``Mesh.tally_fission_rates(...)`` method. + +The code snippet below illustrates how one may compute a mesh fission rate tally for the :file:`/OpenMOC/sample-input/simple-lattice.py` file. The fission rates are returned as a ``numpy.ndarray`` indexed by FSR. + +.. code-block:: python + + import openmoc.process + + # Setup and run simulation + ... + + # Create OpenMOC Mesh on which to tally fission rates + mesh = openmoc.process.Mesh() + mesh.dimension = [4, 4] + mesh.lower_left = [-2., -2.] + mesh.upper_right = [2., 2.] + mesh.width = [1., 1.] + + # Tally OpenMOC fission rates on the Mesh and return NumPy array + fiss_rates = mesh.tally_fission_rates(solver) + +.. note:: The ``'fission'`` cross section must be supplied to each ``Material`` to compute fission rates even though it is *not* needed to perform a simulation. + +The ``Mesh.tally_on_mesh(...)`` class method is designed to compute reaction rates more generally from a user-specified mapping of coefficients (*e.g.*, cross sections) to each material, cell or FSR. The parameters accepted by this method are described in :ref:`Table 6 `. + +.. _table_mesh_rxn_rates: + +====================== =========== ============== ======== +Parameter Type Default Optional +====================== =========== ============== ======== +``solver`` ``Solver`` None No +``domains_to_coeffs`` ``dict`` None No +``domain_type`` string 'fsr' Yes +``volume`` string 'integrated' Yes +``energy`` string 'integrated' Yes +====================== =========== ============== ======== + +**Table 6**: Parameters for the ``Mesh.tally_on_mesh(...)`` method. + +The code snippet below illustrates how one may compile the groupwise coefficients (total cross sections) for each ``Material`` in a Python ``dict`` to supply to ``Mesh.tally_on_mesh(...)`` to compute a total reaction rate tally for the :file:`/OpenMOC/sample-input/simple-lattice.py` file. The reaction rates are returned as a ``numpy.ndarray`` indexed by FSR. + +.. code-block:: python + + import openmoc.process + import numpy as np + + # Setup and run simulation + ... + + # Retrieve the Materials and number of groups from the geometry + materials = geometry.getAllMaterials() + num_groups = geometry.getNumEnergyGroups() + + # Aggregate the total cross sections for each Material + # into a dictionary to pass to the mesh tally + domains_to_coeffs = {} + for material_id in materials: + domains_to_coeffs[material_id] = np.zeros(num_groups) + for group in range(num_groups): + domains_to_coeffs[material_id][group] = \ + materials[material_id].getSigmaTByGroup(group+1) + + # Tally volume-averaged OpenMOC total rates on the Mesh + tot_rates = mesh.tally_on_mesh(solver, domains_to_coeffs) + + +Fission Rates by Universe Level +------------------------------- + +The ``compute_fission_rates(...)`` routine in the ``openmoc.process`` module computes the fission rate for each ``Universe`` in the ``Geometry`` by summing up the fission rates in each ``Cell`` in the ``Universe``. In most cases, a ``Universe`` is replicated in many places throughout the ``Geometry``. To account for this, the routine will separately compute the fission rates for each unique placement of that ``Universe`` in the ``Geometry``. By default, the fission rates will be exported to a Python pickle_ file, but may alternatively be exported to an HDF5_ binary file. Each fission rate will be indexed by a string representing the "path" of ``Universes``, ``Lattices`` and ``Lattice`` cell indices traversed through the ``Geometry`` to reach the flat source region of interest. :ref:`Table 7 ` describes the parameters accepted by the routine. + +.. _table_fission_rates: + +============ ================== ======== ========= +Parameter Type Default Optional +============ ================== ======== ========= +``solver`` ``Solver`` object None No +``use_hdf5`` boolean False Yes +============ ================== ======== ========= + +**Table 7**: Parameters for the ``openmoc.process.compute_fission_rates(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.process + + # Setup and run simulation + ... + + # Compute and export the flat source region fission rates + openmoc.process.compute_fission_rates(solver, use_hdf5=True) + +.. note:: The fission rates are computed for each nested universe level in the hierarchical geometry model. +.. note:: The fission rates are not normalized in any way - this is left to the user's discretion during data processing. + + +---------------------- +Geometry Visualization +---------------------- + + +Plotting Tracks +--------------- + +To plot the tracks crossing the geometry, use the ``plot_tracks(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 8 `. + +.. _table_plot_tracks: + +=================== ========================= ========= ========= =========================================== +Parameter Type Default Optional Note +=================== ========================= ========= ========= =========================================== +``track_generator`` ``TrackGenerator`` None No The tracks of interest +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +=================== ========================= ========= ========= =========================================== + +**Table 8**: Parameters for the ``openmoc.plotter.plot_tracks(...)`` routine. + +The code snippet below illustrates the use of this routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + openmoc.plotter.plot_tracks(geometry) + +A depiction of the tracks for the :file:`/OpenMOC/sample-input/simple-lattice.py` example input file with 4 azimuthal angles and 0.1 cm track spacing is illustrated in :ref:`Figure 1 `. + +.. _figure_tracks: + +.. figure:: ../../img/tracks.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 1**: The tracks crossing a a 4 :math:`\times` 4 lattice. + +.. note:: The runtime required by the plotting routine scales with the number of tracks, which is proportional to the number of azimuthal angles and inversely proportional the track spacing. + + +Plotting Segments +----------------- + +To plot the segments crossing the geometry color-coded by flat source region, use the ``plot_segments(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 9 `. + +.. _table_plot_segments: + +=================== ========================= ========= ========= =========================================== +Parameter Type Default Optional Note +=================== ========================= ========= ========= =========================================== +``track_generator`` ``TrackGenerator`` None No The tracks of interest +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +=================== ========================= ========= ========= =========================================== + +**Table 9**: Parameters for the ``openmoc.plotter.plot_segments(...)`` routine. + +The code snippet below illustrates the use of this routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + openmoc.plotter.plot_segments(geometry) + +A depiction of the segments for the :file:`/OpenMOC/sample-input/simple-lattice.py` example input file with 4 azimuthal angles and 0.1 cm track spacing is illustrated in :ref:`Figure 2 `. + +.. _figure_segments: + +.. figure:: ../../img/segments.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 2**: The segments crossing a a 4 :math:`\times` 4 lattice. + +.. warning:: This routine will require a long time for large geometries or fine track discretization. In addition, Matplotlib consumes a substantial amount of memory to plot the segments and may throw a `segmentation fault`_ for large geometries. +.. note:: The runtime required by the plotting routine scales with the number of segments, which is proportional to the number of flat source regions and number of azimuthal angles and inversely proportional the track spacing. + + +Plotting by Material +-------------------- + +To plot the geometry color-coded by the material ID's throughout the geometry, use the ``plot_materials(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 10 `. + +.. _table_plot_materials: + +=============== =============== ============= ========= ======================================================== +Parameter Type Default Optional Note +=============== =============== ============= ========= ======================================================== +``geometry`` ``Geometry`` None No The ``Geometry`` of interest +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``zcoord`` float None Yes The level along the :math:`z`-axis to plot +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +=============== =============== ============= ========= ======================================================== + +**Table 10**: Parameters for the ``openmoc.plotter.plot_materials(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry + ... + + # Plot a 500 x 500 pixel image of the materials + openmoc.plotter.plot_materials(geometry, gridsize=500) + +A depiction of the materials for the :file:`/OpenMOC/sample-input/simple-lattice.py` example input file is illustrated in :ref:`Figure 3 `. + +.. _figure_materials: + +.. figure:: ../../img/materials.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 3**: A 4 :math:`\times` 4 lattice color-coded by material. + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +Plotting by Cell +---------------- +To plot the geometry color-coded by the cell ID's throughout the geometry, use the ``plot_cells(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 11 `. + +.. _table_plot_cells: + +=============== =============== ============= ========= ======================================================== +Parameter Type Default Optional Note +=============== =============== ============= ========= ======================================================== +``geometry`` ``Geometry`` None No The ``Geometry`` of interest +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``zcoord`` float None Yes The level along the :math:`z`-axis to plot +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +=============== =============== ============= ========= ======================================================== + +**Table 11**: Parameters for the ``openmoc.plotter.plot_cells(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry + ... + + # Plot a 500 x 500 pixel image of the cells + openmoc.plotter.plot_cells(geometry, gridsize=500) + +A depiction of the cells for the :file:`/OpenMOC/sample-input/simple-lattice.py` example input file is illustrated in :ref:`Figure 4 `. + +.. _figure_cells: + +.. figure:: ../../img/cells.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 4**: A 4 :math:`\times` 4 lattice color-coded by cell. + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +Plotting by FSR +--------------- + +To plot the geometry color-coded by the flat source region ID's throughout the geometry, use the ``plot_flat_source_regions(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 12 `. + +.. _table_plot_fsrs: + +================= =============== ============= ========= ======================================================== +Parameter Type Default Optional Note +================= =============== ============= ========= ======================================================== +``geometry`` ``Geometry`` None No The ``Geometry`` of interest +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``centroids`` boolean False Yes Whether to plot the FSR centroids +``marker_type`` string ``'o'`` Yes The marker type to use for FSR centroids +``marker_size`` integer 2 Yes The marker size to use for FSR centroids +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +================= =============== ============= ========= ======================================================== + +**Table 12**: Parameters for the ``openmoc.plotter.plot_flat_source_regions(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry + ... + + # Plot a 500 x 500 pixel image of the flat source regions + openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) + +A depiction of the flat source regions for the :file:`/OpenMOC/sample-input/simple-lattice.py` example input file is illustrated in :ref:`Figure 5 `. + +.. _figure_flat_source_regions: + +.. figure:: ../../img/flat-source-regions.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 5**: A 4 :math:`\times` 4 lattice color-coded by flat source region. + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +Plotting by CMFD Cell +--------------------- + +To plot the geometry color-coded by the CMFD cells throughout the geometry, use the ``plot_cmfd_cells(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 13 `. + +.. _table_plot_cmfd_cells: + +=============== =============== ============= ========= ======================================================== +Parameter Type Default Optional Note +=============== =============== ============= ========= ======================================================== +``geometry`` ``Geometry`` None No The ``Geometry`` of interest +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +=============== =============== ============= ========= ======================================================== + +**Table 13**: Parameters for the ``openmoc.plotter.plot_cmfd_cells(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and cmfd + ... + + # Plot a 500 x 500 pixel image of the CMFD cells + openmoc.plotter.plot_cmfd_cells(geometry, cmfd, gridsize=500) + +A depiction of the flat source regions and CMFD cells for the :file:`/OpenMOC/sample-input/benchmarks/c5g7/c5g7-cmfd.py` example input file is illustrated in :ref:`Figure 6 `. + +.. _figure_cmfd_cells: + +.. table:: + + +------------------------------------------+---------------------------------------------+ + | .. _figure_cmfd_cells_a: | .. _figure_cmfd_cells_b: | + | | | + | .. image:: ../../img/c5g7-fsrs.png | .. image:: ../../img/c5g7-cmfd-cells.png | + | :width: 70 % | :width: 64 % | + | :align: center | :align: center | + +------------------------------------------+---------------------------------------------+ + +**Figure 6**: The flat source regions and CMFD cells for the C5G7 benchmark problem. + + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +------------------ +Flux Visualization +------------------ + +The ``openmoc.plotter`` module includes routines to plot the scalar flux in space and energy, as detailed in the following sections. + +Flux in Space +------------- + +To plot the flat source region scalar fluxes in space, use the ``plot_spatial_fluxes(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 14 `. + +.. _table_plot_fluxes_space: + +================== =============== ============= ========= ======================================================== +Parameter Type Default Optional Note +================== =============== ============= ========= ======================================================== +``solver`` ``Solver`` None No The ``Solver`` used to converge the source +``energy_groups`` list [1] No Create separate plots for each energy group +``norm`` boolean False Yes Whether to normalize fluxes to the mean +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +================== =============== ============= ========= ======================================================== + +**Table 14**: Parameters for the ``openmoc.plotter.plot_spatial_fluxes(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + # Setup solver and converge the source + ... + + # Plot the fluxes for energy groups 1 and 7 in 500 x 500 pixel images + openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,7], gridsize=500) + +A depiction of the group 1 and 7 fluxes for the C5G7 benchmark (:file:`/OpenMOC/sample-input/benchmarks/c5g7`) is illustrated in :ref:`Figure 7 `. + +.. _figure_spatial_fluxes: + +.. table:: + + +------------------------------------------+-----------------------------------------+ + | .. _figure_spatial_fluxes_a: | .. _figure_spatial_fluxes_b: | + | | | + | .. image:: ../../img/flux-group-1.png | .. image:: ../../img/flux-group-7.png | + | :width: 72 % | :width: 75 % | + | :align: center | :align: center | + +------------------------------------------+-----------------------------------------+ + +**Figure 7**: The fast and thermal fluxes in the C5G7 benchmark problem. + + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +Flux in Energy +-------------- + +To plot the flux in energy for one or more flat source regions, use the ``plot_energy_fluxes(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 15 `. + +.. _table_plot_fluxes_energy: + +================= =================== ========= ========= ============================================ +Parameter Type Default Optional Note +================= =================== ========= ========= ============================================ +``solver`` ``Solver`` object None No The ``Solver`` used to converge the source +``fsrs`` list None No The flat source region IDs of interest +``group_bounds`` list None Yes The sequential bounds for each energy group +``norm`` boolean True Yes Whether to normalize the flux across energy +``loglog`` boolean True Yes Whether to use a log-log plotting scale +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +================= =================== ========= ========= ============================================ + +**Table 15**: Parameters for the ``openmoc.plotter.plot_energy_fluxes(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + # Setup solver and converge the source + ... + + # Plot the fluxes vs. energy for flat source regions 0 and 1 + openmoc.plotter.plot_energy_fluxes(solver, fsrs=[0,1]) + +A depiction of the normalized 7-group fluxes for the sample pin cell problem (:file:`/OpenMOC/sample-input/pin-cell/pin-cell.py`) is illustrated in :ref:`Figure 8 `. + +.. _figure_energy_fluxes: + +.. table:: + + +------------------------------------------+-----------------------------------------+ + | .. _figa: | .. _figb: | + | | | + | .. image:: ../../img/flux-fsr-0.png | .. image:: ../../img/flux-fsr-1.png | + | :width: 72 % | :width: 75 % | + | :align: center | :align: center | + +------------------------------------------+-----------------------------------------+ + +**Figure 8**: The normalized moderator and fuel flux for a simple PWR pin cell problem. + + +-------------------------- +Fission Rate Visualization +-------------------------- + +The ``openmoc.plotter`` module includes routines to plot the energy-integrated fission rates in each flat source region. To plot the fission rates, use the ``plot_fission_rates(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 16 `. + +.. _table_plot_fission_rates: + +====================== =================== ============= ========= ===================================================== +Parameter Type Default Optional Note +====================== =================== ============= ========= ===================================================== +``solver`` ``Solver`` None No The ``Solver`` used to converge the source +``norm`` boolean False Yes Whether to normalize fluxes to the mean +``transparent_zeros`` boolean True Yes Whether to make all non-fissionable FSRs transparent +``gridsize`` integer 250 Yes The pixel resolution +``xlim`` 2-tuple None Yes The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None Yes The min/max :math:`y`-coordinates to plot +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +``library`` string 'matplotlib' Yes The plotting library to use ('matplotlib' or 'pil') +====================== =================== ============= ========= ===================================================== + +**Table 16**: Parameters for the ``openmoc.plotter.plot_fission_rates(...)`` routine. + +The code snippet below illustrates one possible configuration of parameters to the routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + # Setup solver and converge the source + ... + + # Plot the fission rates in each FSR in a 500 x 500 pixel image + openmoc.plotter.plot_fission_rates(solver, gridsize=500) + +A depiction of the energy-integrated FSR fission rates for the C5G7 benchmark (:file:`/OpenMOC/sample-input/benchmarks/c5g7`) is illustrated in :ref:`Figure 9 `. + +.. _figure_fission_rates: + +.. figure:: ../../img/fission-rates.png + :align: center + :figclass: align-center + :width: 400px + +**Figure 9**: The energy-integrated FSR fission rates in the C5G7 benchmark problem. + + +.. note:: The runtime required by the plotting routine scales with the number of pixels in the image (the square of the ``gridsize`` parameter). + + +--------------------------------- +Generalized Spatial Visualization +--------------------------------- + +The ``openmoc.plotter`` module includes a generalized method to plot spatially-varying indexed by ``Material``, ``Cell``, or FSR. For general spatial plotting, use the ``plot_spatial_data(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 17 `. + +.. _table_general_plotting: + +====================== ===================================================== ============= ========= ============================================================ +Parameter Type Default Optional Note +====================== ===================================================== ============= ========= ============================================================ +``domains_to_data`` ``dict``, ``numpy.ndarray``, or ``pandas.DataFrame`` None No Spatial domains-to-data mapping +``plot_params`` boolean None No Plotting parametetrs +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +====================== ===================================================== ============= ========= ============================================================ + +**Table 17**: Parameters for the ``openmoc.plotter.plot_spatial_data(...)`` routine. + +:ref:`Table 18 ` below itemizes each of the property attributes of the ``PlotParams`` class which can be used to customize images with generalized spatial plotting. + +.. _table_plot_params: + +======================== ======================== ====================== ========================================================== +Property Type Default Note +======================== ======================== ====================== ========================================================== +``geometry`` ``Geometry`` None The Geometry to query when generating the spatial map +``domain_type`` string 'fsr' The domain type used to map spatial data to the geometry +``filename`` string None The filename string +``extension`` string '.png' The image file extension (e.g., '.png') +``library`` string 'matplotlib' The plotting library to use ('matplotlib' or 'pil') +``zcoord`` float 0 The level along the :math:`z`-axis to plot +``gridsize`` integer 250 The pixel resolution +``xlim`` 2-tuple None The min/max :math:`x`-coordinates to plot +``ylim`` 2-tuple None The min/max :math:`y`-coordinates to plot +``title`` string None The minor title string +``suptitle`` string None The major title string +``norm`` boolean False Normalize the plotted data to unity +``transparent_zeros`` boolean False Make zeros in the data appear transparent +``interpolation`` string None Interpolation used between points (e.g., 'nearest') +``colorbar`` boolean False Include a colorbar to the right of the plot +``cmap`` ``matplotlib.colormap`` ``cmap('spectral')`` A Matplotlib colormap for the plot +``vmin`` float None The minimum value used in colormapping the data +``vmax`` float None The maximum value used in colormapping the data +======================== ======================== ====================== ========================================================== + +**Table 18**: The ``PlotParams`` class property attributes for plot customization. + +The generalied spatial plotter may be applied in a myriad of ways to create spatial plots of the geometry with user-defined data mapped to materials, cells or FSRs. The following code snippet illustrates the generation of three plots for three columns of randomized data mapped by FSR in a Pandas_ ``DataFrame``: + +.. code-block:: python + + import numpy as np + import pandas as pd + + # Initialize a Pandas DataFrame with normally distributed random data + num_fsrs = geometry.getNumFSRs() + df = pd.DataFrame(np.random.randn(num_fsrs,3), columns=list('ABC')) + + # Initialize a PlotParams object + plot_params = openmoc.plotter.PlotParams() + plot_params.geometry = geometry + plot_params.suptitle = 'Pandas DataFrame' + plot_params.filename = 'pandas-df' + plot_params.colorbar = True + + # Enforce consistent color scheme across figures + plot_params.vmin = df.values.min() + plot_params.vmax = df.values.max() + + openmoc.plotter.plot_spatial_data(df, plot_params) + +.. _figure_general_plotting: + +.. table:: + + +-------------------------------------+-------------------------------------+--------------------------------------+ + | .. _figure_spatials_a: | .. _figure_spatial_b: | .. _figure_spatial_c: | + | | | | + | .. image:: ../../img/spatial-a.png | .. image:: ../../img/spatial-b.png | .. image:: ../../img/spatial-c.png | + | :width: 85 % | :width: 85 % | :width: 85 % | + | :align: center | :align: center | :align: center | + +-------------------------------------+-------------------------------------+--------------------------------------+ + +**Figure 10**: The randomized spatial data for each of the three columns in a Pandas DataFrame for the C5G7 benchmark problem. + + +-------------------------------- +Angular Quadrature Visualization +-------------------------------- + +To plot the angular quadrature deployed by a ``Solver`` in an MOC simulation, use the ``plot_quadrature(...)`` routine in the ``openmoc.plotter`` module. The parameters accepted by this routine are described in :ref:`Table 19 `. + +.. _table_plot_quadrature: + +=================== ========================= ========= ========= =============================================== +Parameter Type Default Optional Note +=================== ========================= ========= ========= =============================================== +``solver`` ``Solver`` None No The ``Solver`` with the quadrature of interest +``get_figure`` boolean False Yes Whether to return the Matplotlib ``Figure`` +=================== ========================= ========= ========= =============================================== + +**Table 19**: Parameters for the ``openmoc.plotter.plot_quadrature(...)`` routine. + +The code snippet below illustrates the use of this routine. + +.. code-block:: python + + import openmoc.plotter + + # Setup geometry and generate tracks + ... + + # Setup solver + ... + + openmoc.plotter.plot_quadrature(solver) + +A depiction of the Tabuchi-Yamamoto polar quadrature used by default in OpenMOC is illustrated in :ref:`Figure 11 `. + +.. _figure_quadrature: + +.. figure:: ../../img/polar-quad-ty.png + :align: center + :figclass: align-center + :width: 400px + + **Figure 11**: The Tabuchi-Yamamoto polar quadrature used as the default in OpenMOC. + + +.. _dictionary: http://docs.python.org/2/library/stdtypes.html#mapping-types-dict +.. _pickle: http://docs.python.org/2/library/pickle.html +.. _HDF5: http://www.hdfgroup.org/HDF5/ +.. _segmentation fault: http://en.wikipedia.org/wiki/Segmentation_fault +.. _Pandas: http://pandas.pydata.org/ diff --git a/docs/source/usersguide/running.rst b/docs/source/usersguide/running.rst new file mode 100644 index 000000000..03fbd7fa9 --- /dev/null +++ b/docs/source/usersguide/running.rst @@ -0,0 +1,148 @@ +.. _running: + +=============== +Running OpenMOC +=============== + +Once you have created your OpenMOC Python script, it is relatively straightforward to run the code. Instructions for running directly in the shell, or on clusters using the TORQUE_ and Cobalt_ job schedulers are described in the following sections. + + +---------------------------- +Running OpenMOC in the Shell +---------------------------- + +If you wish to run your code from the shell, simply type the following in the console:: + + python your-script.py ... + + + +------------------------ +Submitting a TORQUE_ Job +------------------------ + +To schedule a job to run your code on a cluster using the TORQUE job scheduler, you will need to write a submission script. This script will need to specify the desired compute resources (number of nodes and processors per node), the maximum walltime, among `other flags`_. An example script requesting a single node with 12 cores for one hour is presented below: + +.. code-block:: guess + + #!/bin/sh + ################################################### + # Specify nodes, processors per node and maximum + # running time + ################################################### + + #PBS -l nodes=1:ppn=12 + #PBS -l walltime=01:00:00 + + ################################################### + # Enter directory and set PATH + ################################################### + + cd $PBS_O_WORKDIR + PATH=$PBS_O_PATH + + ################################################### + # Run OpenMOC + ################################################### + + python your-script.py ... + + +To submit this script (``my-job.pbs``) your job to TORQUE, simply use the following command in the console:: + + qsub my-job.pbs + + +.. _TORQUE: http://www.adaptivecomputing.com/products/open-source/torque/ +.. _Cobalt: https://www.alcf.anl.gov/user-guides/cobalt-job-control +.. _other flags: https://www.osc.edu/supercomputing/batch-processing-at-osc/pbs-directives-summary + + + +------------------------ +Submitting a Cobalt_ Job +------------------------ + +Cobalt is a job scheduler that is used on large scale machines at Argonne National Laboratory Leadership Computing Facility (ALCF_), namely the IBM BlueGene machines, such as Mira_. To schedule a job to run your code on a cluster using Cobalt, you can submit your job using :program:`qsub` with options to specify the desired compute resources (number of nodes and processors per node), the maximum walltime, etc. + +An example command to request a single node for 20 minutes is presented below:: + + qsub -A -n 1 -t 20 --mode=c1 --env PYTHONPATH=: /python your-script.py ... + +NOTE: You must specify the path to the location where OpenMOC was installed in the :envvar:`PYTHONPATH` environment variable. For OpenMOC ditributions built with the :option:`--user` option, this location will be `~/.local/lib/pythonX.X/site-packages/...`. In particular, the :envvar:`PYTHONPATH` given to :program:`qsub` must include the path to all OpenMOC shared libraries (files with a ``.so`` extension) needed for your script (*i.e.*, ``_openmoc.so`` for the ``openmoc`` Python module). + + +.. _ALCF: http://www.alcf.anl.gov/ +.. _Mira: https://www.alcf.anl.gov/mira + + +.. _runtime_options: + +--------------- +Runtime Options +--------------- + +This section provides a brief overview of each of the runtime options that are supported by OpenMOC. The runtime arguments and the method to retrieve them in a Python script are elaborated upon further in :ref:`Simulation Parameters `. Each of these can be passed into your Python script as follows:: + + python your-script.py ... + +.. option:: -h, --help + +Reports all supported OpenMOC runtime options to the screen. + + +.. option:: -a, --num-azim=<4> + +The number of azimuthal angles for ray tracing. The default is 4. + + +.. option:: -s, --track-spacing=<0.1> + +The track spacing (in cm) for ray tracing. The default is 0.1 cm. + +.. option:: -i, --max-iters=<1000> + +The maximum number of source convergence iterations. The MOC solvers will execute as many iterations needed to converge the source, up to this limiting value. The default is 1000. + + +.. option:: -c, --tolerance=<1E-5> + +The tolerance on the convergence. The default is 1E-5. + + +.. option:: -t, --num-omp-threads=<# CPU cores> + +The number of OpenMP threads to use. This option only applies to scripts which use OpenMOC's :cpp:class:`CPUSolver`, or derived classes such as :cpp:class:`VectorizedSolver`. The default is the number of CPU cores available on the machine of interest. + + +.. option:: -b, --num-gpu-threadblocks=<64> + +The number of CUDA threadblocks. This option only applies to scripts which use OpenMOC's :cpp:class:`GPUSolver` class. The default is 64 threadblocks. + + +.. option:: -g, --num-gpu-threads=<64> + +The number of CUDA threads per threadblock. This option only applies to scripts which use OpenMOC's :cpp:class:`GPUSolver` class. This value must be a multiple of the number of threads in a CUDA warp_. At the time of this writing, nearly all NVIDIA GPUs have a warp size of 32, though this may change for future NVIDIA GPUs. If the value set for this option is not a multiple of 32, the CUDA source code will round up to the nearest multiple of 32 threads. The default is 64 threads. + +.. note:: If you are unsure what the warp size is for your GPU, you can use the ``openmoc.cuda`` module to find out. The following Python code will report the warp size for your GPU to the console: + +.. code-block:: python + + import openmoc.cuda as cuda + + if cuda.machine_contains_gpu(): + num_threads = cuda.get_num_threads_per_warp() + print 'This machines GPU contains %d threads per warp' % (num_threads) + + else: + print 'This machine does not contain an NVIDIA CUDA-enabled GPU' + + +------------------------------- +Canceling an OpenMOC Simulation +------------------------------- + +To cancel an OpenMOC job running in your shell, you can use the ``CTRL+C`` keyboard combination. This will kill the Python script as well as the underlying computation running in the C/C++/CUDA shared library. + + +.. _warp: http://www.pgroup.com/lit/articles/insider/v2n1a5.htm diff --git a/docs/source/usersguide/troubleshoot.rst b/docs/source/usersguide/troubleshoot.rst new file mode 100644 index 000000000..169de996d --- /dev/null +++ b/docs/source/usersguide/troubleshoot.rst @@ -0,0 +1,34 @@ +.. _usersguide_troubleshoot: + +=============== +Troubleshooting +=============== + +If you are experiencing problems trying to compile OpenMOC, first check if the +error you are receiving is among the following options. + + +------------------------- +Problems with Compilation +------------------------- + +NameError: ... is not defined +----------------------------- + +In some cases, the symbolic links for the code are not established correctly and users may receive a `NameError`, and example of which is given below:: + + Traceback (most recent call last): + File "simple-lattice.py", line 1, in + from openmoc import * + File "/home/wbinventor/.local/lib/python2.7/site-packages/openmoc/__init__.py", line 15, in + setLogfileName('log/openmoc-' + current_time + '.log'); + NameError: name 'setLogfileName' is not defined + +This error is commonly seen by new users after just installing the code. As noted in the :ref:`Installation and Configuration `, some Python distributions require that OpenMOC be installed twice the first time it is installed. The recommended solution in this case would be to execute the installation command twice in sequence:: + + python setup.py install --user + python setup.py install --user + + + +.. _mailing list: https://groups.google.com/forum/?hl=en#!forum/openmoc-users diff --git a/docs/source/usersguide/ubuntu_prerequisites.rst b/docs/source/usersguide/ubuntu_prerequisites.rst new file mode 100644 index 000000000..2ead09cd7 --- /dev/null +++ b/docs/source/usersguide/ubuntu_prerequisites.rst @@ -0,0 +1,84 @@ +.. _ubuntu_prerequisites: + +================================== +Installing Prerequisites on Ubuntu +================================== + +There are a few prerequisites which must be installed on your machine before you will be able to build and install OpenMOC. All of the prerequisites can easily be installed using a standard package manager, such as apt-get_ for Ubuntu. The following instructions detail which packages are needed, with instructions on how to install them using ``apt-get``. + +The following command will install all required and optional dependencies on Ubuntu 12.04 or later:: + + sudo apt-get install build-essential git swig python-dev python-numpy python-matplotlib python-h5py + + +.. admonition:: Required + + * GNU's C++ compiler_ + + In order to compile OpenMOC, you will need to have a C++ compiler installed on your machine. It is recommended that you build OpenMOC with g++ version 4.4 or later. To install g++ on Debian Linux or a Debian derivative such as Ubuntu, use the following command in the console:: + + sudo apt-get install build-essential + + + * Python_ + + OpenMOC extensively uses Python for rapid data processing and visualization. OpenMOC uses a mixture of fast, compiled C/C++/CUDA code with Python bindingssuch that users are entirely insulated from having to write in C/C++ or CUDA, and can simply write a Python script with calls to OpenMOC. + + Currently, OpenMOC has been tested with Python versions 2.6, 2.7, 3.1 and 3.2. Even if you already have Python installed, it is recommended that you install it again using ``apt-get`` to ensure that it is properly configured with ``g++``. You can easily install version 2.7 in Ubuntu as follows:: + + sudo apt-get install python2.7 + + In addition, you must install the Python development headers:: + + sudo apt-get install python-dev + + + * Git_ + + The OpenMOC development team uses the Git_ version control software for code development and collaboration. To download the code from our GitHub_ repository, you must first install git. You can do so on Ubuntu as follows:: + + sudo apt-get install git + + + * SWIG_ + + The Simplified Wrapper Interface Generator (SWIG) is used to wrap the compiled C/C++ and CUDA source code and generate Python bindings. SWIG can be installed on Ubuntu as follows:: + + sudo apt-get install swig + + + * NumPy_ + + NumPy is a commonly used, general purpose numerical array creation and manipulation package for Python. OpenMOC uses NumPy to seamlessly transfer numerical data between Python and the C/C++ back-end compiled code. To install NumPy on Ubuntu, use the following command:: + + sudo apt-get install python-numpy + +.. admonition:: Optional + + * matplotlib_ + + The matplotlib Python package is a general purpose utility for plotting and visualizations. OpenMOC uses matplotlib in the ``openmoc.plotter`` module to generate plots, such as flux and power distributions. Although matplotlib and the ``openmoc.plotter`` modules are not required for an OpenMOC simulation, visualizations can be a helpful tool in debugging and input model validation. To install matplotlib in Ubuntu, issue the following command:: + + sudo apt-get install python-matplotlib + + + * h5py_ + + The h5py Python package contains tools to create, retrieve, and manipulate data stored using the HDF5_ binary format. OpenMOC leverages the h5py functionality in its ``openmoc.materialize`` module which includes routines to import/export multi-group nuclear cross-section data to/from HDF5. In addition, the ``openmoc.process`` module contains routines to import/export simulation and performance data to/from HDF5 output files. Although h5py and the ``openmoc.materialize`` and ``openmoc.process`` modules are not required to run OpenMOC, they can facilitate fast access and storage of binary data. + + To install h5py on Ubuntu, issue the following command:: + + sudo apt-get install python-h5py + + +.. _GitHub: https://github.com/mit-crpg/OpenMOC +.. _apt-get: http://www.apt-get.org/ +.. _compiler: http://gcc.gnu.org/ +.. _Python: http://www.python.org/ +.. _Git: http://git-scm.com +.. _SWIG: http://www.swig.org/ +.. _NumPy: http://www.numpy.org/ +.. _BlueGene: http://www-03.ibm.com/systems/technicalcomputing/solutions/bluegene/ +.. _matplotlib: http://matplotlib.org/ +.. _h5py: http://www.h5py.org/ +.. _HDF5: http://www.hdfgroup.org/HDF5/ diff --git a/openmoc/__init__.py b/openmoc/__init__.py index 8b8787ddc..70375ffb4 100644 --- a/openmoc/__init__.py +++ b/openmoc/__init__.py @@ -5,20 +5,33 @@ # For Python 2.X.X if (sys.version_info[0] == 2): - from openmoc import * + from openmoc import * + import log + import options + import materialize + import plotter + import process + import krylov # For Python 3.X.X else: - from openmoc.openmoc import * + from openmoc.openmoc import * + import openmoc.log + import openmoc.options + import openmoc.materialize + import openmoc.plotter + import openmoc.process + import openmoc.krylov # Tell Python to recognize CTRL+C and stop the C++ extension module # when this is passed in from the keyboard signal.signal(signal.SIGINT, signal.SIG_DFL) -# Set a log file name using a date and time +# Build a log file name using the date and time +left_pad = lambda x: x.zfill(2) now = datetime.datetime.now() -current_time = str(now.month).zfill(2) + '-' + str(now.day).zfill(2) + '-' + str(now.year) + '--' -current_time = current_time + str(now.hour).zfill(2) + ':' + str(now.minute).zfill(2) -current_time = current_time + ':' + str(now.second).zfill(2) -set_log_filename('log/openmoc-' + current_time + '.log'); - -Timer = Timer() +time = (now.month, now.day, now.year, now.hour, now.minute, now.second) +year_string = '-'.join(map(left_pad, map(str, (now.month, now.day, now.year)))) +today_string = ':'.join(map(left_pad, map(str, (now.hour, now.minute, now.second)))) +time_string = year_string + '--' + today_string +initialize_logger() +set_log_filename('openmoc-' + time_string + '.log'); diff --git a/openmoc/bgq/__init__.py b/openmoc/bgq/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openmoc/bgq/double/__init__.py b/openmoc/bgq/double/__init__.py deleted file mode 100644 index 811d06a05..000000000 --- a/openmoc/bgq/double/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import signal, sys - -import _openmoc_bgq_double - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_bgq_double import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.bgq.double.openmoc_bgq_double import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -set_log_level(str(openmoc.get_log_level())) -set_output_directory(openmoc.get_output_directory()) -set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/bgq/double/openmoc_bgq_double.i b/openmoc/bgq/double/openmoc_bgq_double.i deleted file mode 100644 index 347b23453..000000000 --- a/openmoc/bgq/double/openmoc_bgq_double.i +++ /dev/null @@ -1,266 +0,0 @@ -%module openmoc_bgq_double - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/Solver.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "as universe IDs when constructing Lattice cells\n"); - return NULL; - } - } -} - - -/* Typemap for Lattice::setLatticeCells(int num_x, int num_y, int* universes) - * method - allows users to pass in Python lists of Universe IDs for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, int* universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (int*) malloc(($1 * $2) * sizeof(int)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PySequence_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem(outer_list,j); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $3[i*$1 + j] = (int) PyInt_AS_LONG(o); - } - else { - free($3); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers as" - "Universe IDs when constructing Lattice cells\n"); - return NULL; - } - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef double FP_PRECISION; diff --git a/openmoc/bgq/single/__init__.py b/openmoc/bgq/single/__init__.py deleted file mode 100644 index 96025f90d..000000000 --- a/openmoc/bgq/single/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import signal, sys - -import _openmoc_bgq_single - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_bgq_single import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.bgq.single.openmoc_bgq_single import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -set_log_level(str(openmoc.get_log_level())) -set_output_directory(openmoc.get_output_directory()) -set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/bgq/single/openmoc_bgq_single.i b/openmoc/bgq/single/openmoc_bgq_single.i deleted file mode 100644 index 8d3a15358..000000000 --- a/openmoc/bgq/single/openmoc_bgq_single.i +++ /dev/null @@ -1,214 +0,0 @@ -%module openmoc_bgq_single - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/Solver.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef float FP_PRECISION; diff --git a/openmoc/bgq/single/openmoc_bgq_single.py b/openmoc/bgq/single/openmoc_bgq_single.py deleted file mode 100644 index c51f39019..000000000 --- a/openmoc/bgq/single/openmoc_bgq_single.py +++ /dev/null @@ -1,893 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 2.0.7 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - - - -from sys import version_info -if version_info >= (2,6,0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_openmoc_bgq_single', [dirname(__file__)]) - except ImportError: - import _openmoc_bgq_single - return _openmoc_bgq_single - if fp is not None: - try: - _mod = imp.load_module('_openmoc_bgq_single', fp, pathname, description) - finally: - fp.close() - return _mod - _openmoc_bgq_single = swig_import_helper() - del swig_import_helper -else: - import _openmoc_bgq_single -del version_info -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. -def _swig_setattr_nondynamic(self,class_type,name,value,static=1): - if (name == "thisown"): return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name,None) - if method: return method(self,value) - if (not static): - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - -def _swig_setattr(self,class_type,name,value): - return _swig_setattr_nondynamic(self,class_type,name,value,0) - -def _swig_getattr(self,class_type,name): - if (name == "thisown"): return self.this.own() - method = class_type.__swig_getmethods__.get(name,None) - if method: return method(self) - raise AttributeError(name) - -def _swig_repr(self): - try: strthis = "proxy of " + self.this.__repr__() - except: strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except AttributeError: - class _object : pass - _newclass = 0 - - - -def castCellToCellFill(*args, **kwargs): - return _openmoc_bgq_single.castCellToCellFill(*args, **kwargs) -castCellToCellFill = _openmoc_bgq_single.castCellToCellFill - -def castCellToCellBasic(*args, **kwargs): - return _openmoc_bgq_single.castCellToCellBasic(*args, **kwargs) -castCellToCellBasic = _openmoc_bgq_single.castCellToCellBasic - -def castUniverseToLattice(*args, **kwargs): - return _openmoc_bgq_single.castUniverseToLattice(*args, **kwargs) -castUniverseToLattice = _openmoc_bgq_single.castUniverseToLattice - -def castLatticeToUniverse(*args, **kwargs): - return _openmoc_bgq_single.castLatticeToUniverse(*args, **kwargs) -castLatticeToUniverse = _openmoc_bgq_single.castLatticeToUniverse - -def cell_id(): - return _openmoc_bgq_single.cell_id() -cell_id = _openmoc_bgq_single.cell_id -MATERIAL = _openmoc_bgq_single.MATERIAL -FILL = _openmoc_bgq_single.FILL -class Cell(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Cell, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Cell, name) - def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined - class is abstract") - __repr__ = _swig_repr - __swig_destroy__ = _openmoc_bgq_single.delete_Cell - __del__ = lambda self : None; - def getUid(self): return _openmoc_bgq_single.Cell_getUid(self) - def getId(self): return _openmoc_bgq_single.Cell_getId(self) - def getType(self): return _openmoc_bgq_single.Cell_getType(self) - def getUniverse(self): return _openmoc_bgq_single.Cell_getUniverse(self) - def getNumSurfaces(self): return _openmoc_bgq_single.Cell_getNumSurfaces(self) - def getSurfaces(self): return _openmoc_bgq_single.Cell_getSurfaces(self) - def getNumFSRs(self): return _openmoc_bgq_single.Cell_getNumFSRs(self) - def setUniverse(self, *args, **kwargs): return _openmoc_bgq_single.Cell_setUniverse(self, *args, **kwargs) - def addSurface(self, *args, **kwargs): return _openmoc_bgq_single.Cell_addSurface(self, *args, **kwargs) - def setSurfacePointer(self, *args, **kwargs): return _openmoc_bgq_single.Cell_setSurfacePointer(self, *args, **kwargs) - def cellContainsPoint(self, *args, **kwargs): return _openmoc_bgq_single.Cell_cellContainsPoint(self, *args, **kwargs) - def cellContainsCoords(self, *args, **kwargs): return _openmoc_bgq_single.Cell_cellContainsCoords(self, *args, **kwargs) - def minSurfaceDist(self, *args, **kwargs): return _openmoc_bgq_single.Cell_minSurfaceDist(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Cell_toString(self) - def printString(self): return _openmoc_bgq_single.Cell_printString(self) -Cell_swigregister = _openmoc_bgq_single.Cell_swigregister -Cell_swigregister(Cell) - -class CellBasic(Cell): - __swig_setmethods__ = {} - for _s in [Cell]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, CellBasic, name, value) - __swig_getmethods__ = {} - for _s in [Cell]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, CellBasic, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_CellBasic(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def getMaterial(self): return _openmoc_bgq_single.CellBasic_getMaterial(self) - def getNumRings(self): return _openmoc_bgq_single.CellBasic_getNumRings(self) - def getNumSectors(self): return _openmoc_bgq_single.CellBasic_getNumSectors(self) - def getNumFSRs(self): return _openmoc_bgq_single.CellBasic_getNumFSRs(self) - def setNumRings(self, *args, **kwargs): return _openmoc_bgq_single.CellBasic_setNumRings(self, *args, **kwargs) - def setNumSectors(self, *args, **kwargs): return _openmoc_bgq_single.CellBasic_setNumSectors(self, *args, **kwargs) - def clone(self): return _openmoc_bgq_single.CellBasic_clone(self) - def subdivideCell(self): return _openmoc_bgq_single.CellBasic_subdivideCell(self) - def toString(self): return _openmoc_bgq_single.CellBasic_toString(self) - def printString(self): return _openmoc_bgq_single.CellBasic_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_CellBasic - __del__ = lambda self : None; -CellBasic_swigregister = _openmoc_bgq_single.CellBasic_swigregister -CellBasic_swigregister(CellBasic) - -class CellFill(Cell): - __swig_setmethods__ = {} - for _s in [Cell]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, CellFill, name, value) - __swig_getmethods__ = {} - for _s in [Cell]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, CellFill, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_CellFill(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def getUniverseFillId(self): return _openmoc_bgq_single.CellFill_getUniverseFillId(self) - def getUniverseFill(self): return _openmoc_bgq_single.CellFill_getUniverseFill(self) - def getNumFSRs(self): return _openmoc_bgq_single.CellFill_getNumFSRs(self) - def setUniverseFill(self, *args, **kwargs): return _openmoc_bgq_single.CellFill_setUniverseFill(self, *args, **kwargs) - def setUniverseFillPointer(self, *args, **kwargs): return _openmoc_bgq_single.CellFill_setUniverseFillPointer(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.CellFill_toString(self) - def printString(self): return _openmoc_bgq_single.CellFill_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_CellFill - __del__ = lambda self : None; -CellFill_swigregister = _openmoc_bgq_single.CellFill_swigregister -CellFill_swigregister(CellFill) - -class Geometry(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Geometry, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Geometry, name) - __repr__ = _swig_repr - def __init__(self): - this = _openmoc_bgq_single.new_Geometry() - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Geometry - __del__ = lambda self : None; - def getWidth(self): return _openmoc_bgq_single.Geometry_getWidth(self) - def getHeight(self): return _openmoc_bgq_single.Geometry_getHeight(self) - def getXMin(self): return _openmoc_bgq_single.Geometry_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.Geometry_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.Geometry_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.Geometry_getYMax(self) - def getBCTop(self): return _openmoc_bgq_single.Geometry_getBCTop(self) - def getBCBottom(self): return _openmoc_bgq_single.Geometry_getBCBottom(self) - def getBCLeft(self): return _openmoc_bgq_single.Geometry_getBCLeft(self) - def getBCRight(self): return _openmoc_bgq_single.Geometry_getBCRight(self) - def getNumFSRs(self): return _openmoc_bgq_single.Geometry_getNumFSRs(self) - def getNumEnergyGroups(self): return _openmoc_bgq_single.Geometry_getNumEnergyGroups(self) - def getNumMaterials(self): return _openmoc_bgq_single.Geometry_getNumMaterials(self) - def getFSRtoCellMap(self): return _openmoc_bgq_single.Geometry_getFSRtoCellMap(self) - def getFSRtoMaterialMap(self): return _openmoc_bgq_single.Geometry_getFSRtoMaterialMap(self) - def getMaxSegmentLength(self): return _openmoc_bgq_single.Geometry_getMaxSegmentLength(self) - def getMinSegmentLength(self): return _openmoc_bgq_single.Geometry_getMinSegmentLength(self) - def getMaterials(self): return _openmoc_bgq_single.Geometry_getMaterials(self) - def getMaterial(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_getMaterial(self, *args, **kwargs) - def getSurface(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_getSurface(self, *args, **kwargs) - def getCell(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_getCell(self, *args, **kwargs) - def getUniverse(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_getUniverse(self, *args, **kwargs) - def getLattice(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_getLattice(self, *args, **kwargs) - def addMaterial(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_addMaterial(self, *args, **kwargs) - def addSurface(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_addSurface(self, *args, **kwargs) - def addCell(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_addCell(self, *args, **kwargs) - def addUniverse(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_addUniverse(self, *args, **kwargs) - def addLattice(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_addLattice(self, *args, **kwargs) - def findCellContainingCoords(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_findCellContainingCoords(self, *args, **kwargs) - def findCellContainingFSR(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_findCellContainingFSR(self, *args, **kwargs) - def findCell(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_findCell(self, *args, **kwargs) - def findFSRId(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_findFSRId(self, *args, **kwargs) - def subdivideCells(self): return _openmoc_bgq_single.Geometry_subdivideCells(self) - def initializeFlatSourceRegions(self): return _openmoc_bgq_single.Geometry_initializeFlatSourceRegions(self) - def segmentize(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_segmentize(self, *args, **kwargs) - def computeFissionability(self, univ=None): return _openmoc_bgq_single.Geometry_computeFissionability(self, univ) - def computePinPowers(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_computePinPowers(self, *args, **kwargs) - def computePinPowersInUniverse(self, *args, **kwargs): return _openmoc_bgq_single.Geometry_computePinPowersInUniverse(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Geometry_toString(self) - def printString(self): return _openmoc_bgq_single.Geometry_printString(self) -Geometry_swigregister = _openmoc_bgq_single.Geometry_swigregister -Geometry_swigregister(Geometry) - -UNIV = _openmoc_bgq_single.UNIV -LAT = _openmoc_bgq_single.LAT -class LocalCoords(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, LocalCoords, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, LocalCoords, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_LocalCoords(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_LocalCoords - __del__ = lambda self : None; - def getType(self): return _openmoc_bgq_single.LocalCoords_getType(self) - def getUniverse(self): return _openmoc_bgq_single.LocalCoords_getUniverse(self) - def getCell(self): return _openmoc_bgq_single.LocalCoords_getCell(self) - def getLattice(self): return _openmoc_bgq_single.LocalCoords_getLattice(self) - def getLatticeX(self): return _openmoc_bgq_single.LocalCoords_getLatticeX(self) - def getLatticeY(self): return _openmoc_bgq_single.LocalCoords_getLatticeY(self) - def getX(self): return _openmoc_bgq_single.LocalCoords_getX(self) - def getY(self): return _openmoc_bgq_single.LocalCoords_getY(self) - def getPoint(self): return _openmoc_bgq_single.LocalCoords_getPoint(self) - def getNext(self): return _openmoc_bgq_single.LocalCoords_getNext(self) - def getPrev(self): return _openmoc_bgq_single.LocalCoords_getPrev(self) - def setType(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setType(self, *args, **kwargs) - def setUniverse(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setUniverse(self, *args, **kwargs) - def setCell(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setCell(self, *args, **kwargs) - def setLattice(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setLattice(self, *args, **kwargs) - def setLatticeX(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setLatticeX(self, *args, **kwargs) - def setLatticeY(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setLatticeY(self, *args, **kwargs) - def setX(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setX(self, *args, **kwargs) - def setY(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setY(self, *args, **kwargs) - def setNext(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setNext(self, *args, **kwargs) - def setPrev(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_setPrev(self, *args, **kwargs) - def getLowestLevel(self): return _openmoc_bgq_single.LocalCoords_getLowestLevel(self) - def adjustCoords(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_adjustCoords(self, *args, **kwargs) - def updateMostLocal(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_updateMostLocal(self, *args, **kwargs) - def prune(self): return _openmoc_bgq_single.LocalCoords_prune(self) - def copyCoords(self, *args, **kwargs): return _openmoc_bgq_single.LocalCoords_copyCoords(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.LocalCoords_toString(self) -LocalCoords_swigregister = _openmoc_bgq_single.LocalCoords_swigregister -LocalCoords_swigregister(LocalCoords) - -DEBUG = _openmoc_bgq_single.DEBUG -INFO = _openmoc_bgq_single.INFO -NORMAL = _openmoc_bgq_single.NORMAL -SEPARATOR = _openmoc_bgq_single.SEPARATOR -HEADER = _openmoc_bgq_single.HEADER -TITLE = _openmoc_bgq_single.TITLE -WARNING = _openmoc_bgq_single.WARNING -CRITICAL = _openmoc_bgq_single.CRITICAL -RESULT = _openmoc_bgq_single.RESULT -UNITTEST = _openmoc_bgq_single.UNITTEST -ERROR = _openmoc_bgq_single.ERROR - -def set_err(*args, **kwargs): - return _openmoc_bgq_single.set_err(*args, **kwargs) -set_err = _openmoc_bgq_single.set_err - -def setOutputDirectory(*args, **kwargs): - return _openmoc_bgq_single.setOutputDirectory(*args, **kwargs) -setOutputDirectory = _openmoc_bgq_single.setOutputDirectory - -def getOutputDirectory(): - return _openmoc_bgq_single.getOutputDirectory() -getOutputDirectory = _openmoc_bgq_single.getOutputDirectory - -def setLogfileName(*args, **kwargs): - return _openmoc_bgq_single.setLogfileName(*args, **kwargs) -setLogfileName = _openmoc_bgq_single.setLogfileName - -def getLogfileName(): - return _openmoc_bgq_single.getLogfileName() -getLogfileName = _openmoc_bgq_single.getLogfileName - -def setSeparatorCharacter(*args, **kwargs): - return _openmoc_bgq_single.setSeparatorCharacter(*args, **kwargs) -setSeparatorCharacter = _openmoc_bgq_single.setSeparatorCharacter - -def getSeparatorCharacter(): - return _openmoc_bgq_single.getSeparatorCharacter() -getSeparatorCharacter = _openmoc_bgq_single.getSeparatorCharacter - -def setHeaderCharacter(*args, **kwargs): - return _openmoc_bgq_single.setHeaderCharacter(*args, **kwargs) -setHeaderCharacter = _openmoc_bgq_single.setHeaderCharacter - -def getHeaderCharacter(): - return _openmoc_bgq_single.getHeaderCharacter() -getHeaderCharacter = _openmoc_bgq_single.getHeaderCharacter - -def setTitleCharacter(*args, **kwargs): - return _openmoc_bgq_single.setTitleCharacter(*args, **kwargs) -setTitleCharacter = _openmoc_bgq_single.setTitleCharacter - -def getTitleCharacter(): - return _openmoc_bgq_single.getTitleCharacter() -getTitleCharacter = _openmoc_bgq_single.getTitleCharacter - -def setLineLength(*args, **kwargs): - return _openmoc_bgq_single.setLineLength(*args, **kwargs) -setLineLength = _openmoc_bgq_single.setLineLength - -def setLogLevel(*args, **kwargs): - return _openmoc_bgq_single.setLogLevel(*args, **kwargs) -setLogLevel = _openmoc_bgq_single.setLogLevel - -def getLogLevel(): - return _openmoc_bgq_single.getLogLevel() -getLogLevel = _openmoc_bgq_single.getLogLevel - -def log_printf(*args, **kwargs): - return _openmoc_bgq_single.log_printf(*args, **kwargs) -log_printf = _openmoc_bgq_single.log_printf - -def createMultilineMsg(*args, **kwargs): - return _openmoc_bgq_single.createMultilineMsg(*args, **kwargs) -createMultilineMsg = _openmoc_bgq_single.createMultilineMsg -SIGMA_T_THRESH = _openmoc_bgq_single.SIGMA_T_THRESH - -def material_id(): - return _openmoc_bgq_single.material_id() -material_id = _openmoc_bgq_single.material_id -class Material(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Material, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Material, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Material(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Material - __del__ = lambda self : None; - def getUid(self): return _openmoc_bgq_single.Material_getUid(self) - def getId(self): return _openmoc_bgq_single.Material_getId(self) - def getNumEnergyGroups(self): return _openmoc_bgq_single.Material_getNumEnergyGroups(self) - def getSigmaT(self): return _openmoc_bgq_single.Material_getSigmaT(self) - def getSigmaA(self): return _openmoc_bgq_single.Material_getSigmaA(self) - def getSigmaS(self): return _openmoc_bgq_single.Material_getSigmaS(self) - def getSigmaF(self): return _openmoc_bgq_single.Material_getSigmaF(self) - def getNuSigmaF(self): return _openmoc_bgq_single.Material_getNuSigmaF(self) - def getChi(self): return _openmoc_bgq_single.Material_getChi(self) - def isFissionable(self): return _openmoc_bgq_single.Material_isFissionable(self) - def isDataAligned(self): return _openmoc_bgq_single.Material_isDataAligned(self) - def getNumVectorGroups(self): return _openmoc_bgq_single.Material_getNumVectorGroups(self) - def setNumEnergyGroups(self, *args, **kwargs): return _openmoc_bgq_single.Material_setNumEnergyGroups(self, *args, **kwargs) - def setSigmaT(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaT(self, *args, **kwargs) - def setSigmaA(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaA(self, *args, **kwargs) - def setSigmaS(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaS(self, *args, **kwargs) - def setSigmaF(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaF(self, *args, **kwargs) - def setNuSigmaF(self, *args, **kwargs): return _openmoc_bgq_single.Material_setNuSigmaF(self, *args, **kwargs) - def setChi(self, *args, **kwargs): return _openmoc_bgq_single.Material_setChi(self, *args, **kwargs) - def setSigmaTByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaTByGroup(self, *args, **kwargs) - def setSigmaAByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaAByGroup(self, *args, **kwargs) - def setSigmaFByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaFByGroup(self, *args, **kwargs) - def setNuSigmaFByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setNuSigmaFByGroup(self, *args, **kwargs) - def setSigmaSByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setSigmaSByGroup(self, *args, **kwargs) - def setChiByGroup(self, *args, **kwargs): return _openmoc_bgq_single.Material_setChiByGroup(self, *args, **kwargs) - def checkSigmaT(self): return _openmoc_bgq_single.Material_checkSigmaT(self) - def toString(self): return _openmoc_bgq_single.Material_toString(self) - def printString(self): return _openmoc_bgq_single.Material_printString(self) - def alignData(self): return _openmoc_bgq_single.Material_alignData(self) -Material_swigregister = _openmoc_bgq_single.Material_swigregister -Material_swigregister(Material) - -class Point(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Point, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Point, name) - __repr__ = _swig_repr - def __init__(self): - this = _openmoc_bgq_single.new_Point() - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Point - __del__ = lambda self : None; - def setCoords(self, *args, **kwargs): return _openmoc_bgq_single.Point_setCoords(self, *args, **kwargs) - def getX(self): return _openmoc_bgq_single.Point_getX(self) - def getY(self): return _openmoc_bgq_single.Point_getY(self) - def setX(self, *args, **kwargs): return _openmoc_bgq_single.Point_setX(self, *args, **kwargs) - def setY(self, *args, **kwargs): return _openmoc_bgq_single.Point_setY(self, *args, **kwargs) - def distance(self, *args, **kwargs): return _openmoc_bgq_single.Point_distance(self, *args, **kwargs) - def distanceToPoint(self, *args, **kwargs): return _openmoc_bgq_single.Point_distanceToPoint(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Point_toString(self) -Point_swigregister = _openmoc_bgq_single.Point_swigregister -Point_swigregister(Point) - -LEONARD = _openmoc_bgq_single.LEONARD -TABUCHI = _openmoc_bgq_single.TABUCHI -class Quadrature(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Quadrature, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Quadrature, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Quadrature(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Quadrature - __del__ = lambda self : None; - def getNumPolarAngles(self): return _openmoc_bgq_single.Quadrature_getNumPolarAngles(self) - def getType(self): return _openmoc_bgq_single.Quadrature_getType(self) - def getSinTheta(self, *args, **kwargs): return _openmoc_bgq_single.Quadrature_getSinTheta(self, *args, **kwargs) - def getWeight(self, *args, **kwargs): return _openmoc_bgq_single.Quadrature_getWeight(self, *args, **kwargs) - def getMultiple(self, *args, **kwargs): return _openmoc_bgq_single.Quadrature_getMultiple(self, *args, **kwargs) - def getSinThetas(self): return _openmoc_bgq_single.Quadrature_getSinThetas(self) - def getWeights(self): return _openmoc_bgq_single.Quadrature_getWeights(self) - def getMultiples(self): return _openmoc_bgq_single.Quadrature_getMultiples(self) - def toString(self): return _openmoc_bgq_single.Quadrature_toString(self) -Quadrature_swigregister = _openmoc_bgq_single.Quadrature_swigregister -Quadrature_swigregister(Quadrature) - -FOUR_PI = _openmoc_bgq_single.FOUR_PI -ONE_OVER_FOUR_PI = _openmoc_bgq_single.ONE_OVER_FOUR_PI -class Solver(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Solver, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Solver, name) - def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined - class is abstract") - __repr__ = _swig_repr - __swig_destroy__ = _openmoc_bgq_single.delete_Solver - __del__ = lambda self : None; - def getGeometry(self): return _openmoc_bgq_single.Solver_getGeometry(self) - def getTrackGenerator(self): return _openmoc_bgq_single.Solver_getTrackGenerator(self) - def getNumPolarAngles(self): return _openmoc_bgq_single.Solver_getNumPolarAngles(self) - def getPolarQuadratureType(self): return _openmoc_bgq_single.Solver_getPolarQuadratureType(self) - def getNumIterations(self): return _openmoc_bgq_single.Solver_getNumIterations(self) - def getSourceConvergenceThreshold(self): return _openmoc_bgq_single.Solver_getSourceConvergenceThreshold(self) - def getFSRScalarFlux(self, *args, **kwargs): return _openmoc_bgq_single.Solver_getFSRScalarFlux(self, *args, **kwargs) - def getFSRScalarFluxes(self): return _openmoc_bgq_single.Solver_getFSRScalarFluxes(self) - def setGeometry(self, *args, **kwargs): return _openmoc_bgq_single.Solver_setGeometry(self, *args, **kwargs) - def setTrackGenerator(self, *args, **kwargs): return _openmoc_bgq_single.Solver_setTrackGenerator(self, *args, **kwargs) - def setPolarQuadratureType(self, *args, **kwargs): return _openmoc_bgq_single.Solver_setPolarQuadratureType(self, *args, **kwargs) - def setNumPolarAngles(self, *args, **kwargs): return _openmoc_bgq_single.Solver_setNumPolarAngles(self, *args, **kwargs) - def setSourceConvergenceThreshold(self, *args, **kwargs): return _openmoc_bgq_single.Solver_setSourceConvergenceThreshold(self, *args, **kwargs) - def useExponentialInterpolation(self): return _openmoc_bgq_single.Solver_useExponentialInterpolation(self) - def useExponentialIntrinsic(self): return _openmoc_bgq_single.Solver_useExponentialIntrinsic(self) - def convergeSource(self, *args, **kwargs): return _openmoc_bgq_single.Solver_convergeSource(self, *args, **kwargs) - def computeFSRFissionRates(self, *args, **kwargs): return _openmoc_bgq_single.Solver_computeFSRFissionRates(self, *args, **kwargs) - def printTimerReport(self): return _openmoc_bgq_single.Solver_printTimerReport(self) -Solver_swigregister = _openmoc_bgq_single.Solver_swigregister -Solver_swigregister(Solver) - -class CPUSolver(Solver): - __swig_setmethods__ = {} - for _s in [Solver]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, CPUSolver, name, value) - __swig_getmethods__ = {} - for _s in [Solver]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, CPUSolver, name) - __repr__ = _swig_repr - def __init__(self, geometry=None, track_generator=None): - this = _openmoc_bgq_single.new_CPUSolver(geometry, track_generator) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_CPUSolver - __del__ = lambda self : None; - def getNumThreads(self): return _openmoc_bgq_single.CPUSolver_getNumThreads(self) - def getFSRScalarFlux(self, *args, **kwargs): return _openmoc_bgq_single.CPUSolver_getFSRScalarFlux(self, *args, **kwargs) - def getFSRScalarFluxes(self): return _openmoc_bgq_single.CPUSolver_getFSRScalarFluxes(self) - def setNumThreads(self, *args, **kwargs): return _openmoc_bgq_single.CPUSolver_setNumThreads(self, *args, **kwargs) - def computeFSRFissionRates(self, *args, **kwargs): return _openmoc_bgq_single.CPUSolver_computeFSRFissionRates(self, *args, **kwargs) -CPUSolver_swigregister = _openmoc_bgq_single.CPUSolver_swigregister -CPUSolver_swigregister(CPUSolver) - -class ThreadPrivateSolver(CPUSolver): - __swig_setmethods__ = {} - for _s in [CPUSolver]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, ThreadPrivateSolver, name, value) - __swig_getmethods__ = {} - for _s in [CPUSolver]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, ThreadPrivateSolver, name) - __repr__ = _swig_repr - def __init__(self, geometry=None, track_generator=None): - this = _openmoc_bgq_single.new_ThreadPrivateSolver(geometry, track_generator) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_ThreadPrivateSolver - __del__ = lambda self : None; -ThreadPrivateSolver_swigregister = _openmoc_bgq_single.ThreadPrivateSolver_swigregister -ThreadPrivateSolver_swigregister(ThreadPrivateSolver) - -ON_SURFACE_THRESH = _openmoc_bgq_single.ON_SURFACE_THRESH - -def surf_id(): - return _openmoc_bgq_single.surf_id() -surf_id = _openmoc_bgq_single.surf_id -PLANE = _openmoc_bgq_single.PLANE -CIRCLE = _openmoc_bgq_single.CIRCLE -XPLANE = _openmoc_bgq_single.XPLANE -YPLANE = _openmoc_bgq_single.YPLANE -ZPLANE = _openmoc_bgq_single.ZPLANE -QUADRATIC = _openmoc_bgq_single.QUADRATIC -VACUUM = _openmoc_bgq_single.VACUUM -REFLECTIVE = _openmoc_bgq_single.REFLECTIVE -BOUNDARY_NONE = _openmoc_bgq_single.BOUNDARY_NONE -class Surface(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Surface, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Surface, name) - def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined - class is abstract") - __repr__ = _swig_repr - __swig_destroy__ = _openmoc_bgq_single.delete_Surface - __del__ = lambda self : None; - def getUid(self): return _openmoc_bgq_single.Surface_getUid(self) - def getId(self): return _openmoc_bgq_single.Surface_getId(self) - def getSurfaceType(self): return _openmoc_bgq_single.Surface_getSurfaceType(self) - def getBoundaryType(self): return _openmoc_bgq_single.Surface_getBoundaryType(self) - def getXMin(self): return _openmoc_bgq_single.Surface_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.Surface_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.Surface_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.Surface_getYMax(self) - def setBoundaryType(self, *args, **kwargs): return _openmoc_bgq_single.Surface_setBoundaryType(self, *args, **kwargs) - def evaluate(self, *args, **kwargs): return _openmoc_bgq_single.Surface_evaluate(self, *args, **kwargs) - def intersection(self, *args, **kwargs): return _openmoc_bgq_single.Surface_intersection(self, *args, **kwargs) - def isPointOnSurface(self, *args, **kwargs): return _openmoc_bgq_single.Surface_isPointOnSurface(self, *args, **kwargs) - def isCoordOnSurface(self, *args, **kwargs): return _openmoc_bgq_single.Surface_isCoordOnSurface(self, *args, **kwargs) - def getMinDistance(self, *args, **kwargs): return _openmoc_bgq_single.Surface_getMinDistance(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Surface_toString(self) - def printString(self): return _openmoc_bgq_single.Surface_printString(self) -Surface_swigregister = _openmoc_bgq_single.Surface_swigregister -Surface_swigregister(Surface) - -class Plane(Surface): - __swig_setmethods__ = {} - for _s in [Surface]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, Plane, name, value) - __swig_getmethods__ = {} - for _s in [Surface]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, Plane, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Plane(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def getXMin(self): return _openmoc_bgq_single.Plane_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.Plane_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.Plane_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.Plane_getYMax(self) - def evaluate(self, *args, **kwargs): return _openmoc_bgq_single.Plane_evaluate(self, *args, **kwargs) - def intersection(self, *args, **kwargs): return _openmoc_bgq_single.Plane_intersection(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Plane_toString(self) - def printString(self): return _openmoc_bgq_single.Plane_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_Plane - __del__ = lambda self : None; -Plane_swigregister = _openmoc_bgq_single.Plane_swigregister -Plane_swigregister(Plane) - -class XPlane(Plane): - __swig_setmethods__ = {} - for _s in [Plane]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, XPlane, name, value) - __swig_getmethods__ = {} - for _s in [Plane]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, XPlane, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_XPlane(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def setX(self, *args, **kwargs): return _openmoc_bgq_single.XPlane_setX(self, *args, **kwargs) - def getX(self): return _openmoc_bgq_single.XPlane_getX(self) - def getXMin(self): return _openmoc_bgq_single.XPlane_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.XPlane_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.XPlane_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.XPlane_getYMax(self) - def toString(self): return _openmoc_bgq_single.XPlane_toString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_XPlane - __del__ = lambda self : None; -XPlane_swigregister = _openmoc_bgq_single.XPlane_swigregister -XPlane_swigregister(XPlane) - -class YPlane(Plane): - __swig_setmethods__ = {} - for _s in [Plane]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, YPlane, name, value) - __swig_getmethods__ = {} - for _s in [Plane]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, YPlane, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_YPlane(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def setY(self, *args, **kwargs): return _openmoc_bgq_single.YPlane_setY(self, *args, **kwargs) - def getY(self): return _openmoc_bgq_single.YPlane_getY(self) - def getXMin(self): return _openmoc_bgq_single.YPlane_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.YPlane_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.YPlane_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.YPlane_getYMax(self) - def toString(self): return _openmoc_bgq_single.YPlane_toString(self) - def printString(self): return _openmoc_bgq_single.YPlane_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_YPlane - __del__ = lambda self : None; -YPlane_swigregister = _openmoc_bgq_single.YPlane_swigregister -YPlane_swigregister(YPlane) - -class ZPlane(Plane): - __swig_setmethods__ = {} - for _s in [Plane]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, ZPlane, name, value) - __swig_getmethods__ = {} - for _s in [Plane]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, ZPlane, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_ZPlane(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def setZ(self, *args, **kwargs): return _openmoc_bgq_single.ZPlane_setZ(self, *args, **kwargs) - def getZ(self): return _openmoc_bgq_single.ZPlane_getZ(self) - def getXMin(self): return _openmoc_bgq_single.ZPlane_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.ZPlane_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.ZPlane_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.ZPlane_getYMax(self) - def toString(self): return _openmoc_bgq_single.ZPlane_toString(self) - def printString(self): return _openmoc_bgq_single.ZPlane_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_ZPlane - __del__ = lambda self : None; -ZPlane_swigregister = _openmoc_bgq_single.ZPlane_swigregister -ZPlane_swigregister(ZPlane) - -class Circle(Surface): - __swig_setmethods__ = {} - for _s in [Surface]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, Circle, name, value) - __swig_getmethods__ = {} - for _s in [Surface]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, Circle, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Circle(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - def getX0(self): return _openmoc_bgq_single.Circle_getX0(self) - def getY0(self): return _openmoc_bgq_single.Circle_getY0(self) - def getRadius(self): return _openmoc_bgq_single.Circle_getRadius(self) - def getXMin(self): return _openmoc_bgq_single.Circle_getXMin(self) - def getXMax(self): return _openmoc_bgq_single.Circle_getXMax(self) - def getYMin(self): return _openmoc_bgq_single.Circle_getYMin(self) - def getYMax(self): return _openmoc_bgq_single.Circle_getYMax(self) - def evaluate(self, *args, **kwargs): return _openmoc_bgq_single.Circle_evaluate(self, *args, **kwargs) - def intersection(self, *args, **kwargs): return _openmoc_bgq_single.Circle_intersection(self, *args, **kwargs) - def toString(self): return _openmoc_bgq_single.Circle_toString(self) - def printString(self): return _openmoc_bgq_single.Circle_printString(self) - __swig_destroy__ = _openmoc_bgq_single.delete_Circle - __del__ = lambda self : None; -Circle_swigregister = _openmoc_bgq_single.Circle_swigregister -Circle_swigregister(Circle) - -class Timer(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Timer, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Timer, name) - __repr__ = _swig_repr - def __init__(self): - this = _openmoc_bgq_single.new_Timer() - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Timer - __del__ = lambda self : None; - __swig_getmethods__["Get"] = lambda x: _openmoc_bgq_single.Timer_Get - if _newclass:Get = staticmethod(_openmoc_bgq_single.Timer_Get) - def startTimer(self): return _openmoc_bgq_single.Timer_startTimer(self) - def stopTimer(self): return _openmoc_bgq_single.Timer_stopTimer(self) - def recordSplit(self, *args, **kwargs): return _openmoc_bgq_single.Timer_recordSplit(self, *args, **kwargs) - def getTime(self): return _openmoc_bgq_single.Timer_getTime(self) - def getSplit(self, *args, **kwargs): return _openmoc_bgq_single.Timer_getSplit(self, *args, **kwargs) - def printSplits(self): return _openmoc_bgq_single.Timer_printSplits(self) - def clearSplit(self, *args, **kwargs): return _openmoc_bgq_single.Timer_clearSplit(self, *args, **kwargs) - def clearSplits(self): return _openmoc_bgq_single.Timer_clearSplits(self) -Timer_swigregister = _openmoc_bgq_single.Timer_swigregister -Timer_swigregister(Timer) - -def Timer_Get(): - return _openmoc_bgq_single.Timer_Get() -Timer_Get = _openmoc_bgq_single.Timer_Get - -class segment(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, segment, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, segment, name) - __repr__ = _swig_repr - __swig_setmethods__["_length"] = _openmoc_bgq_single.segment__length_set - __swig_getmethods__["_length"] = _openmoc_bgq_single.segment__length_get - if _newclass:_length = _swig_property(_openmoc_bgq_single.segment__length_get, _openmoc_bgq_single.segment__length_set) - __swig_setmethods__["_material"] = _openmoc_bgq_single.segment__material_set - __swig_getmethods__["_material"] = _openmoc_bgq_single.segment__material_get - if _newclass:_material = _swig_property(_openmoc_bgq_single.segment__material_get, _openmoc_bgq_single.segment__material_set) - __swig_setmethods__["_region_id"] = _openmoc_bgq_single.segment__region_id_set - __swig_getmethods__["_region_id"] = _openmoc_bgq_single.segment__region_id_get - if _newclass:_region_id = _swig_property(_openmoc_bgq_single.segment__region_id_get, _openmoc_bgq_single.segment__region_id_set) - def __init__(self): - this = _openmoc_bgq_single.new_segment() - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_segment - __del__ = lambda self : None; -segment_swigregister = _openmoc_bgq_single.segment_swigregister -segment_swigregister(segment) - -class Track(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Track, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Track, name) - __repr__ = _swig_repr - def __init__(self): - this = _openmoc_bgq_single.new_Track() - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Track - __del__ = lambda self : None; - def setValues(self, *args, **kwargs): return _openmoc_bgq_single.Track_setValues(self, *args, **kwargs) - def setUid(self, *args, **kwargs): return _openmoc_bgq_single.Track_setUid(self, *args, **kwargs) - def setPhi(self, *args, **kwargs): return _openmoc_bgq_single.Track_setPhi(self, *args, **kwargs) - def setAzimAngleIndex(self, *args, **kwargs): return _openmoc_bgq_single.Track_setAzimAngleIndex(self, *args, **kwargs) - def setReflIn(self, *args, **kwargs): return _openmoc_bgq_single.Track_setReflIn(self, *args, **kwargs) - def setReflOut(self, *args, **kwargs): return _openmoc_bgq_single.Track_setReflOut(self, *args, **kwargs) - def setBCIn(self, *args, **kwargs): return _openmoc_bgq_single.Track_setBCIn(self, *args, **kwargs) - def setBCOut(self, *args, **kwargs): return _openmoc_bgq_single.Track_setBCOut(self, *args, **kwargs) - def setTrackIn(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackIn(self, *args, **kwargs) - def setTrackOut(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackOut(self, *args, **kwargs) - def setTrackInI(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackInI(self, *args, **kwargs) - def setTrackInJ(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackInJ(self, *args, **kwargs) - def setTrackOutI(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackOutI(self, *args, **kwargs) - def setTrackOutJ(self, *args, **kwargs): return _openmoc_bgq_single.Track_setTrackOutJ(self, *args, **kwargs) - def getUid(self): return _openmoc_bgq_single.Track_getUid(self) - def getEnd(self): return _openmoc_bgq_single.Track_getEnd(self) - def getStart(self): return _openmoc_bgq_single.Track_getStart(self) - def getPhi(self): return _openmoc_bgq_single.Track_getPhi(self) - def getAzimAngleIndex(self): return _openmoc_bgq_single.Track_getAzimAngleIndex(self) - def getSegment(self, *args, **kwargs): return _openmoc_bgq_single.Track_getSegment(self, *args, **kwargs) - def getSegments(self): return _openmoc_bgq_single.Track_getSegments(self) - def getNumSegments(self): return _openmoc_bgq_single.Track_getNumSegments(self) - def getTrackIn(self): return _openmoc_bgq_single.Track_getTrackIn(self) - def getTrackOut(self): return _openmoc_bgq_single.Track_getTrackOut(self) - def getTrackInI(self): return _openmoc_bgq_single.Track_getTrackInI(self) - def getTrackInJ(self): return _openmoc_bgq_single.Track_getTrackInJ(self) - def getTrackOutI(self): return _openmoc_bgq_single.Track_getTrackOutI(self) - def getTrackOutJ(self): return _openmoc_bgq_single.Track_getTrackOutJ(self) - def isReflIn(self): return _openmoc_bgq_single.Track_isReflIn(self) - def isReflOut(self): return _openmoc_bgq_single.Track_isReflOut(self) - def getBCIn(self): return _openmoc_bgq_single.Track_getBCIn(self) - def getBCOut(self): return _openmoc_bgq_single.Track_getBCOut(self) - def contains(self, *args, **kwargs): return _openmoc_bgq_single.Track_contains(self, *args, **kwargs) - def addSegment(self, *args, **kwargs): return _openmoc_bgq_single.Track_addSegment(self, *args, **kwargs) - def clearSegments(self): return _openmoc_bgq_single.Track_clearSegments(self) - def toString(self): return _openmoc_bgq_single.Track_toString(self) -Track_swigregister = _openmoc_bgq_single.Track_swigregister -Track_swigregister(Track) - -class TrackGenerator(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, TrackGenerator, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, TrackGenerator, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_TrackGenerator(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_TrackGenerator - __del__ = lambda self : None; - def getNumAzim(self): return _openmoc_bgq_single.TrackGenerator_getNumAzim(self) - def getTrackSpacing(self): return _openmoc_bgq_single.TrackGenerator_getTrackSpacing(self) - def getGeometry(self): return _openmoc_bgq_single.TrackGenerator_getGeometry(self) - def getNumTracks(self): return _openmoc_bgq_single.TrackGenerator_getNumTracks(self) - def getNumTracksArray(self): return _openmoc_bgq_single.TrackGenerator_getNumTracksArray(self) - def getNumSegments(self): return _openmoc_bgq_single.TrackGenerator_getNumSegments(self) - def getNumSegmentsArray(self): return _openmoc_bgq_single.TrackGenerator_getNumSegmentsArray(self) - def getTracks(self): return _openmoc_bgq_single.TrackGenerator_getTracks(self) - def getAzimWeights(self): return _openmoc_bgq_single.TrackGenerator_getAzimWeights(self) - def containsTracks(self): return _openmoc_bgq_single.TrackGenerator_containsTracks(self) - def retrieveTrackCoords(self, *args, **kwargs): return _openmoc_bgq_single.TrackGenerator_retrieveTrackCoords(self, *args, **kwargs) - def retrieveSegmentCoords(self, *args, **kwargs): return _openmoc_bgq_single.TrackGenerator_retrieveSegmentCoords(self, *args, **kwargs) - def setNumAzim(self, *args, **kwargs): return _openmoc_bgq_single.TrackGenerator_setNumAzim(self, *args, **kwargs) - def setTrackSpacing(self, *args, **kwargs): return _openmoc_bgq_single.TrackGenerator_setTrackSpacing(self, *args, **kwargs) - def setGeometry(self, *args, **kwargs): return _openmoc_bgq_single.TrackGenerator_setGeometry(self, *args, **kwargs) - def generateTracks(self): return _openmoc_bgq_single.TrackGenerator_generateTracks(self) -TrackGenerator_swigregister = _openmoc_bgq_single.TrackGenerator_swigregister -TrackGenerator_swigregister(TrackGenerator) - -ON_LATTICE_CELL_THRESH = _openmoc_bgq_single.ON_LATTICE_CELL_THRESH -TINY_MOVE = _openmoc_bgq_single.TINY_MOVE -SIMPLE = _openmoc_bgq_single.SIMPLE -LATTICE = _openmoc_bgq_single.LATTICE -class Universe(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr(self, Universe, name, value) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr(self, Universe, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Universe(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Universe - __del__ = lambda self : None; - def addCell(self, *args, **kwargs): return _openmoc_bgq_single.Universe_addCell(self, *args, **kwargs) - def getCell(self, *args, **kwargs): return _openmoc_bgq_single.Universe_getCell(self, *args, **kwargs) - def getCells(self): return _openmoc_bgq_single.Universe_getCells(self) - def getUid(self): return _openmoc_bgq_single.Universe_getUid(self) - def getId(self): return _openmoc_bgq_single.Universe_getId(self) - def getType(self): return _openmoc_bgq_single.Universe_getType(self) - def getNumCells(self): return _openmoc_bgq_single.Universe_getNumCells(self) - def getFSR(self, *args, **kwargs): return _openmoc_bgq_single.Universe_getFSR(self, *args, **kwargs) - def getOrigin(self): return _openmoc_bgq_single.Universe_getOrigin(self) - def getMaterialIds(self): return _openmoc_bgq_single.Universe_getMaterialIds(self) - def getNestedUniverseIds(self): return _openmoc_bgq_single.Universe_getNestedUniverseIds(self) - def getCellIds(self, *args, **kwargs): return _openmoc_bgq_single.Universe_getCellIds(self, *args, **kwargs) - def isFissionable(self): return _openmoc_bgq_single.Universe_isFissionable(self) - def setType(self, *args, **kwargs): return _openmoc_bgq_single.Universe_setType(self, *args, **kwargs) - def setOrigin(self, *args, **kwargs): return _openmoc_bgq_single.Universe_setOrigin(self, *args, **kwargs) - def setFissionability(self, *args, **kwargs): return _openmoc_bgq_single.Universe_setFissionability(self, *args, **kwargs) - def findCell(self, *args, **kwargs): return _openmoc_bgq_single.Universe_findCell(self, *args, **kwargs) - def computeFSRMaps(self): return _openmoc_bgq_single.Universe_computeFSRMaps(self) - def subdivideCells(self): return _openmoc_bgq_single.Universe_subdivideCells(self) - def toString(self): return _openmoc_bgq_single.Universe_toString(self) - def printString(self): return _openmoc_bgq_single.Universe_printString(self) -Universe_swigregister = _openmoc_bgq_single.Universe_swigregister -Universe_swigregister(Universe) - -class Lattice(Universe): - __swig_setmethods__ = {} - for _s in [Universe]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{})) - __setattr__ = lambda self, name, value: _swig_setattr(self, Lattice, name, value) - __swig_getmethods__ = {} - for _s in [Universe]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{})) - __getattr__ = lambda self, name: _swig_getattr(self, Lattice, name) - __repr__ = _swig_repr - def __init__(self, *args, **kwargs): - this = _openmoc_bgq_single.new_Lattice(*args, **kwargs) - try: self.this.append(this) - except: self.this = this - __swig_destroy__ = _openmoc_bgq_single.delete_Lattice - __del__ = lambda self : None; - def getNumX(self): return _openmoc_bgq_single.Lattice_getNumX(self) - def getNumY(self): return _openmoc_bgq_single.Lattice_getNumY(self) - def getOrigin(self): return _openmoc_bgq_single.Lattice_getOrigin(self) - def getUniverses(self): return _openmoc_bgq_single.Lattice_getUniverses(self) - def getUniverse(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_getUniverse(self, *args, **kwargs) - def getWidthX(self): return _openmoc_bgq_single.Lattice_getWidthX(self) - def getWidthY(self): return _openmoc_bgq_single.Lattice_getWidthY(self) - def getFSR(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_getFSR(self, *args, **kwargs) - def getNestedUniverseIds(self): return _openmoc_bgq_single.Lattice_getNestedUniverseIds(self) - def setLatticeCells(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_setLatticeCells(self, *args, **kwargs) - def setUniversePointer(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_setUniversePointer(self, *args, **kwargs) - def withinBounds(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_withinBounds(self, *args, **kwargs) - def findCell(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_findCell(self, *args, **kwargs) - def findNextLatticeCell(self, *args, **kwargs): return _openmoc_bgq_single.Lattice_findNextLatticeCell(self, *args, **kwargs) - def computeFSRMaps(self): return _openmoc_bgq_single.Lattice_computeFSRMaps(self) - def toString(self): return _openmoc_bgq_single.Lattice_toString(self) - def printString(self): return _openmoc_bgq_single.Lattice_printString(self) -Lattice_swigregister = _openmoc_bgq_single.Lattice_swigregister -Lattice_swigregister(Lattice) - -# This file is compatible with both classic and new-style classes. - - diff --git a/openmoc/casting.i b/openmoc/casting.i new file mode 100644 index 000000000..ccfd054ab --- /dev/null +++ b/openmoc/casting.i @@ -0,0 +1,36 @@ +/* C++ casting helper method for openmoc.process computePinPowers + * routine and the OpenCG compatibility module */ + +%module casting + +%inline %{ + + Lattice* castUniverseToLattice(Universe* universe) { + return dynamic_cast(universe); + } + + Universe* castLatticeToUniverse(Lattice* lattice) { + return dynamic_cast(lattice); + } + + Plane* castSurfaceToPlane(Surface* plane) { + return dynamic_cast(plane); + } + + XPlane* castSurfaceToXPlane(Surface* xplane) { + return dynamic_cast(xplane); + } + + YPlane* castSurfaceToYPlane(Surface* yplane) { + return dynamic_cast(yplane); + } + + ZPlane* castSurfaceToZPlane(Surface* zplane) { + return dynamic_cast(zplane); + } + + ZCylinder* castSurfaceToZCylinder(Surface* zcylinder) { + return dynamic_cast(zcylinder); + } + +%} diff --git a/openmoc/checkvalue.py b/openmoc/checkvalue.py new file mode 100644 index 000000000..5f6fef6ee --- /dev/null +++ b/openmoc/checkvalue.py @@ -0,0 +1,256 @@ +import sys +from collections import Iterable +from numbers import Integral, Real + +import numpy as np + +# For Python 2.X.X +if (sys.version_info[0] == 2): + from log import * +# For Python 3.X.X +else: + from openmoc.log import * + + +def _isinstance(value, expected_type): + """A Numpy-aware replacement for isinstance + + This function will be obsolete when Numpy v. >= 1.9 is established. + """ + + # Declare numpy numeric types. + np_ints = (np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64) + np_floats = (np.float_, np.float16, np.float32, np.float64) + + # Include numpy integers, if necessary. + if type(expected_type) is tuple: + if Integral in expected_type: + expected_type = expected_type + np_ints + elif expected_type is Integral: + expected_type = (Integral, ) + np_ints + + # Include numpy floats, if necessary. + if type(expected_type) is tuple: + if Real in expected_type: + expected_type = expected_type + np_floats + elif expected_type is Real: + expected_type = (Real, ) + np_floats + + # Now, make the instance check. + return isinstance(value, expected_type) + +def check_type(name, value, expected_type, expected_iter_type=None): + """Ensure that an object is of an expected type. Optionally, if the object + is iterable, check that each element is of a particular type. + + Parameters + ---------- + name : str + Description of value being checked + value : object + Object to check type of + expected_type : type + type to check object against + expected_iter_type : type or None, optional + Expected type of each element in value, assuming it is iterable. If + None, no check will be performed. + + """ + + if not _isinstance(value, expected_type): + msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format( + name, value, expected_type.__name__) + py_printf('ERROR', msg) + + if expected_iter_type: + for item in value: + if not _isinstance(item, expected_iter_type): + msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ + 'of type "{2}"'.format(name, value, + expected_iter_type.__name__) + py_printf('ERROR', msg) + + +def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1): + """Ensure that an object is an iterable containing an expected type. + + Parameters + ---------- + name : str + Description of value being checked + value : Iterable + Iterable, possibly of other iterables, that should ultimately contain + the expected type + expected_type : type + type that the iterable should contain + min_depth : int + The minimum number of layers of nested iterables there should be before + reaching the ultimately contained items + max_depth : int + The maximum number of layers of nested iterables there should be before + reaching the ultimately contained items + """ + # Initialize the tree at the very first item. + tree = [value] + index = [0] + + # Traverse the tree. + while index[0] != len(tree[0]): + # If we are done with this level of the tree, go to the next branch on + # the level above this one. + if index[-1] == len(tree[-1]): + del index[-1] + del tree[-1] + index[-1] += 1 + continue + + # Get a string representation of the current index in case we raise an + # exception. + form = '[' + '{:d}, '*(len(index)-1) + '{:d}]' + ind_str = form.format(*index) + + # What is the current item we are looking at? + current_item = tree[-1][index[-1]] + + # If this item is of the expected type, then we've reached the bottom + # level of this branch. + if _isinstance(current_item, expected_type): + # Is this deep enough? + if len(tree) < min_depth: + msg = 'Error setting "{0}": The item at {1} does not meet the '\ + 'minimum depth of {2}'.format(name, ind_str, min_depth) + py_printf('ERROR', msg) + + # This item is okay. Move on to the next item. + index[-1] += 1 + + # If this item is not of the expected type, then it's either an error or + # another level of the tree that we need to pursue deeper. + else: + if isinstance(current_item, Iterable): + # The tree goes deeper here, let's explore it. + tree.append(current_item) + index.append(0) + + # But first, have we exceeded the max depth? + if len(tree) > max_depth: + msg = 'Error setting {0}: Found an iterable at {1}, items '\ + 'in that iterable excceed the maximum depth of {2}' \ + .format(name, ind_str, max_depth) + py_printf('ERROR', msg) + + else: + # This item is completely unexpected. + msg = "Error setting {0}: Items must be of type '{1}', but " \ + "item at {2} is of type '{3}'"\ + .format(name, expected_type.__name__, ind_str, + type(current_item).__name__) + py_printf('ERROR', msg) + + +def check_length(name, value, length_min, length_max=None): + """Ensure that a sized object has length within a given range. + + Parameters + ---------- + name : str + Description of value being checked + value : collections.Sized + Object to check length of + length_min : int + Minimum length of object + length_max : int or None, optional + Maximum length of object. If None, it is assumed object must be of + length length_min. + + """ + + if length_max is None: + if len(value) != length_min: + msg = 'Unable to set "{0}" to "{1}" since it must be of ' \ + 'length "{2}"'.format(name, value, length_min) + py_printf('ERROR', msg) + elif not length_min <= len(value) <= length_max: + if length_min == length_max: + msg = 'Unable to set "{0}" to "{1}" since it must be of ' \ + 'length "{2}"'.format(name, value, length_min) + else: + msg = 'Unable to set "{0}" to "{1}" since it must have length ' \ + 'between "{2}" and "{3}"'.format(name, value, length_min, + length_max) + py_printf('ERROR', msg) + + +def check_value(name, value, accepted_values): + """Ensure that an object's value is contained in a set of acceptable values. + + Parameters + ---------- + name : str + Description of value being checked + value : collections.Iterable + Object to check + accepted_values : collections.Container + Container of acceptable values + + """ + + if value not in accepted_values: + msg = 'Unable to set "{0}" to "{1}" since it is not in "{2}"'.format( + name, value, accepted_values) + py_printf('ERROR', msg) + +def check_less_than(name, value, maximum, equality=False): + """Ensure that an object's value is less than a given value. + + Parameters + ---------- + name : str + Description of the value being checked + value : object + Object to check + maximum : object + Maximum value to check against + equality : bool, optional + Whether equality is allowed. Defaluts to False. + + """ + + if equality: + if value > maximum: + msg = 'Unable to set "{0}" to "{1}" since it is greater than ' \ + '"{2}"'.format(name, value, maximum) + py_printf('ERROR', msg) + else: + if value >= maximum: + msg = 'Unable to set "{0}" to "{1}" since it is greater than ' \ + 'or equal to "{2}"'.format(name, value, maximum) + py_printf('ERROR', msg) + +def check_greater_than(name, value, minimum, equality=False): + """Ensure that an object's value is less than a given value. + + Parameters + ---------- + name : str + Description of the value being checked + value : object + Object to check + minimum : object + Minimum value to check against + equality : bool, optional + Whether equality is allowed. Defaluts to False. + + """ + + if equality: + if value < minimum: + msg = 'Unable to set "{0}" to "{1}" since it is less than ' \ + '"{2}"'.format(name, value, minimum) + py_printf('ERROR', msg) + else: + if value <= minimum: + msg = 'Unable to set "{0}" to "{1}" since it is less than ' \ + 'or equal to "{2}"'.format(name, value, minimum) + py_printf('ERROR', msg) diff --git a/openmoc/compatible/__init__.py b/openmoc/compatible/__init__.py deleted file mode 100644 index 8871b6a37..000000000 --- a/openmoc/compatible/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from casmo import * -from opencg_compatible import * \ No newline at end of file diff --git a/openmoc/compatible/casmo.py b/openmoc/compatible/casmo.py deleted file mode 100644 index e18058b71..000000000 --- a/openmoc/compatible/casmo.py +++ /dev/null @@ -1,922 +0,0 @@ -## -# @file casmo.py -# @package openmoc.compatible.casmo -# @brief The parsing module provides utility functions to parse in data -# necessary to construct assembly geometries in OpenMOC -# @author Davis Tran (dvtran@mit.edu) -# @date April 24, 2014 - -import numpy -import h5py -import os -import openmoc.log as log - -## -# @class casmo.py 'openmoc/compatible/casmo.py' -# @brief Contains data parsed from casmo output file -class Casmo(object): - - ## - # @brief Casmo object class constructor - def __init__(self): - self._assembly_name = None - self._filename = None - self._directory = None - self._is_symmetric = True - self._energy_groups = None - self._num_micro_regions = None - self._fuel_pin_rad = None - self._lattice_pitch = None - self._siga = None - self._sigd = None - self._sigt = None - self._sigf = None - self._signf = None - self._sigs = None - self._chi = None - self._width = None - self._min_microregions = None - self._max_microregions = None - self._kinf = None - self._pin_powers = None - self._cell_types = {} - self._cell_type_array = None - self._string_cell_type_array = None - self._average_cross_sections = None - - - ## - # @brief Returns assembly type as string - # @return assembly type (string) - def getAssemblyName(self): - return self._assembly_name - - ## - # @brief Sets assembly type - # @param assembly_name a string that indicates assembly type - def setAssemblyName(self, assembly_name): - self._assembly_name = assembly_name - - ## - # @brief Returns name of casmo output file to be parsed - # @return name of casmo output file to be parsed - def getFilename(self): - return self._filename - - ## - # @brief Sets file name of casmo output file to be parsed - # @param filename the name of the casmo output file to be parsed (string) - def setFilename(self, filename): - self._filename = filename - - ## - # @brief Returns directory of casmo output file being parsed - # @return directory of casmo output file being parsed - def getDirectory(self): - return self._directory - - ## - # @brief Sets directory of casmo output file to be parsed - # @param directory directory of the casmo output file to be parsed (string) - def setDirectory(self, directory): - self._directory = directory - - ## - # @brief Returns whether the assembly for the casmo output file is symmetric - # @return True if symmetric, else False - def isSymmetric(self): - return self._is_symmetric - - ## - # @brief Sets whether the assembly for the casmo output file is symmetric - # @param is_symmetric boolean indicating whether the geometry is symmetric - def setSymmetric(self, is_symmetric): - self._is_symmetric = is_symmetric - - ## - # @brief Checks to see if assembly for casmo output file is symmetric - # @param f casmo output file - def checkSymmetry(self, f): - sym_counter = 0 - for sym_line in f: - if 'LPI' in sym_line: - sym_counter += 1 - continue - if sym_counter ==1: - sym_tokens = sym_line.split() - if len(sym_tokens) > 2: - self._is_symmetric = False - break - else: - self._is_symmetric = True - break - - - ## - # @brief This method parses the casmo output file for the number of - # energy groups - # @return number of energy groups directly from casmo output file - def parseEnergyGroups(self): - f = open(self._directory + self._filename,'r') - for line in f: - if '[Usage Note]' in line: - tokens = line.split() - energy_groups = int(tokens[5]) - break - f.close() - return energy_groups - - ## - # @brief Returns number of energy groups - # @return number of energy groups - def getEnergyGroups(self): - return self._energy_groups - - ## - # @brief Sets number of energy groups - # @param energy_groups number of energy groups (int) - def setEnergyGroups(self, energy_groups): - self._energy_groups = energy_groups - - ## - # @brief parses and sets number of energy groups from casmo output file - def importEnergyGroups(self): - self.setEnergyGroups(self.parseEnergyGroups()) - - ## - # @brief This method parses the casmo output file for the number of - # microregions in the assembly - # @return number of microregions directly from casmo output file - def parseNumRegions(self): - f = open(self._directory + self._filename, 'r') - - #check for symmetry - self.checkSymmetry(f) - - counter = 0 - newcounter = 0 - num_micro_regions = 0 - if self._is_symmetric: - for line in f: - if 'Micro-region number ' in line: - counter += 1 - continue - if counter == 1: - tokens = line.split() - num_micro_regions = int(tokens[1]) - break - else: - for newline in f: - if '--- ---- --------------- ------------ ' in newline: - newcounter += 1 - continue - if newcounter == 1: - newtokens = newline.split() - num_micro_regions = int(newtokens[0]) - break - - - f.close() - return num_micro_regions - - ## - # @brief Returns number of microregions in assembly - # @return number of microregions - def getNumRegions(self): - return self._num_micro_regions - - ## - # @brief Sets the number of microregions - # @param num_micro_regions the number of microregions in the assembly - def setNumRegions(self, num_micro_regions): - self._num_micro_regions = num_micro_regions - - ## - # @brief parses and sets number of microregions from casmo output file - def importNumRegions(self): - self.setNumRegions(self.parseNumRegions()) - - ## - # @brief This method parses the casmo output file for the thermally - # expanded fuel pin radii - # @return fuel pin radii (float) - def parseFuelPinRadii(self): - f = open(self._directory + self._filename, 'r') - for line in f: - if 'Average fuel pellet diam.' in line: - tokens = line.split() - diameter = tokens[5] - break - f.close() - E = diameter.index('E') - radii = (0.5 * float(diameter[0:E]) * 10 ** int(diameter[E+1:])) - return radii - - ## - # @brief Returns fuel pin radii of the assembly - # @return fuel pin radii (float) - def getFuelPinRadii(self): - return self._fuel_pin_rad - - ## - # @brief Sets fuel pin radii of the assembly - # @param fuel_pin_rad fuel pin radii to be set for assembly (float) - def setFuelPinRadii(self, fuel_pin_rad): - self._fuel_pin_rad = fuel_pin_rad - - ## - # @brief parses and sets fuel pin radii of the assembly - def importFuelPinRadii(self): - self.setFuelPinRadii(self.parseFuelPinRadii()) - - ## - # @brief This method parses the casmo output file for the thermally - # expanded lattice pitch - # @return lattice pitch (float) - def parseLatticePitch(self): - f = open(self._directory + self._filename, 'r') - for line in f: - if 'Bundle pitch' in line: - tokens = line.split() - raw_pitch = tokens[3] - break - f.close() - E = raw_pitch.index('E') - pitch = (float(raw_pitch[0:E]) * 10 ** int(raw_pitch[E+1:])) - return pitch - - ## - # @brief Returns lattice pitch of the assembly - # @return lattice pitch (float) - def getLatticePitch(self): - return self._lattice_pitch - - ## - # @brief Sets lattice pitch of the assembly - # @param lattice_pitch lattice pitch to be set for assembly (float) - def setLatticePitch(self, lattice_pitch): - self._lattice_pitch = lattice_pitch - - ## - # @brief parses and sets lattice pitch of the assembly - def importLatticePitch(self): - self.setLatticePitch(self.parseLatticePitch()) - - ## - # @brief This method parses the casmo output file for the materials - # cross sections for every microregion in the assembly - # @param xs_name the name of cross section type (string in all CAPS) - # @return numpy array of cross sections - def parseXS(self, xs_name): - - # Parses for cross sections that are not the scattering matrix - if xs_name != 'SIGS' and xs_name!='CHI': - xs_array = numpy.zeros((self._num_micro_regions, self._energy_groups)) - f = open(self._directory + self._filename, 'r') - counter = 0 - for line in f: - if xs_name in line: - tokens = line.split() - xs_array[counter, :] = [float(xs) for xs in tokens[2:2+self._energy_groups]] - counter += 1 - if counter == self._num_micro_regions: - break - f.close() - - # Parses for scattering matrix cross sections - if xs_name == 'SIGS': - xs_array = numpy.zeros((self._num_micro_regions, self._energy_groups, self._energy_groups)) - f = open(self._directory + self._filename, 'r') - cur_region = 0 - cur_group = 0 - for line in f: - if xs_name in line: - words = line.split() - xs_array[cur_region, cur_group, :] = [float(xs) for xs in words[2:2+self._energy_groups]] - cur_group += 1 - if cur_group == self._energy_groups: - cur_region += 1 - cur_group = 0 - if cur_region == self._num_micro_regions: - break - f.close() - return xs_array - - ## - # @brief Returns a specific cross section numpy array - # @param xs_name the name of a type of cross section (string) - # @return a cross section numpy array - def getXS(self, xs_name): - '''Retrieves cross-section attribute.''' - - if xs_name == 'SIGA': - return self._siga - if xs_name == 'SIGD': - return self._sigd - if xs_name == 'SIGT': - return self._sigt - if xs_name == 'SIGF': - return self._sigf - if xs_name == 'SIGNF': - return self._signf - if xs_name == 'SIGS': - return self._sigs - if xs_name == 'CHI': - return self._chi - - ## - # @brief Sets a specific cross section - # @param xs_name the name of a type of cross section (string) - # @param xs_array a numpy array of cross section values - def setXS(self, xs_name, xs_array): - - if xs_name == 'SIGA': - self._siga = xs_array - if xs_name == 'SIGD': - self._sigd = xs_array - if xs_name == 'SIGT': - self._sigt = xs_array - if xs_name == 'SIGF': - self._sigf = xs_array - if xs_name == 'SIGNF': - self._signf = xs_array - if xs_name == 'SIGS': - self._sigs = xs_array - if xs_name == 'CHI': - self._chi = xs_array - - ## - # @brief parses and sets a specific cross section type from casmo ouput file - # @param xs_name the name of a type of cross section (string) - def importXS(self, xs_name): - self.setXS(xs_name, self.parseXS(xs_name)) - - ## - # @brief calls importXS for all types of cross sections needed by OpenMOC - def importAllXS(self): - xs_list = ['SIGA', 'SIGD', 'SIGT', 'SIGF', 'SIGNF', 'SIGS'] - for xs_name in xs_list: - self.importXS(xs_name) - - ## - # @brief This method parses the casmo output file for the dimensions of - # the assembly. The width equals the number of fuel pins in a row - # or column of an assembly. - # @return width of the assembly - def parseWidth(self): - half_width = -1 - f = open(self._directory + self._filename, 'r') - - #check for symmetry - self.checkSymmetry(f) - - - for line in f: - if 'Layout' in line: - half_width += 1 - continue - if half_width>=0 and line == '\n': - break - if half_width>=0: - half_width += 1 - f.close() - if self._is_symmetric: - return half_width*2-1 - else: - return half_width - - - ## - # @brief Returns width of the assembly - # @return width of the assembly (int) - def getWidth(self): - return self._width - - ## - # @brief Sets width of the assembly - # @param width the width to be set for the assembly - def setWidth(self, width): - self._width = width - - ## - # @brief parses and sets a width of assembly from casmo ouput file - def importWidth(self): - self.setWidth(self.parseWidth()) - - ## - # @brief This method parses the casmo output file for microregion ranges - # and returns a tuple of two numpy arrays, one is the minimum values - # and the other is the maximum values of those microregion ranges, each - # each located within its specific macroregion - # @return numpy array tuple (min microregion values, max microregion values) - def parseMicroregions(self): - - half_width = (self._width+1)/2 - min_array = numpy.zeros((self._width,self._width), dtype=numpy.int32) - max_array = numpy.zeros((self._width,self._width), dtype=numpy.int32) - min_quadrant4 = numpy.zeros((half_width,half_width), dtype=numpy.int32) - max_quadrant4 = numpy.zeros((half_width,half_width), dtype=numpy.int32) - min_values = [] - max_values = [] - - - - - f = open(self._directory + self._filename, 'r') - counter = 0 - - #check for symmetry - self.checkSymmetry(f) - - if self._is_symmetric: - for line in f: - if counter >= 1 and '1_________' in line: - break - if 'Micro-region' in line: - counter += 1 - continue - if counter >= 1: - tokens = line.split() - for index, token in enumerate(tokens): - token = token.strip('*') - token = token.strip('-') - if index%2 ==0: - min_quadrant4[counter-1, index/2] = float(token) - min_quadrant4[index/2, counter-1] = float(token) - else: - max_quadrant4[counter-1, (index-1)/2] = float(token) - max_quadrant4[(index-1)/2, counter-1] = float(token) - counter += 1 - f.close() - - min_array[(half_width-1):,(half_width-1):] = min_quadrant4 - min_array[(half_width-1):, 0:(half_width)] = numpy.fliplr(min_quadrant4) - min_array[0:(half_width), (half_width-1):] = numpy.flipud(min_quadrant4) - min_array[0:(half_width), 0:(half_width)] = numpy.flipud(numpy.fliplr(min_quadrant4)) - - max_array[(half_width-1):,(half_width-1):] = max_quadrant4 - max_array[(half_width-1):, 0:(half_width)] = numpy.fliplr(max_quadrant4) - max_array[0:(half_width), (half_width-1):] = numpy.flipud(max_quadrant4) - max_array[0:(half_width), 0:(half_width)] = numpy.flipud(numpy.fliplr(max_quadrant4)) - else: - counter = 0 - for line in f: - if 'Micro :' in line: - newline = line.lstrip('Micro :') - xline = newline.translate(None, '-') - tokens = xline.split() - for index, token in enumerate(tokens): - if index%2 ==0: - min_values.append(token) - else: - max_values.append(token) - for index, value in enumerate(min_values): - min_array[int(counter)/int(self._width), index%self._width] = float(value) - counter += 1 - continue - - counter = 0 - for index, value in enumerate(max_values): - max_array[int(counter)/int(self._width), index%self._width] = float(value) - counter += 1 - continue - f.close() - return min_array, max_array - - ## - # @brief Returns numpy array of minimum values of microregion range within - # each macroregion - # @return numpy array of minimum values of microregion ranges - def getMinMicroregions(self): - return self._min_microregions - - ## - # @brief Sets minimum values of microregion ranges within each macroregion - # @param min_array numpy array of minimum values of microregion ranges - def setMinMicroregions(self, min_array): - self._min_microregions = min_array - - ## - # @brief Returns numpy array of maximum values of microregion ranges within - # each macroregion - # @return numpy array of maximum values of microregion ranges - def getMaxMicroregions(self): - return self._max_microregions - - ## - # @brief Sets minimum values of microregion ranges within each macroregion - # @param max_array numpy array of minimum values of microregion ranges - def setMaxMicroregions(self, max_array): - self._max_microregions = max_array - - ## - # @brief parses and sets microregion value numpy arrays - def importMicroregions(self): - self.setMinMicroregions(self.parseMicroregions()[0]) - self.setMaxMicroregions(self.parseMicroregions()[1]) - - ## - # @brief This method parses the casmo output file for reference eigenvalue - # @return reference eigenvalue of assembly (float) - def parseKinf(self): - f = open(self._directory + self._filename, 'r') - - for line in f: - if 'k-infinity' in line: - tokens = line.split() - kinf = float(tokens[2]) - break - f.close() - return kinf - - ## - # @brief Returns reference eigenvalue of assembly from casmo output file - # @return reference eigenvalue of assembly (float) - def getKinf(self): - return self._kinf - - ## - # @brief Sets reference eigenvalue of assembly - # @param kinf the reference eigenvalue to be set for the assembly - def setKinf(self, kinf): - self._kinf = kinf - - ## - # @brief parses and sets eigenvalue of assembly - def importKinf(self): - self.setKinf(self.parseKinf()) - - ## - # @brief This method parses the casmo output file for reference pin powers - # @return numpy array of float-valued reference pin powers of assembly - def parsePinPowers(self): - - f = open(self._directory + self._filename, 'r') - - half_width = (self._width+1)/2 - pin_power_array = numpy.zeros((self._width,self._width), dtype=numpy.float32) - quadrant4 = numpy.zeros((half_width,half_width), dtype=numpy.float32) - - counter = 0 - - #check for symmetry - self.checkSymmetry(f) - - for line in f: - - if counter >= 1 and line == '\n': - break - - if 'Power Distribution' in line: - counter += 1 - continue - - if self._is_symmetric: - if counter >= 1: - powers = line.split() - for index, power in enumerate(powers): - power = power.strip('*') - quadrant4[counter-1, index] = float(power) - quadrant4[index, counter-1] = float(power) - counter += 1 - # Arranges section of pin powers into larger array by symmetry - pin_power_array[(half_width-1):,(half_width-1):] = quadrant4 - pin_power_array[(half_width-1):, 0:(half_width)] = numpy.fliplr(quadrant4) - pin_power_array[0:(half_width), (half_width-1):] = numpy.flipud(quadrant4) - pin_power_array[0:(half_width), 0:(half_width)] = numpy.flipud(numpy.fliplr(quadrant4)) - - else: - if counter >= 1: - powers = line.split() - - for index, power in enumerate(powers): - power = power.strip('*') - pin_power_array[counter-1, index] = float(power) - counter+=1 - - f.close() - return pin_power_array - - ## - # @brief Returns reference pin powers of assembly from casmo output file - # @return numpy array of float valued reference pin powers of assembly - def getPinPowers(self): - return self._pin_powers - - ## - # @brief Sets reference pin powers of assembly - # @param pin_power_array numpy array of float-valued reference pin powers - def setPinPowers(self, pin_power_array): - self._pin_powers = pin_power_array - - ## - # @brief parses and sets pin powers of assembly - def importPinPowers(self): - self.setPinPowers(self.parsePinPowers()) - - ## - # @brief Returns dictionary of cell type associated with each id number - # @return dictionary cell types by id number, int-->string - def getCellTypes(self): - return self._cell_types - - ## - # @brief Sets a cell type and cell type id key-value pair - # @param cell_types_id id number for a certain cell type (int) - # @param name name of a specific cell type associated an id number (string) - def setCellType(self, cell_types_id, name): - self._cell_types[cell_types_id] = name - - ## - # @brief This method parses the casmo output file for the type of material in - # each cell - # @return numpy array of int-valued cell types - def parseCellTypeArray(self): - - half_width = (self._width+1)/2 - full_width = self._width - cell_type_array = numpy.zeros((full_width,full_width), dtype=numpy.int32) - quadrant4 = numpy.zeros((half_width,half_width), dtype=numpy.int32) - - counter = 0 - f = open(self._directory + self._filename, 'r') - - #check for symmetry - self.checkSymmetry(f) - - for line in f: - if counter >=1 and line == '\n': - break - if 'Layout' in line: - counter += 1 - continue - if counter >= 1: - cell_types = line.split() - for index, cell_type in enumerate(cell_types): - cell_type = cell_type.strip('*') - if self._is_symmetric: - quadrant4[counter-1, index] = int(cell_type) - else: - cell_type_array[counter-1, index] = int(cell_type) - counter += 1 - f.close() - if self._is_symmetric: - # Arranges section of cell types into larger array by symmetry - cell_type_array[(half_width-1):,(half_width-1):] = quadrant4 - cell_type_array[(half_width-1):, 0:(half_width)] = numpy.fliplr(quadrant4) - cell_type_array[0:(half_width), (half_width-1):] = numpy.flipud(quadrant4) - cell_type_array[0:(half_width), 0:(half_width)] = numpy.flipud(numpy.fliplr(quadrant4)) - - cell_type_array[half_width-1,half_width-1] = 2 - return cell_type_array - - ## - # @brief Returns array of cell type ids for assembly - # @return array of cell types for every cell in assembly - def getCellTypeArray(self): - return self._cell_type_array - - ## - # @brief Sets array of cell type ids for assembly - # @param cell_type_array numpy array of int-valued cell type ids - def setCellTypeArray(self, cell_type_array): - self._cell_type_array = cell_type_array - - ## - # @brief parses and sets cell type ids for assembly - def importCellTypeArray(self): - self.setCellTypeArray(self.parseCellTypeArray()) - - ## - # @brief This method converts the numerical cell type array to strings that - # indicate the cell type in clearer language - # @return numpy array of cell types as strings - def stringCellTypeArray(self): - - #id of 1 corresponds to fuel (string of fuel) - #id of 2 corresponds to guide tube (string of gt) - #id of 3 corresponds to burnable poison (string of bp) - string_cell_type_array = numpy.zeros((self._width,self._width), dtype=numpy.str) - - - for i, row in enumerate(self._cell_type_array): - for j, cell in enumerate(row): - if self._cell_type_array[i,j] in self._cell_types.keys(): - string_cell_type_array[i,j] = self._cell_types[self._cell_type_array[i,j]] - else: - log.py_printf('WARNING', 'Cell type id %d does not exist. Call' - ' setCellTypes to set cell name for id.', self._cell_type_array[i,j]) - - return string_cell_type_array - - ## - # @brief Returns array of cell types as strings for assembly - # @return array of cell types as strings for assembly - def getStringCellTypeArray(self): - return self._string_cell_type_array - - ## - # @brief Sets array of cell types as strings for assembly - # @param string_cell_type_array array of cell types as strings - def setStringCellTypeArray(self, string_cell_type_array): - self._string_cell_type_array = string_cell_type_array - - ## - # @brief This method calls the Casmo import methods necessary to construct - # the geometry of an assembly in OpenMOC - # @param filename filename of casmo output file to be parsed - # @param directory directory of casmo output file to be parsed - def importFromCasmo(self, filename, directory): - self._filename = filename - self._directory = directory - self.importEnergyGroups() - self.importNumRegions() - self.importAllXS() - self.importWidth() - self.importMicroregions() - self.importKinf() - self.importPinPowers() - self.importCellTypeArray() - self.importFuelPinRadii() - self.importLatticePitch() - - ## - # @brief This method exports all data contained within member variables - # of the Casmo object to an hdf5 data file, data sets expect arrays - # @param filename filename of hdf5 data file - # @param directory directory where hdf5 data file will be stored - def export(self, directory = 'casmo-data/', filename = 'casmo-data.h5'): - if not os.path.exists(directory): - os.makedirs(directory) - f = h5py.File(directory + filename, 'w') - f.attrs['Energy Groups'] = self._energy_groups - f.attrs['Assembly Width'] = self._width - f.attrs['Num Microregions'] = self._num_micro_regions - f.attrs['Fuel Pin Radii'] = self._fuel_pin_rad - f.attrs['Lattice Pitch'] = self._lattice_pitch - big_data = f.create_group('Casmo Data') - big_data.create_dataset('K-Infinity', data=self._kinf) - big_data.create_dataset('Total XS', data=self._sigt) - big_data.create_dataset('Absorption XS', data=self._siga) - big_data.create_dataset('Fission XS', data=self._sigf) - big_data.create_dataset('Nu Fission XS', data=self._signf) - big_data.create_dataset('Scattering XS', data=self._sigs) - big_data.create_dataset('Dif Coefficient', data=self._sigd) - big_data.create_dataset('Chi', data=self._chi) - big_data.create_dataset('Pin Powers', data=self._pin_powers) - big_data.create_dataset('Cell Types', data=self._cell_type_array) - big_data.create_dataset('String Cell Types', data=self._string_cell_type_array) - big_data.create_dataset('Min Microregions', data=self._min_microregions) - big_data.create_dataset('Max Microregions', data=self._max_microregions) - f.close() - - ## - # @brief This method imports data from an hdf5 data file and assigns it - # to the corresponding member variables - # @param filename filename of hdf5 data file - # @param directory directory where hdf5 data file is stored - def importFromHDF5(self, directory = 'casmo-data/', filename = 'casmo-data.h5'): - - f = h5py.File(directory + filename, 'r') - self._directory = directory - self._filename = filename - self._energy_groups = f.attrs['Energy Groups'] - self._kinf = f.attrs['K-Infinity'] - self._width = f.attrs['Assembly Width'] - self._num_micro_regions = f.attrs['Num Microregions'] - self._fuel_pin_rad = f.attrs['Fuel Pin Radii'] - self._lattice_pitch = f.attrs['Lattice Pitch'] - self._sigt = f['Casmo Data']['Total XS'][...] - self._siga = f['Casmo Data']['Absorption XS'][...] - self._sigf = f['Casmo Data']['Fission XS'][...] - self._signf = f['Casmo Data']['Nu Fission XS'][...] - self._sigs = f['Casmo Data']['Scattering XS'][...] - self._sigd = f['Casmo Data']['Dif Coefficient'][...] - self._chi = f['Casmo Data']['Chi'][...] - self._pin_powers = f['Casmo Data']['Pin Powers'][...] - self._cell_type_array = f['Casmo Data']['Cell Types'][...] - self._min_microregions = f['Casmo Data']['Min Microregions'][...] - self._max_microregions = f['Casmo Data']['Max Microregions'][...] - f.close() - - ## - # @brief This method exports only cross sectional arrays contained within - # member variables of the Casmo object to an hdf5 data file - # @param assembly_name name of assembly for materials being exported - # @param directory directory where hdf5 data file will be stored - def exportAllXSToHDF5(self, assembly_name, directory = 'casmo-data'): - if not os.path.exists(directory): - os.makedirs(directory) - f = h5py.File(directory + '/' + assembly_name + '-all-materials.hdf5','w') - f.attrs['Energy Groups'] = self._energy_groups - for region in range(self._num_micro_regions): - material = f.create_group('microregion-' + str((region + 1))) - material.create_dataset('Total XS', data=self._sigt[region, :]) - material.create_dataset('Absorption XS', data=self._siga[region, :]) - material.create_dataset('Fission XS', data=self._sigf[region, :]) - material.create_dataset('Nu Fission XS', data=self._signf[region, :]) - material.create_dataset('Scattering XS', data=numpy.ravel(self._sigs[region, :, :])) - material.create_dataset('Dif Coefficient', data=self._sigd[region, :]) - material.create_dataset('Chi', data=self._chi[region, :]) - f.close() - - - ## - # @brief This method exports average cross sectional arrays contained within - # member variables of the Casmo object to an hdf5 data file - # @param assembly_name name of assembly for materials being exported - # @param directory directory where hdf5 data file will be stored - def exportAvgXSToHDF5(self, assembly_name, directory = 'casmo-data'): - - #check if cross sections have been computed - if len(self._average_cross_sections) == 0: - log.py_printf('WARNING', 'Average Cross Sections do not exist. Call' - ' averageXSGenerator to compute them.') - - else: - - #create/set directory in which to store hdf5 file - if not os.path.exists(directory): - os.makedirs(directory) - f = h5py.File(directory + '/' + assembly_name + '-avg-materials.hdf5','w') - f.attrs['Energy Groups'] = self._energy_groups - - #create an hdf5 dataset to store each average cross section - for material in self._average_cross_sections.keys(): - material_group = f.create_group(material) - for xs_type in self._average_cross_sections[material].keys(): - material_group.create_dataset(xs_type,data=self._average_cross_sections[material][xs_type]) - f.close() - - - ## - # @brief This method determines the average materials based on average cross - # parsed from the output file - def averageXSGenerator(self): - - materials = ['fuel','water','cladding','helium'] - - #check for burnable poisons - if 'b' in self._string_cell_type_array: - materials.extend(['bp','ss304']) - - #create dictionary of variables - variable_dict = {'Absorption XS':self._siga,'Dif Coefficient':self._sigd, - 'Total XS':self._sigt,'Fission XS':self._sigf,'Nu Fission XS':self._signf, - 'Scattering XS':self._sigs,'Chi':self._chi} - - #create dictionary of values - val_dict = {} - - #compute average cross section for each material - for material in materials: - val_dict[material] = {} - for xs_type in variable_dict.keys(): - val_dict[material][xs_type] = [] - - for i in range(len(self._string_cell_type_array)): - for j in range(len(self._string_cell_type_array[i])): - for xs_type in variable_dict.keys(): - - #if pin cell is guide tube - if self._string_cell_type_array[i][j]=='g': - val_dict['water'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]-1]) - val_dict['cladding'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]]) - for k in range(self._min_microregions[i][j]+1,self._max_microregions[i][j]): - val_dict['water'][xs_type].append(variable_dict[xs_type][k]) - - #if pin cell is fuel - elif self._string_cell_type_array[i][j]=='f': - val_dict['fuel'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]-1]) - val_dict['helium'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]]) - val_dict['cladding'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+1]) - for k in range(self._min_microregions[i][j]+2,self._max_microregions[i][j]): - val_dict['water'][xs_type].append(variable_dict[xs_type][k]) - - #if pin cell is burnable poison - elif self._string_cell_type_array[i][j]=='b': - val_dict['helium'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]-1]) - val_dict['ss304'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]]) - val_dict['helium'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+1]) - val_dict['bp'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+2]) - val_dict['helium'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+3]) - val_dict['ss304'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+4]) - val_dict['water'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+5]) - val_dict['cladding'][xs_type].append(variable_dict[xs_type][self._min_microregions[i][j]+6]) - for k in range(self._min_microregions[i][j]+7,self._max_microregions[i][j]): - val_dict['water'][xs_type].append(variable_dict[xs_type][k]) - avg_dict = {} - - #add avg cross sections to dictionary - for material in materials: - avg_dict[material] = {} - for xs_type in variable_dict.keys(): - avg_dict[material][xs_type] = [] - for group in range(self._energy_groups): - numerator = sum([e[group] for e in val_dict[material][xs_type]]) - denominator = float(len(val_dict[material][xs_type])) - if xs_type == 'Scattering XS': - avg_dict[material][xs_type].extend(numerator/denominator) - else: - avg_dict[material][xs_type].append(numerator/denominator) - self._average_cross_sections = avg_dict diff --git a/openmoc/compatible/opencg_compatible.py b/openmoc/compatible/opencg_compatible.py deleted file mode 100644 index fd8cb22ea..000000000 --- a/openmoc/compatible/opencg_compatible.py +++ /dev/null @@ -1,821 +0,0 @@ -#!/usr/bin/env python - -import openmoc -import opencg -import copy -import numpy as np - - -# A dictionary of all OpenMOC Materials created -# Keys - Material IDs -# Values - Materials -OPENMOC_MATERIALS = dict() - -# A dictionary of all OpenCG Materials created -# Keys - Material IDs -# Values - Materials -OPENCG_MATERIALS = dict() - -# A dictionary of all OpenMOC Surfaces created -# Keys - Surface IDs -# Values - Surfaces -OPENMOC_SURFACES = dict() - -# A dictionary of all OpenCG Surfaces created -# Keys - Surface IDs -# Values - Surfaces -OPENCG_SURFACES = dict() - -# A dictionary of all OpenMOC Cells created -# Keys - Cell IDs -# Values - Cells -OPENMOC_CELLS = dict() - -# A dictionary of all OpenCG Cells created -# Keys - Cell IDs -# Values - Cells -OPENCG_CELLS = dict() - -# A dictionary of all OpenMOC Universes created -# Keys - Universes IDs -# Values - Universes -OPENMOC_UNIVERSES = dict() - -# A dictionary of all OpenCG Universes created -# Keys - Universes IDs -# Values - Universes -OPENCG_UNIVERSES = dict() - -# A dictionary of all OpenMOC Lattices created -# Keys - Lattice IDs -# Values - Lattices -OPENMOC_LATTICES = dict() - -# A dictionary of all OpenCG Lattices created -# Keys - Lattice IDs -# Values - Lattices -OPENCG_LATTICES = dict() - - - -def get_opencg_material(openmoc_material): - - if not isinstance(openmoc_material, openmoc.Material): - msg = 'Unable to create an OpenCG Material from {0} ' \ - 'which is not an OpenMOC Material'.format(openmoc_material) - raise ValueError(msg) - - global OPENCG_MATERIALS - material_id = openmoc_material.getId() - - # If this Material was already created, use it - if material_id in OPENCG_MATERIALS: - return OPENCG_MATERIALS[material_id] - - # Create an OpenCG Material to represent this OpenMOC Material - name = openmoc_material.getName() - opencg_material = opencg.Material(material_id=material_id, name=name) - - # Add the OpenMOC Material to the global collection of all OpenMOC Materials - OPENMOC_MATERIALS[material_id] = openmoc_material - - # Add the OpenCG Material to the global collection of all OpenCG Materials - OPENCG_MATERIALS[material_id] = opencg_material - - return opencg_material - - -def get_openmoc_material(opencg_material): - - if not isinstance(opencg_material, opencg.Material): - msg = 'Unable to create an OpenMOC Material from {0} ' \ - 'which is not an OpenCG Material'.format(opencg_material) - raise ValueError(msg) - - global OPENMOC_MATERIALS - material_id = opencg_material._id - - # If this Material was already created, use it - if material_id in OPENMOC_MATERIALS: - return OPENMOC_MATERIALS[material_id] - - # Create an OpenMOC Material to represent this OpenCG Material - name = opencg_material._name - openmoc_material = openmoc.Material(id=material_id, name=name) - - # Add the OpenMOC Material to the global collection of all OpenMOC Materials - OPENMOC_MATERIALS[material_id] = openmoc_material - - # Add the OpenCG Material to the global collection of all OpenCG Materials - OPENCG_MATERIALS[material_id] = opencg_material - - # FIXME - openmoc_material.thisown = 0 - - return openmoc_material - - -def is_opencg_surface_compatible(opencg_surface): - - if not isinstance(opencg_surface, opencg.Surface): - msg = 'Unable to check if OpenCG Surface is compatible' \ - 'since {0} is not a Surface'.format(opencg_surface) - raise ValueError(msg) - - if opencg_surface._type in ['z-squareprism']: - return False - else: - return True - - -def get_opencg_surface(openmoc_surface): - - if not isinstance(openmoc_surface, openmoc.Surface): - msg = 'Unable to create an OpenCG Surface from {0} ' \ - 'which is not an OpenMOC Surface'.format(openmoc_surface) - raise ValueError(msg) - - global OPENCG_SURFACES - surface_id = openmoc_surface.getId() - - # If this Surface was already created, use it - if surface_id in OPENCG_SURFACES: - return OPENCG_SURFACES[surface_id] - - # Create an OpenCG Surface to represent this OpenMOC Surface - name = openmoc_surface.getName() - - # Correct for OpenMOC's syntax for Surfaces dividing Cells - boundary = openmoc_surface.getBoundaryType() - if boundary == openmoc.VACUUM: - boundary = 'vacuum' - elif boundary == openmoc.REFLECTIVE: - boundary = 'reflective' - elif boundary == openmoc.BOUNDARY_NONE: - boundary = 'interface' - - opencg_surface = None - - surface_type = openmoc_surface.getSurfaceType() - - if surface_type == openmoc.PLANE: - openmoc_surface = openmoc.castSurfaceToPlane(openmoc_surface) - A = openmoc_surface.getA() - B = openmoc_surface.getB() - C = openmoc_surface.getC() - opencg_surface = opencg.Plane(surface_id, name, boundary, A, B, 0, C) - - elif surface_type == openmoc.XPLANE: - openmoc_surface = openmoc.castSurfaceToXPlane(openmoc_surface) - x0 = openmoc_surface.getX() - opencg_surface = opencg.XPlane(surface_id, name, boundary, x0) - - elif surface_type == openmoc.YPLANE: - openmoc_surface = openmoc.castSurfaceToYPlane(openmoc_surface) - y0 = openmoc_surface.getY() - opencg_surface = opencg.YPlane(surface_id, name, boundary, y0) - - elif surface_type == openmoc.ZPLANE: - openmoc_surface = openmoc.castSurfaceToZPlane(openmoc_surface) - z0 = openmoc_surface.getZ() - opencg_surface = opencg.ZPlane(surface_id, name, boundary, z0) - - elif surface_type == openmoc.CIRCLE: - openmoc_surface = openmoc.castSurfaceToCircle(openmoc_surface) - x0 = openmoc_surface.getX0() - y0 = openmoc_surface.getY0() - R = openmoc_surface.getRadius() - opencg_surface = opencg.ZCylinder(surface_id, name, boundary, x0, y0, R) - - # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces - OPENMOC_SURFACES[surface_id] = openmoc_surface - - # Add the OpenCG Surface to the global collection of all OpenCG Surfaces - OPENCG_SURFACES[surface_id] = opencg_surface - - return opencg_surface - - -def get_openmoc_surface(opencg_surface): - - if not isinstance(opencg_surface, opencg.Surface): - msg = 'Unable to create an OpenMoC Surface from {0} which ' \ - 'is not an OpenCG Surface'.format(opencg_surface) - raise ValueError(msg) - - global OPENMOC_SURFACES - surface_id = opencg_surface._id - - # If this Surface was already created, use it - if surface_id in OPENMOC_SURFACES: - return OPENMOC_SURFACES[surface_id] - - # Create an OpenMOC Surface to represent this OpenCG Surface - name = opencg_surface._name - - # Correct for OpenMOC's syntax for Surfaces dividing Cells - boundary = opencg_surface._boundary_type - if boundary == 'vacuum': - boundary = openmoc.VACUUM - elif boundary == 'reflective': - boundary = openmoc.REFLECTIVE - elif boundary == 'interface': - boundary = openmoc.BOUNDARY_NONE - - if opencg_surface._type == 'plane': - A = opencg_surface._coeffs['A'] - B = opencg_surface._coeffs['B'] - D = opencg_surface._coeffs['D'] - openmoc_surface = openmoc.Plane(A, B, D, surface_id, name) - - elif opencg_surface._type == 'x-plane': - x0 = opencg_surface._coeffs['x0'] - openmoc_surface = openmoc.XPlane(x0, int(surface_id), name) - - elif opencg_surface._type == 'y-plane': - y0 = opencg_surface._coeffs['y0'] - openmoc_surface = openmoc.YPlane(y0, surface_id, name) - - elif opencg_surface._type == 'z-plane': - z0 = opencg_surface._coeffs['z0'] - openmoc_surface = openmoc.ZPlane(z0, surface_id, name) - - elif opencg_surface._type == 'z-cylinder': - x0 = opencg_surface._coeffs['x0'] - y0 = opencg_surface._coeffs['y0'] - R = opencg_surface._coeffs['R'] - openmoc_surface = openmoc.Circle(x0, y0, R, surface_id, name) - - else: - msg = 'Unable to create an OpenMOC Surface from an OpenCG ' \ - 'Surface of type {0} since it is not a compatible ' \ - 'Surface type in OpenMOC'.format(opencg_surface._type) - raise ValueError(msg) - - # Set the boundary condition for this Surface - openmoc_surface.setBoundaryType(boundary) - - # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces - OPENMOC_SURFACES[surface_id] = openmoc_surface - - # Add the OpenCG Surface to the global collection of all OpenCG Surfaces - OPENCG_SURFACES[surface_id] = opencg_surface - - # FIXME - openmoc_surface.thisown = 0 - - return openmoc_surface - - -def get_compatible_opencg_surfaces(opencg_surface): - - if not isinstance(opencg_surface, opencg.Surface): - msg = 'Unable to create an OpenMOC Surface from {0} which ' \ - 'is not an OpenCG Surface'.format(opencg_surface) - raise ValueError(msg) - - global OPENMOC_SURFACES - surface_id = opencg_surface._id - - # If this Surface was already created, use it - if surface_id in OPENMOC_SURFACES: - return OPENMOC_SURFACES[surface_id] - - # Create an OpenMOC Surface to represent this OpenCG Surface - name = opencg_surface._name - - # Correct for OpenMOC's syntax for Surfaces dividing Cells - boundary = opencg_surface._boundary_type - - if opencg_surface._type == 'z-squareprism': - x0 = opencg_surface._coeffs['x0'] - y0 = opencg_surface._coeffs['y0'] - R = opencg_surface._coeffs['R'] - - # Create a list of the four planes we need - left = opencg.XPlane(x0=x0-R, name=name) - right = opencg.XPlane(x0=x0+R, name=name) - bottom = opencg.YPlane(y0=y0-R, name=name) - top = opencg.YPlane(y0=y0+R, name=name) - - # Set the boundary conditions for each Surface - left.setBoundaryType(boundary) - right.setBoundaryType(boundary) - bottom.setBoundaryType(boundary) - top.setBoundaryType(boundary) - - surfaces = [left, right, bottom, top] - - elif opencg_surface._type in ['x-cylinder', 'y-cylinder', - 'x-squareprism', 'y-squareprism']: - msg = 'Unable to create a compatible OpenMOC Surface from an OpenCG ' \ - 'Surface of type {0} since it is not compatible with OpenMOCs 2D ' \ - 'geometry formulation on the xy-plane'.format(opencg_surface._type) - raise ValueError(msg) - - else: - msg = 'Unable to create a compatible OpenMOC Surface from an OpenCG ' \ - 'Surface of type {0} since it already a compatible ' \ - 'Surface type in OpenMOC'.format(opencg_surface._type) - raise ValueError(msg) - - # Add the OpenMOC Surface(s) to the global collection of all OpenMOC Surfaces - OPENMOC_SURFACES[surface_id] = surfaces - - # Add the OpenCG Surface to the global collection of all OpenCG Surfaces - OPENCG_SURFACES[surface_id] = opencg_surface - - return surfaces - - -def get_opencg_cell(openmoc_cell): - - if not isinstance(openmoc_cell, openmoc.Cell): - msg = 'Unable to create an OpenCG Cell from {0} which ' \ - 'is not an OpenMOC Cell'.format(openmoc_cell) - raise ValueError(msg) - - global OPENCG_CELLS - cell_id = openmoc_cell.getId() - - # If this Cell was already created, use it - if cell_id in OPENCG_CELLS: - return OPENCG_CELLS[cell_id] - - # Create an OpenCG Cell to represent this OpenMOC Cell - name = openmoc_cell.getName() - opencg_cell = opencg.Cell(cell_id, name) - - if (openmoc_cell.getType() == openmoc.MATERIAL): - fill = openmoc.castCellToCellBasic(openmoc_cell).getMaterial() - opencg_cell.setFill(get_opencg_material(fill)) - elif (openmoc_cell.getType() == openmoc.FILL): - fill = openmoc.castCellToCellFill(openmoc_cell).getFill() - if isinstance(fill, openmoc.Lattice): - opencg_cell.setFill(get_opencg_lattice(fill)) - else: - opencg_cell.setFill(get_opencg_universe(fill)) - - surfaces = openmoc_cell.getSurfaces() - - for surf_id, surface_halfspace in surfaces.items(): - halfspace = surface_halfspace._halfspace - surface = surface_halfspace._surface - opencg_cell.addSurface(get_opencg_surface(surface), halfspace) - - # Add the OpenMOC Cell to the global collection of all OpenMOC Cells - OPENMOC_CELLS[cell_id] = openmoc_cell - - # Add the OpenCG Cell to the global collection of all OpenCG Cells - OPENCG_CELLS[cell_id] = opencg_cell - - return opencg_cell - - -def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace): - - if not isinstance(opencg_cell, opencg.Cell): - msg = 'Unable to create compatible OpenMOC Cell from {0} which ' \ - 'is not an OpenCG Cell'.format(opencg_cell) - raise ValueError(msg) - - elif not isinstance(opencg_surface, opencg.Surface): - msg = 'Unable to create compatible OpenMOC Cell since {0} is ' \ - 'not an OpenCG Surface'.format(opencg_surface) - raise ValueError(msg) - - elif not halfspace in [-1, +1]: - msg = 'Unable to create compatible OpenMOC Cell since {0}' \ - 'is not a +/-1 halfspace'.format(halfspace) - raise ValueError(msg) - - # Initialize an empty list for the new compatible cells - compatible_cells = list() - - # SquarePrism Surfaces - if opencg_surface._type == 'z-squareprism': - - # Get the compatible Surfaces (XPlanes and YPlanes) - compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface) - - opencg_cell.removeSurface(opencg_surface) - - # If Cell is inside SquarePrism, add "inside" of Surface halfspaces - if halfspace == -1: - opencg_cell.addSurface(compatible_surfaces[0], +1) - opencg_cell.addSurface(compatible_surfaces[1], -1) - opencg_cell.addSurface(compatible_surfaces[2], +1) - opencg_cell.addSurface(compatible_surfaces[3], -1) - compatible_cells.append(opencg_cell) - - # If Cell is outside SquarePrism, add "outside" of Surface halfspaces - else: - - # Create 8 Cell clones to represent each of the disjoint planar - # Surface halfspace intersections - num_clones = 8 - - for clone_id in range(num_clones): - - # Create a cloned OpenCG Cell with Surfaces compatible with OpenMOC - clone = opencg_cell.clone() - compatible_cells.append(clone) - - # Top left subcell - add left XPlane, top YPlane - if clone_id == 0: - clone.addSurface(compatible_surfaces[0], -1) - clone.addSurface(compatible_surfaces[3], +1) - - # Top center subcell - add top YPlane, left/right XPlanes - elif clone_id == 1: - clone.addSurface(compatible_surfaces[0], +1) - clone.addSurface(compatible_surfaces[1], -1) - clone.addSurface(compatible_surfaces[3], +1) - - # Top right subcell - add top YPlane, right XPlane - elif clone_id == 2: - clone.addSurface(compatible_surfaces[1], +1) - clone.addSurface(compatible_surfaces[3], +1) - - # Right center subcell - add right XPlane, top/bottom YPlanes - elif clone_id == 3: - clone.addSurface(compatible_surfaces[1], +1) - clone.addSurface(compatible_surfaces[3], -1) - clone.addSurface(compatible_surfaces[2], +1) - - # Bottom right subcell - add right XPlane, bottom YPlane - elif clone_id == 4: - clone.addSurface(compatible_surfaces[1], +1) - clone.addSurface(compatible_surfaces[2], -1) - - # Bottom center subcell - add bottom YPlane, left/right XPlanes - elif clone_id == 5: - clone.addSurface(compatible_surfaces[0], +1) - clone.addSurface(compatible_surfaces[1], -1) - clone.addSurface(compatible_surfaces[2], -1) - - # Bottom left subcell - add bottom YPlane, left XPlane - elif clone_id == 6: - clone.addSurface(compatible_surfaces[0], -1) - clone.addSurface(compatible_surfaces[2], -1) - - # Left center subcell - add left XPlane, top/bottom YPlanes - elif clone_id == 7: - clone.addSurface(compatible_surfaces[0], -1) - clone.addSurface(compatible_surfaces[3], -1) - clone.addSurface(compatible_surfaces[2], +1) - - # Remove redundant Surfaces from the Cells - for cell in compatible_cells: - cell.removeRedundantSurfaces() - - # Return the list of compatible OpenCG Cells - return compatible_cells - - -def make_opencg_cells_compatible(opencg_universe): - - if not isinstance(opencg_universe, opencg.Universe): - msg = 'Unable to make compatible OpenCG Cells for {0} which ' \ - 'is not an OpenCG Universe'.format(opencg_universe) - raise ValueError(msg) - - # Check all OpenCG Cells in this Universe for compatibility with OpenMOC - opencg_cells = opencg_universe._cells - - for cell_id, opencg_cell in opencg_cells.items(): - - # Check each of the OpenCG Surfaces for OpenMOC compatibility - surfaces = opencg_cell._surfaces - - for surface_id in surfaces: - surface = surfaces[surface_id][0] - halfspace = surfaces[surface_id][1] - - # If this Surface is not compatible with OpenMOC, create compatible - # OpenCG cells with a compatible version of this OpenCG Surface - if not is_opencg_surface_compatible(surface): - - # Get the one or more OpenCG Cells that are compatible with OpenMOC - # NOTE: This does not necessarily make the OpenCG fully compatible. - # It only removes the incompatible Surface and replaces it with - # compatible OpenCG Surface(s). The recursive call at the end - # of this block is necessary in the event that there are more - # incompatible Surfaces in this Cell that are not accounted for. - cells = get_compatible_opencg_cells(opencg_cell, surface, halfspace) - - # Remove the non-compatible OpenCG Cell from the Universe - opencg_universe.removeCell(opencg_cell) - - # Add the compatible OpenCG Cells to the Universe - opencg_universe.addCells(cells) - - # Make recursive call to look at the updated state of the - # OpenCG Universe and return - return make_opencg_cells_compatible(opencg_universe) - - # If all OpenCG Cells in the OpenCG Universe are compatible, return - return - - -def get_openmoc_cell(opencg_cell): - - if not isinstance(opencg_cell, opencg.Cell): - msg = 'Unable to create an OpenMOC Cell from {0} which ' \ - 'is not an OpenCG Cell'.format(opencg_cell) - raise ValueError(msg) - - global OPENMOC_CELLS - cell_id = opencg_cell._id - - # If this Cell was already created, use it - if cell_id in OPENMOC_CELLS: - return OPENMOC_CELLS[cell_id] - - # Create an OpenMOC Cell to represent this OpenCG Cell - name = opencg_cell._name - - fill = opencg_cell._fill - if opencg_cell._type == 'universe': - openmoc_cell = openmoc.CellFill(cell_id, name) - openmoc_cell.setFill(get_openmoc_universe(fill)) - elif opencg_cell._type == 'lattice': - openmoc_cell = openmoc.CellFill(cell_id, name) - openmoc_cell.setFill(get_openmoc_lattice(fill)) - else: - openmoc_cell = openmoc.CellBasic(cell_id, name) - openmoc_cell.setMaterial(get_openmoc_material(fill)) - - surfaces = opencg_cell._surfaces - - for surface_id in surfaces: - surface = surfaces[surface_id][0] - halfspace = int(surfaces[surface_id][1]) - openmoc_cell.addSurface(halfspace, get_openmoc_surface(surface)) - - # Add the OpenMOC Cell to the global collection of all OpenMOC Cells - OPENMOC_CELLS[cell_id] = openmoc_cell - - # Add the OpenCG Cell to the global collection of all OpenCG Cells - OPENCG_CELLS[cell_id] = opencg_cell - - # FIXME - openmoc_cell.thisown = 0 - - return openmoc_cell - - -def get_opencg_universe(openmoc_universe): - - if not isinstance(openmoc_universe, openmoc.Universe): - msg = 'Unable to create an OpenCG Universe from {0} which ' \ - 'is not an OpenMOC Universe'.format(openmoc_universe) - raise ValueError(msg) - - global OPENCG_UNIVERSES - universe_id = openmoc_universe.getId() - - # If this Universe was already created, use it - if universe_id in OPENCG_UNIVERSES: - return OPENCG_UNIVERSES[universe_id] - - # Create an OpenCG Universe to represent this OpenMOC Universe - name = openmoc_universe.getName() - opencg_universe = opencg.Universe(universe_id, name) - - # Convert all OpenMOC Cells in this Universe to OpenCG Cells - openmoc_cells = openmoc_universe.getCells() - - for cell_id, openmoc_cell in openmoc_cells.items(): - opencg_cell = get_opencg_cell(openmoc_cell) - opencg_universe.addCell(opencg_cell) - - # Add the OpenMOC Universe to the global collection of all OpenMOC Universes - OPENMOC_UNIVERSES[universe_id] = openmoc_universe - - # Add the OpenCG Universe to the global collection of all OpenCG Universes - OPENCG_UNIVERSES[universe_id] = opencg_universe - - return opencg_universe - - -def get_openmoc_universe(opencg_universe): - - if not isinstance(opencg_universe, opencg.Universe): - msg = 'Unable to create an OpenMOC Universe from {0} which ' \ - 'is not an OpenCG Universe'.format(opencg_universe) - raise ValueError(msg) - - global OPENMOC_UNIVERSES - universe_id = opencg_universe._id - - # If this Universe was already created, use it - if universe_id in OPENMOC_UNIVERSES: - return OPENMOC_UNIVERSES[universe_id] - - # Make all OpenCG Cells and Surfaces in this Universe compatible with OpenMOC - make_opencg_cells_compatible(opencg_universe) - - # Create an OpenMOC Universe to represent this OpenCG Universe - name = opencg_universe._name - openmoc_universe = openmoc.Universe(universe_id, name) - - # Convert all OpenCG Cells in this Universe to OpenMOC Cells - opencg_cells = opencg_universe._cells - - for cell_id, opencg_cell in opencg_cells.items(): - openmoc_cell = get_openmoc_cell(opencg_cell) - openmoc_universe.addCell(openmoc_cell) - - # Add the OpenMOC Universe to the global collection of all OpenMOC Universes - OPENMOC_UNIVERSES[universe_id] = openmoc_universe - - # Add the OpenCG Universe to the global collection of all OpenCG Universes - OPENCG_UNIVERSES[universe_id] = opencg_universe - - # FIXME - openmoc_universe.thisown = 0 - - return openmoc_universe - - -def get_opencg_lattice(openmoc_lattice): - - if not isinstance(openmoc_lattice, openmoc.Lattice): - msg = 'Unable to create an OpenCG Lattice from {0} which ' \ - 'is not an OpenMOC Lattice'.format(openmoc_lattice) - raise ValueError(msg) - - global OPENCG_LATTICES - lattice_id = openmoc_lattice.getId() - - # If this Lattice was already created, use it - if lattice_id in OPENCG_LATTICES: - return OPENCG_LATTICES[lattice_id] - - # Create an OpenCG Lattice to represent this OpenMOC Lattice - name = openmoc_lattice.getName() - offset = openmoc_lattice.getOffset() - dimension = [1, openmoc_lattice.getNumY(), openmoc_lattice.getNumX()] - width = [1, openmoc_lattice.getWidthY(), openmoc_lattice.getWidthX()] - lower_left = [-np.inf, width[1]*dimension[1]/2. + offset.getX(), - width[2]*dimension[2] / 2. + offset.getY()] - - # Initialize an empty array for the OpenCG nested Universes in this Lattice - universe_array = np.ndarray(tuple(np.array(dimension)[::-1]), \ - dtype=opencg.Universe) - - # Create OpenCG Universes for each unique nested Universe in this Lattice - unique_universes = openmoc_lattice.getUniqueUniverses() - - for universe_id, universe in unique_universes.items(): - unique_universes[universe_id] = get_opencg_universe(universe) - - # Build the nested Universe array - for y in range(dimension[1]): - for x in range(dimension[0]): - universe = openmoc_lattice.getUniverse(x, y) - universe_id = universe.getId() - universe_array[0][y][x] = unique_universes[universe_id] - - opencg_lattice = opencg.Lattice(lattice_id, name) - opencg_lattice.setDimension(dimension) - opencg_lattice.setWidth(width) - opencg_lattice.setUniverses(universe_array) - - offset = np.array(lower_left, dtype=np.float64) - \ - ((np.array(width, dtype=np.float64) * \ - np.array(dimension, dtype=np.float64))) / -2.0 - opencg_lattice.setOffset(offset) - - # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices - OPENMOC_LATTICES[lattice_id] = openmoc_lattice - - # Add the OpenCG Lattice to the global collection of all OpenCG Lattices - OPENCG_LATTICES[lattice_id] = opencg_lattice - - return opencg_lattice - - -def get_openmoc_lattice(opencg_lattice): - - if not isinstance(opencg_lattice, opencg.Lattice): - msg = 'Unable to create an OpenMOC Lattice from {0} which ' \ - 'is not an OpenCG Lattice'.format(opencg_lattice) - raise ValueError(msg) - - global OPENMOC_LATTICES - lattice_id = opencg_lattice._id - - # If this Lattice was already created, use it - if lattice_id in OPENMOC_LATTICES: - return OPENMOC_LATTICES[lattice_id] - - name = opencg_lattice._name - dimension = opencg_lattice._dimension - width = opencg_lattice._width - offset = opencg_lattice._offset - universes = opencg_lattice._universes - - # Initialize an empty array for the OpenMOC nested Universes in this Lattice - universe_array = np.ndarray(tuple(np.array(dimension[0:2])), \ - dtype=openmoc.Universe) - - # Create OpenMOC Universes for each unique nested Universe in this Lattice - unique_universes = opencg_lattice.getUniqueUniverses() - - for universe_id, universe in unique_universes.items(): - unique_universes[universe_id] = get_openmoc_universe(universe) - - # Build the nested Universe array - for y in range(dimension[1]): - for x in range(dimension[0]): - universe_id = universes[0][y][x]._id - universe_array[x][y] = unique_universes[universe_id] - - openmoc_lattice = openmoc.Lattice(lattice_id, name) - openmoc_lattice.setWidth(width[0], width[1]) - openmoc_lattice.setUniverses(universe_array.tolist()) - openmoc_lattice.setOffset(offset[0], offset[1]) - - # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices - OPENMOC_LATTICES[lattice_id] = openmoc_lattice - - # Add the OpenCG Lattice to the global collection of all OpenCG Lattices - OPENCG_LATTICES[lattice_id] = opencg_lattice - - # FIXME - openmoc_lattice.thisown = 0 - - return openmoc_lattice - - -def get_opencg_geometry(openmoc_geometry): - - if not isinstance(openmoc_geometry, openmoc.Geometry): - msg = 'Unable to get OpenCG geometry from {0} which is ' \ - 'not an OpenMOC Geometry object'.format(openmoc_geometry) - raise ValueError(msg) - - # Clear dictionaries and auto-generated IDs - OPENMOC_SURFACES.clear() - OPENCG_SURFACES.clear() - OPENMOC_CELLS.clear() - OPENCG_CELLS.clear() - OPENMOC_UNIVERSES.clear() - OPENCG_UNIVERSES.clear() - OPENMOC_LATTICES.clear() - OPENCG_LATTICES.clear() - - openmoc_root_universe = openmoc_geometry.getRootUniverse() - opencg_root_universe = get_opencg_universe(openmoc_root_universe) - - opencg_geometry = opencg.Geometry() - opencg_geometry.setRootUniverse(opencg_root_universe) - opencg_geometry.initializeCellOffsets() - - return opencg_geometry - - -def get_openmoc_geometry(opencg_geometry): - - if not isinstance(opencg_geometry, opencg.Geometry): - msg = 'Unable to get OpenMOC geometry from {0} which is ' \ - 'not an OpenCG Geometry object'.format(opencg_geometry) - raise ValueError(msg) - - # Deep copy the goemetry since it may be modified to make all Surfaces - # compatible with OpenMOC's specifications - opencg_geometry.assignAutoIds() - opencg_geometry = copy.deepcopy(opencg_geometry) - - # Update Cell bounding boxes in Geometry - opencg_geometry.updateBoundingBoxes() - - # Clear dictionaries and auto-generated ID - OPENMOC_SURFACES.clear() - OPENCG_SURFACES.clear() - OPENMOC_CELLS.clear() - OPENCG_CELLS.clear() - OPENMOC_UNIVERSES.clear() - OPENCG_UNIVERSES.clear() - OPENMOC_LATTICES.clear() - OPENCG_LATTICES.clear() - - # Make the entire geometry "compatible" before assigning auto IDs - universes = opencg_geometry.getAllUniverses() - for universe_id, universe in universes.items(): - make_opencg_cells_compatible(universe) - - opencg_geometry.assignAutoIds() - - opencg_root_universe = opencg_geometry._root_universe - openmoc_root_universe = get_openmoc_universe(opencg_root_universe) - - openmoc_geometry = openmoc.Geometry() - openmoc_geometry.setRootUniverse(openmoc_root_universe) - - # FIXME - openmoc_geometry.thisown = 0 - - return openmoc_geometry diff --git a/openmoc/cuda/__init__.py b/openmoc/cuda/__init__.py index 1474f1b07..ae4e8b175 100644 --- a/openmoc/cuda/__init__.py +++ b/openmoc/cuda/__init__.py @@ -1,18 +1,17 @@ -import signal, sys +import signal +import sys # For Python 2.X.X if (sys.version_info[0] == 2): - import openmoc - import _openmoc_cuda - from openmoc_cuda import * + import openmoc + import _openmoc_cuda + from openmoc_cuda import * # For Python 3.X.X else: - import openmoc.openmoc as openmoc - import _openmoc_cuda - from openmoc.cuda.openmoc_cuda import * + import openmoc.openmoc as openmoc + import _openmoc_cuda + from openmoc.cuda.openmoc_cuda import * # Tell Python to recognize CTRL+C and stop the C++ extension module # when this is passed in from the keyboard signal.signal(signal.SIGINT, signal.SIG_DFL) - -Timer = openmoc.Timer diff --git a/openmoc/cuda/double/__init__.py b/openmoc/cuda/double/__init__.py deleted file mode 100644 index 2877bfda4..000000000 --- a/openmoc/cuda/double/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -import signal, sys - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - import _openmoc_cuda - from openmoc_cuda_double import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - import _openmoc_cuda - from openmoc.cuda.openmoc_cuda_double import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -Timer = openmoc.Timer diff --git a/openmoc/cuda/double/openmoc_cuda_double.i b/openmoc/cuda/double/openmoc_cuda_double.i deleted file mode 100644 index 1d4c66ae3..000000000 --- a/openmoc/cuda/double/openmoc_cuda_double.i +++ /dev/null @@ -1,60 +0,0 @@ -%module openmoc_cuda_double - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Solver.h" - #include "../../../src/accel/cuda/GPUSolver.h" - #include "../../../src/accel/cuda/GPUQuery.h" - #include "../../../src/accel/cuda/clone.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -#ifdef NO_NUMPY -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -#endif - - -%include -%include ../../../src/Solver.h -%include ../../../src/accel/cuda/GPUSolver.h -%include ../../../src/accel/cuda/GPUQuery.h -%include ../../../src/accel/cuda/clone.h - -typedef double FP_PRECISION; diff --git a/openmoc/cuda/openmoc_cuda.i b/openmoc/cuda/openmoc_cuda.i index 97e7e08ac..9456a03c2 100644 --- a/openmoc/cuda/openmoc_cuda.i +++ b/openmoc/cuda/openmoc_cuda.i @@ -1,7 +1,16 @@ -%module openmoc_cuda +%define DOCSTRING +"A method of characteristics code for nuclear reactor physics calculations." +%enddef + +%module(docstring=DOCSTRING) openmoc_cuda %{ #define SWIG_FILE_WITH_INIT + + #define PySys_WriteStdout printf + + #include + #include "../../src/constants.h" #include "../../src/Solver.h" #include "../../src/accel/cuda/GPUSolver.h" #include "../../src/accel/cuda/GPUQuery.h" @@ -35,25 +44,15 @@ #ifdef NO_NUMPY #else -%include "../numpy.i" - -%init %{ - import_array(); -%} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - - +%include "../numpy_typemaps.i" #endif - %include +%include +%include ../../src/constants.h %include ../../src/Solver.h %include ../../src/accel/cuda/GPUSolver.h %include ../../src/accel/cuda/GPUQuery.h %include ../../src/accel/cuda/clone.h -typedef float FP_PRECISION; +#define PySys_WriteStdout printf diff --git a/openmoc/cuda/single/__init__.py b/openmoc/cuda/single/__init__.py deleted file mode 100644 index f8ec9dcc0..000000000 --- a/openmoc/cuda/single/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -import signal, sys - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - import _openmoc_cuda - from openmoc_cuda_single import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - import _openmoc_cuda - from openmoc.cuda.openmoc_cuda_single import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -Timer = openmoc.Timer diff --git a/openmoc/cuda/single/openmoc_cuda_single.i b/openmoc/cuda/single/openmoc_cuda_single.i deleted file mode 100644 index 9b429c2ed..000000000 --- a/openmoc/cuda/single/openmoc_cuda_single.i +++ /dev/null @@ -1,59 +0,0 @@ -%module openmoc_cuda_single - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Solver.h" - #include "../../../src/accel/cuda/GPUSolver.h" - #include "../../../src/accel/cuda/GPUQuery.h" - #include "../../../src/accel/cuda/clone.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -#ifdef NO_NUMPY -#else -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -#endif - - -%include -%include ../../../src/Solver.h -%include ../../../src/accel/cuda/GPUSolver.h -%include ../../../src/accel/cuda/GPUQuery.h -%include ../../../src/accel/cuda/clone.h - -typedef float FP_PRECISION; diff --git a/openmoc/docstring.i b/openmoc/docstring.i new file mode 100644 index 000000000..4a4fdfcf5 --- /dev/null +++ b/openmoc/docstring.i @@ -0,0 +1,10532 @@ + +// File: index.xml + +// File: classCell.xml + + +%feature("docstring") Cell " + +Represents a Cell inside of a Universe. + +C++ includes: src/Cell.h +"; + +%feature("docstring") Cell::incrementVolume " +incrementVolume(double volume) + +Increment the volume/area of the Cell by some amount. + +This routine is called by the TrackGenerator during track generation and segmentation. + +Parameters +---------- +* volume : + the amount to increment the current volume by +"; + +%feature("docstring") Cell::getRotationMatrix " +getRotationMatrix() -> double * + +Return pointer to array for the rotation matrix. + +Returns +------- +a pointer to an array of rotation angles +"; + +%feature("docstring") Cell::retrieveTranslation " +retrieveTranslation(double *translations, int num_axes) + +Fills an array with the translations along x, y and z. + +This class method is intended to be called by the OpenMOC Python OpenCG compatiblity +module. Although this method appears to require two arguments, in reality it only requires +one due to SWIG and would be called from within Python as follows: + + +Parameters +---------- +* translation : + an array of translations of length 3 for x, y and z +* num_axes : + the number of axes (this must always be 3) +"; + +%feature("docstring") Cell::getUid " +getUid() const -> int + +Return the Cell's unique ID. + +Returns +------- +the Cell's unique ID +"; + +%feature("docstring") Cell::getMaxY " +getMaxY() -> double + +Return the maximum reachable y-coordinate in the Cell. + +Returns +------- +the maximum y-coordinate +"; + +%feature("docstring") Cell::getMaxX " +getMaxX() -> double + +Return the maximum reachable x-coordinate in the Cell. + +Returns +------- +the maximum x-coordinate +"; + +%feature("docstring") Cell::getName " +getName() const -> char * + +Return the user-defined name of the Cell. + +Returns +------- +the Cell name +"; + +%feature("docstring") Cell::setNumSectors " +setNumSectors(int num_sectors) + +Set the Cell's number of sectors. + +Parameters +---------- +* num_sectors : + the number of sectors in this Cell +"; + +%feature("docstring") Cell::getMinY " +getMinY() -> double + +Return the minimum reachable y-coordinate in the Cell. + +Returns +------- +the minimum y-coordinate +"; + +%feature("docstring") Cell::getMinX " +getMinX() -> double + +Return the minimum reachable x-coordinate in the Cell. + +Returns +------- +the minimum x-coordinate +"; + +%feature("docstring") Cell::getMinZ " +getMinZ() -> double + +Return the minimum reachable z-coordinate in the Cell. + +Returns +------- +the minimum z-coordinate +"; + +%feature("docstring") Cell::getNumSurfaces " +getNumSurfaces() const -> int + +Return the number of Surfaces in the Cell. + +Returns +------- +the number of Surfaces +"; + +%feature("docstring") Cell::setFill " +setFill(Material *fill) +setFill(Universe *fill) + +Overloaded function +------------------- +* setFill(Material *fill) + + Sets the Material filling this Cell. + + Parameters: + * fill : + the Material filling this Cell + +* setFill(Universe *fill) + + Sets the Universe filling this Cell. + + Parameters: + * fill : + the Universe filling this Cell +"; + +%feature("docstring") Cell::Cell " +Cell(int id=0, const char *name=\"\") + +Constructor sets the unique and user-specifed IDs for this Cell. + +Parameters +---------- +* id : + the user-specified optional Cell ID +* name : + the user-specified optional Cell name +"; + +%feature("docstring") Cell::minSurfaceDist " +minSurfaceDist(LocalCoords *coords) -> double + +Computes the minimum distance to a Surface from a point with a given trajectory at a +certain angle stored in a LocalCoords object. + +If the trajectory will not intersect any of the Surfaces in the Cell returns INFINITY. + +Parameters +---------- +* coords : + a pointer to a localcoords +"; + +%feature("docstring") Cell::clone " +clone() -> Cell * + +Create a duplicate of the Cell. + +Returns +------- +a pointer to the clone +"; + +%feature("docstring") Cell::getVolume " +getVolume() -> double + +Return the aggregate volume/area of all instances of this Cell. + +The volume/area of the Cell is computed from track segments which overlap this Cell during +track generation. + +Returns +------- +the volume/area of the Cell +"; + +%feature("docstring") Cell::getMaxZ " +getMaxZ() -> double + +Return the maximum reachable z-coordinate in the Cell. + +Returns +------- +the maximum z-coordinate +"; + +%feature("docstring") Cell::setNumRings " +setNumRings(int num_rings) + +Set the Cell's number of rings. + +Parameters +---------- +* num_rings : + the number of rings in this Cell +"; + +%feature("docstring") Cell::addSurface " +addSurface(int halfspace, Surface *surface) + +Insert a Surface into this Cell's container of bounding Surfaces. + +Parameters +---------- +* halfspace : + the Surface halfspace (+/-1) +* surface : + a pointer to the Surface +"; + +%feature("docstring") Cell::getAllCells " +getAllCells() -> std::map< int, Cell * > + +Returns the std::map of Cell IDs and Cell pointers within any nested Universes filling +this Cell. + +Returns +------- +std::map of Cell IDs and pointers +"; + +%feature("docstring") Cell::getOldestAncestor " +getOldestAncestor() -> Cell * + +Get the oldest ancestor Cell for this Cell. + +This method traverses the linked list of parent Cells to find the one at the root node. +The oldest ancestor Cell is likely the one created by the user at runtime, while +intermediate ancestors were created during radial and angular spatial discretization. + +Returns +------- +this Cell's oldest ancestor Cell +"; + +%feature("docstring") Cell::~Cell " +~Cell() + +Destructor clears vector of Surface pointers bounding the Cell. +"; + +%feature("docstring") Cell::getAllUniverses " +getAllUniverses() -> std::map< int, Universe * > + +Returns the std::map of all nested Universe IDs and Universe pointers filling this Cell. + +Returns +------- +std::map of Universe IDs and pointers +"; + +%feature("docstring") Cell::setTranslation " +setTranslation(double *translation, int num_axes) + +Set the Cell's translation along the x, y and z axes. + +This method is a helper function to allow OpenMOC users to assign the Cell's translations +in Python. A user must initialize a length 3 NumPy array as input to this function. This +function then stores the data values in the NumPy array in the Cell's translation array. +An example of how this function might be called in Python is as follows: + + +Parameters +---------- +* translation : + the array of translations +* num_axes : + the number of axes (this must always be 3) +"; + +%feature("docstring") Cell::retrieveRotation " +retrieveRotation(double *rotations, int num_axes, std::string units=\"degrees\") + +Fills an array with the rotation angles for x, y and z. + +This class method is intended to be called by the OpenMOC Python OpenCG compatiblity +module. Although this method appears to require two arguments, in reality it only requires +one due to SWIG and would be called from within Python as follows: + + +Parameters +---------- +* rotation : + an array of rotation angles of length 3 for x, y and z +* num_axes : + the number of axes (this must always be 3) +* units : + the angular units in \"radians\" or \"degrees\" (default) +"; + +%feature("docstring") Cell::addNeighborCell " +addNeighborCell(Cell *cell) + +Add a neighboring Cell to this Cell's collection of neighbors. + +Parameters +---------- +* cell : + a pointer to the neighboring Cell +"; + +%feature("docstring") Cell::setVolume " +setVolume(double volume) + +Set the volume/area of the Cell. + +Parameters +---------- +* volume : + the volume/area of the Cell +"; + +%feature("docstring") Cell::getType " +getType() const -> cellType + +Return the Cell type (FILL or MATERIAL). + +Returns +------- +the Cell type +"; + +%feature("docstring") Cell::getMinXBoundaryType " +getMinXBoundaryType() -> boundaryType + +Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at the minimum reachable +x-coordinate in the Cell. + +Returns +------- +the boundary condition at the minimum x-coordinate +"; + +%feature("docstring") Cell::getMaxXBoundaryType " +getMaxXBoundaryType() -> boundaryType + +Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at the maximum reachable +x-coordinate in the Cell. + +Returns +------- +the boundary condition at the maximum x-coordinate +"; + +%feature("docstring") Cell::getNumSectors " +getNumSectors() -> int + +Return the number of sectors in the Cell. + +Returns +------- +the number of sectors +"; + +%feature("docstring") Cell::buildNeighbors " +buildNeighbors() + +Build a collection of neighboring Cells for optimized ray tracing. +"; + +%feature("docstring") Cell::isTranslated " +isTranslated() -> bool + +Return a boolean indicating whether the Cell has been translated. + +Returns +------- +whether the Cell has been translated +"; + +%feature("docstring") Cell::getTranslation " +getTranslation() -> double * + +Return pointer to array for the translations along x, y and z. + +Returns +------- +a pointer to an array of translations +"; + +%feature("docstring") Cell::getTheta " +getTheta(std::string units=\"degrees\") -> double + +Get the rotation angle about the y-axis in degrees. + +Parameters +---------- +* units : + the angular units in \"radians\" or \"degrees\" (default) + +Returns +------- +the rotation angle about the y-axis +"; + +%feature("docstring") Cell::getPhi " +getPhi(std::string units=\"degrees\") -> double + +Get the rotation angle about the x-axis in degrees. + +Parameters +---------- +* units : + the angular units in \"radians\" or \"degrees\" (default) + +Returns +------- +the rotation angle about the x-axis +"; + +%feature("docstring") Cell::subdivideCell " +subdivideCell(double max_radius) + +Subdivides a Cell into rings and sectors aligned with the z-axis. + +This method uses the Cell's clone method to produce a vector of this Cell's subdivided +ring and sector Cells. + +Parameters +---------- +* max_radius : + the maximum allowable radius used in the subdivisions + +Returns +------- +a vector of Cell pointers to the new subdivided Cells + +A container of all Cell clones created for rings and sectors +"; + +%feature("docstring") Cell::getNumRings " +getNumRings() -> int + +Return the number of rings in the Cell. + +Returns +------- +the number of rings +"; + +%feature("docstring") Cell::getMaxYBoundaryType " +getMaxYBoundaryType() -> boundaryType + +Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at the maximum reachable +y-coordinate in the Cell. + +Returns +------- +the boundary condition at the maximum y-coordinate +"; + +%feature("docstring") Cell::containsPoint " +containsPoint(Point *point) -> bool + +Determines whether a Point is contained inside a Cell. + +Queries each Surface inside the Cell to determine if the Point is on the same side of the +Surface. This point is only inside the Cell if it is on the same side of every Surface in +the Cell. + +Parameters +---------- +* point : + a pointer to a Point +"; + +%feature("docstring") Cell::setName " +setName(const char *name) + +Sets the name of the Cell. + +Parameters +---------- +* name : + the Cell name string +"; + +%feature("docstring") Cell::removeSurface " +removeSurface(Surface *surface) + +Removes a Surface from this Cell's container of bounding Surfaces. + +Parameters +---------- +* surface : + a pointer to the Surface to remove +"; + +%feature("docstring") Cell::getPsi " +getPsi(std::string units=\"degrees\") -> double + +Get the rotation angle about the z-axis in degrees. + +Parameters +---------- +* units : + the angular units in \"radians\" or \"degrees\" (default) + +Returns +------- +the rotation angle about the z-axis +"; + +%feature("docstring") Cell::getNumInstances " +getNumInstances() -> int + +Return the number of instances of this Cell in the Geometry. + +The number of instances of this Cell in the Geometry is determined during track +generation. + +Returns +------- +the number of cell instances +"; + +%feature("docstring") Cell::toString " +toString() -> std::string + +Convert this Cell's attributes to a string format. + +Returns +------- +a character array of this Cell's attributes + +Add string data for the Surfaces in this Cell +"; + +%feature("docstring") Cell::getNeighbors " +getNeighbors() const -> std::vector< Cell * > + +Return the std::vector of neighbor Cells to this Cell. + +Returns +------- +std::vector of neighbor Cell pointers +"; + +%feature("docstring") Cell::setNumInstances " +setNumInstances(int num_instances) + +Set the number of instances of this Cell. + +Parameters +---------- +* num_instances : + the number of instances of this Cell in the Geometry +"; + +%feature("docstring") Cell::getSurfaces " +getSurfaces() const -> std::map< int, surface_halfspace * > + +Return the std::map of Surface pointers and halfspaces (+/-1) for all surfaces bounding +the Cell. + +Returns +------- +std::map of Surface pointers and halfspaces +"; + +%feature("docstring") Cell::getFillUniverse " +getFillUniverse() -> Universe * + +Return a pointer to the Material filling this Cell. + +Returns +------- +the Material fill pointer +"; + +%feature("docstring") Cell::setRotation " +setRotation(double *rotation, int num_axes, std::string units=\"degrees\") + +Set the Cell's rotation angles about the x, y and z axes. + +This method is a helper function to allow OpenMOC users to assign the Cell's rotation +angles in Python. A user must initialize a length 3 NumPy array as input to this function. +This function then stores the data values in the NumPy array in the Cell's rotation array. +An example of how this function might be called in Python is as follows: + + +Parameters +---------- +* rotation : + the array of rotation angles +* num_axes : + the number of axes (this must always be 3) +* units : + the angular units in \"radians\" or \"degrees\" (default) +"; + +%feature("docstring") Cell::isRotated " +isRotated() -> bool + +Return a boolean indicating whether the Cell has been rotated. + +Returns +------- +whether the Cell has been rotated +"; + +%feature("docstring") Cell::setParent " +setParent(Cell *parent) + +Assign a parent Cell to this Cell. + +This is used by Cell cloning when applied for radial and angular discretization. + +Parameters +---------- +* parent : + a pointer to the parent Cell +"; + +%feature("docstring") Cell::incrementNumInstances " +incrementNumInstances() + +Increment the number of instances of this Cell. + +This routine is called by the TrackGenerator during track generation and segmentation. +"; + +%feature("docstring") Cell::printString " +printString() + +Prints a string representation of all of the Cell's attributes to the console. +"; + +%feature("docstring") Cell::isFissionable " +isFissionable() -> bool + +Returns true if this Cell is filled with a fissionable Material. + +If the Cell is filled by a Material, this method will simply query the filling Material. +If the Cell is filled by a Universe, this method will consider any Materials filling those +Cells contained by the filling Universe. This method should not be called prior to the +calling of the Geometry::computeFissionability() method. + +Returns +------- +true if contains a fissionable Material +"; + +%feature("docstring") Cell::hasParent " +hasParent() -> bool + +Return true if the Cell has a parent and false otherwise. + +Returns +------- +whether the Cell has a parent Cell +"; + +%feature("docstring") Cell::getMinYBoundaryType " +getMinYBoundaryType() -> boundaryType + +Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at the minimum reachable +y-coordinate in the Cell. + +Returns +------- +the boundary condition at the minimum y-coordinate +"; + +%feature("docstring") Cell::getId " +getId() const -> int + +Return the Cell's user-specified ID. + +Returns +------- +the Cell's user-specified ID +"; + +%feature("docstring") Cell::getParent " +getParent() -> Cell * + +Return this Cell's parent Cell. + +If no parent Cell has been assigned from Cell cloning, then NULL is returned. + +Returns +------- +a pointer to the parent Cell +"; + +%feature("docstring") Cell::getFillMaterial " +getFillMaterial() -> Material * + +Return a pointer to the Material filling this Cell. + +Returns +------- +the Material fill pointer +"; + +%feature("docstring") Cell::containsCoords " +containsCoords(LocalCoords *coords) -> bool + +Determines whether a Point is contained inside a Cell. + +Queries each Surface inside the Cell to determine if the Point is on the same side of the +Surface. This Point is only inside the Cell if it is on the same side of every Surface in +the Cell. + +Parameters +---------- +* coords : + a pointer to a localcoord +"; + +// File: classCmfd.xml + + +%feature("docstring") Cmfd " + +A class for Coarse Mesh Finite Difference (CMFD) acceleration. + +C++ includes: src/Cmfd.h +"; + +%feature("docstring") Cmfd::initializeGroupMap " +initializeGroupMap() + +Initialize and set array that links the MOC energy groups to the CMFD energy groups. + +This method initializes the _group_indices_map, which is a 1D array of length +_num_moc_groups that maps the MOC energy groups to CMFD energy groups. The indices into +_group_indices_map are the MOC energy groups and the values are the CMFD energy groups. +"; + +%feature("docstring") Cmfd::getNumY " +getNumY() -> int + +Get the number of Mesh cells in a column. + +Returns +------- +The number of Mesh cells in a column +"; + +%feature("docstring") Cmfd::getNumX " +getNumX() -> int + +Get the number of Mesh cells in a row. + +Returns +------- +The number of Mesh cells in a row +"; + +%feature("docstring") Cmfd::~Cmfd " +~Cmfd() + +Destructor. +"; + +%feature("docstring") Cmfd::setNumFSRs " +setNumFSRs(int num_fsrs) + +Set the number of FSRs. + +Parameters +---------- +* num_fsrs : + The number of FSRs +"; + +%feature("docstring") Cmfd::setFSRVolumes " +setFSRVolumes(FP_PRECISION *FSR_volumes) + +Set the pointer to the array of FSR_volumes. + +Parameters +---------- +* FSR_volumes : + Array of FSR volumes +"; + +%feature("docstring") Cmfd::getNumCmfdGroups " +getNumCmfdGroups() -> int + +Get the number of coarse CMFD energy groups. + +Returns +------- +The number of CMFD energy groups +"; + +%feature("docstring") Cmfd::getCmfdGroup " +getCmfdGroup(int group) -> int + +Get the CMFD group given an MOC group. + +Parameters +---------- +* group : + The MOC energy group + +Returns +------- +The CMFD energy group +"; + +%feature("docstring") Cmfd::setLatticeStructure " +setLatticeStructure(int num_x, int num_y) + +The structure of the Lattice to be used as the CMFD mesh. + +Parameters +---------- +* num_x : + The number of cells in the x direction. +* num_y : + The number of cells in the y direction. +"; + +%feature("docstring") Cmfd::getNumMOCGroups " +getNumMOCGroups() -> int + +Get the number of MOC energy groups. + +Returns +------- +The number of MOC energy groups +"; + +%feature("docstring") Cmfd::Cmfd " +Cmfd() + +Constructor initializes boundaries and variables that describe the Cmfd object. + +The construcor initializes the many variables that describe the CMFD mesh and are used to +solve the nonlinear diffusion acceleration problem. +"; + +%feature("docstring") Cmfd::setGeometry " +setGeometry(Geometry *geometry) + +Set a pointer to the Geometry. + +Parameters +---------- +* goemetry : + A pointer to a Geometry object. +"; + +%feature("docstring") Cmfd::zeroCurrents " +zeroCurrents() + +Zero the surface currents for each mesh cell and energy group. +"; + +%feature("docstring") Cmfd::setGroupStructure " +setGroupStructure(int *group_indices, int length_group_indices) + +Set the CMFD energy group structure. + +CMFD does not necessarily need to have the same energy group structure as the MOC problem. +This function can be used to set a sparse energy group structure to speed up the CMFD +solve. + +Parameters +---------- +* group_indices : + An array of the CMFD group boundaries +* length_group_indices : + The length of the group_indices array +"; + +%feature("docstring") Cmfd::setWidthY " +setWidthY(double width) + +Set Mesh width in the y-direction. + +Parameters +---------- +* width : + Physical width of Mesh in the y-direction +"; + +%feature("docstring") Cmfd::setWidthX " +setWidthX(double width) + +Set Mesh width in the x-direction. + +Parameters +---------- +* width : + Physical width of Mesh in the x-direction +"; + +%feature("docstring") Cmfd::setFluxUpdateOn " +setFluxUpdateOn(bool flux_update_on) + +Set flag indicating whether to update the MOC flux. + +Parameters +---------- +* flux_update_on : + Boolean saying whether to update MOC flux. +"; + +%feature("docstring") Cmfd::getCellFSRs " +getCellFSRs() -> std::vector< std::vector< int > > * + +Return a pointer to the vector of vectors that contains the FSRs that lie in each cell. + +Returns +------- +Vector of vectors containing FSR IDs in each cell. +"; + +%feature("docstring") Cmfd::setFSRMaterials " +setFSRMaterials(Material **FSR_materials) + +Set the FSR materials array pointer. + +Parameters +---------- +* FSR_materials : + Pointer to FSR_materials array +"; + +%feature("docstring") Cmfd::initializeLattice " +initializeLattice(Point *offset) + +Initialize the CMFD lattice. +"; + +%feature("docstring") Cmfd::convertFSRIdToCmfdCell " +convertFSRIdToCmfdCell(int fsr_id) -> int + +Return the CMFD cell ID that an FSR lies in. + +Note that a CMFD cell is not an actual Cell object; rather, a CMFD cell is just a way of +describing each of the rectangular regions that make up a CMFD lattice. CMFD cells are +numbered with 0 in the lower left corner and monotonically increasing from left to right +and from bottom to top. For example, the indices for a 4 x 4 lattice are: 12 13 14 15 8 9 +10 11 4 5 6 7 0 1 2 3 + +Parameters +---------- +* fsr_id : + The FSR ID. + +Returns +------- +The CMFD cell ID. Return -1 if cell is not found. +"; + +%feature("docstring") Cmfd::setCellFSRs " +setCellFSRs(std::vector< std::vector< int > > *cell_fsrs) + +Set the vector of vectors that contains the FSRs that lie in each cell. + +Parameters +---------- +* cell_fsrs : + Vector of vectors containing FSR IDs in each cell. +"; + +%feature("docstring") Cmfd::tallyCurrent " +tallyCurrent(segment *curr_segment, FP_PRECISION *track_flux, FP_PRECISION *polar_weights, + bool fwd) + +Tallies the current contribution from this segment across the the appropriate CMFD mesh +cell surface. + +Parameters +---------- +* curr_segment : + The current Track segment +* track_flux : + The outgoing angular flux for this segment +* polar_weights : + Array of polar weights for some azimuthal angle +* fwd : + Boolean indicating direction of integration along segment +"; + +%feature("docstring") Cmfd::setCentroidUpdateOn " +setCentroidUpdateOn(bool centroid_update_on) + +Set flag indicating whether to use FSR centroids to update the MOC flux. + +Parameters +---------- +* centroid_update_on : + Flag saying whether to use centroids to update MOC flux. +"; + +%feature("docstring") Cmfd::findCmfdSurface " +findCmfdSurface(int cell_id, LocalCoords *coords) -> int + +Find the cmfd surface that a LocalCoords object lies on. + +If the coords is not on a surface, -1 is returned. Otherwise, the surface ID is returned. + +Parameters +---------- +* cell_id : + The CMFD cell ID that the local coords is in. +* coords : + The coords being evaluated. + +Returns +------- +The surface ID. +"; + +%feature("docstring") Cmfd::getBoundary " +getBoundary(int side) -> int + +Get the boundaryType for one side of the CMFD mesh. + +Parameters +---------- +* side : + The CMFD mesh surface ID. + +Returns +------- +The boundaryType for the surface. +"; + +%feature("docstring") Cmfd::setNumMOCGroups " +setNumMOCGroups(int num_moc_groups) + +Set the number of MOC energy groups. + +Parameters +---------- +* num_groups : + Number of MOC energy groups +"; + +%feature("docstring") Cmfd::setSORRelaxationFactor " +setSORRelaxationFactor(FP_PRECISION SOR_factor) + +Set the successive over-relaxation factor for the linear solve within the diffusion +eigenvalue solve. + +Parameters +---------- +* SOR_factor : + Over-relaxation factor +"; + +%feature("docstring") Cmfd::initialize " +initialize() + +Initialize the Matrix and Vector objects, k-nearest stencils, the CMFD cell currents and +MOC materials. +"; + +%feature("docstring") Cmfd::setKNearest " +setKNearest(int k_nearest) + +Set a number of k-nearest neighbor cells to use in updating the FSR flux. + +Parameters +---------- +* k_nearest : + The number of nearest neighbor CMFD cells. +"; + +%feature("docstring") Cmfd::setFSRFluxes " +setFSRFluxes(FP_PRECISION *scalar_flux) + +Set pointer to FSR flux array. + +Parameters +---------- +* scalar_flux : + Pointer to FSR flux array +"; + +%feature("docstring") Cmfd::setNumY " +setNumY(int num_y) + +Set the number of Mesh cells in a column. + +Parameters +---------- +* num_y : + Number of Mesh cells in a column +"; + +%feature("docstring") Cmfd::setNumX " +setNumX(int num_x) + +Set the number of Mesh cells in a row. + +Parameters +---------- +* num_x : + Number of Mesh cells in a row +"; + +%feature("docstring") Cmfd::getLattice " +getLattice() -> Lattice * + +Returns the Lattice object used as the CMFD mesh. + +Returns +------- +A pointer to a Lattice object. +"; + +%feature("docstring") Cmfd::addFSRToCell " +addFSRToCell(int cell_id, int fsr_id) + +Add an FSR ID to a vector that contains all the FSR IDs contained within a CMFD mesh cell. + +Parameters +---------- +* cell_id : + The CMFD cell ID. +* fsr_id : + The FSR ID. +"; + +%feature("docstring") Cmfd::findCmfdCell " +findCmfdCell(LocalCoords *coords) -> int + +Find the CMFD cell that a LocalCoords object is in. + +Parameters +---------- +* coords : + The coords being evaluated. + +Returns +------- +The CMFD cell ID. +"; + +%feature("docstring") Cmfd::setPolarQuadrature " +setPolarQuadrature(PolarQuad *polar_quad) + +Sets the PolarQuad object in use by the MOC Solver. + +Parameters +---------- +* polar_quad : + A PolarQuad object pointer from the Solver +"; + +%feature("docstring") Cmfd::updateBoundaryFlux " +updateBoundaryFlux(Track **tracks, FP_PRECISION *boundary_flux, int num_tracks) + +Update the MOC boundary fluxes. + +The MOC boundary fluxes are updated using the P0 approximation. With this approximation, +the boundary fluxes are updated using the ratio of new to old flux for the cell that the +outgoing flux from the track enters. + +Parameters +---------- +* tracks : + 2D array of Tracks +* boundary_flux : + Array of boundary fluxes + +Returns +------- +The number of Tracks +"; + +%feature("docstring") Cmfd::setBoundary " +setBoundary(int side, boundaryType boundary) + +Set the CMFD boundary type for a given surface. + +The CMFD boundary is assumed to be rectangular with the surfaces identified by constants +in the constants.h file. + +Parameters +---------- +* side : + The CMFD surface UID. +* boundary : + The boundaryType of the surface. +"; + +%feature("docstring") Cmfd::setSourceConvergenceThreshold " +setSourceConvergenceThreshold(FP_PRECISION source_thresh) + +Sets the threshold for CMFD source convergence (>0) + +Parameters +---------- +* the : + threshold for source convergence +"; + +%feature("docstring") Cmfd::isFluxUpdateOn " +isFluxUpdateOn() -> bool + +Get flag indicating whether to update the MOC flux. + +Returns +------- +Boolean saying whether to update MOC flux. +"; + +%feature("docstring") Cmfd::computeKeff " +computeKeff(int moc_iteration) -> FP_PRECISION + +Solve the nonlinear diffusion acceleration problem to accelerate the convergence of the +MOC problem. + +This method uses the information from the last MOC transport sweep and solves a simplified +nonlinear diffusion problem. The diffusion problem is tightly converged and the solution +is used to update the the solution of the MOC problem. + +Parameters +---------- +* moc_iteration : + MOC iteration number + +Returns +------- +The dominant eigenvalue of the nonlinear diffusion problem +"; + +%feature("docstring") Cmfd::initializeCellMap " +initializeCellMap() + +Initializes the vector of vectors that links CMFD cells with FSRs. + +This method is called by the geometry once the CMFD mesh has been initialized by the +geometry. This method allocates a vector for each CMFD cell that is used to store the FSR +ids contained within that cell. +"; + +%feature("docstring") Cmfd::isCentroidUpdateOn " +isCentroidUpdateOn() -> bool + +Get flag indicating whether to use FSR centroids to update the MOC flux. + +Returns +------- +Flag saying whether to use centroids to update MOC flux. +"; + +%feature("docstring") Cmfd::getNumCells " +getNumCells() -> int + +Get the number of CMFD cells. + +Returns +------- +The number of CMFD cells +"; + +// File: classCPUSolver.xml + + +%feature("docstring") CPUSolver " + +This a subclass of the Solver class for multi-core CPUs using OpenMP multi-threading. + +C++ includes: src/CPUSolver.h +"; + +%feature("docstring") CPUSolver::~CPUSolver " +~CPUSolver() + +Destructor deletes array for OpenMP mutual exclusion locks for FSR scalar flux updates, +and calls Solver parent class destructor to deletes arrays for fluxes and sources. +"; + +%feature("docstring") CPUSolver::computeFSRScatterSources " +computeFSRScatterSources() + +Computes the total scattering source in each FSR. + +This method is a helper routine for the openmoc.krylov submodule. +"; + +%feature("docstring") CPUSolver::initializeFluxArrays " +initializeFluxArrays() + +Allocates memory for Track boundary angular and FSR scalar fluxes. + +Deletes memory for old flux arrays if they were allocated for a previous simulation. +"; + +%feature("docstring") CPUSolver::flattenFSRFluxes " +flattenFSRFluxes(FP_PRECISION value) + +Set the scalar flux for each FSR and energy group to some value. + +Parameters +---------- +* value : + the value to assign to each FSR scalar flux +"; + +%feature("docstring") CPUSolver::transportSweep " +transportSweep() + +This method performs one transport sweep of all azimuthal angles, Tracks, Track segments, +polar angles and energy groups. + +The method integrates the flux along each Track and updates the boundary fluxes for the +corresponding output Track, while updating the scalar flux in each flat source region. +"; + +%feature("docstring") CPUSolver::setFluxes " +setFluxes(FP_PRECISION *in_fluxes, int num_fluxes) + +Set the flux array for use in transport sweep source calculations. This is a helper +method for the checkpoint restart capabilities, as well as the IRAMSolver in the +openmoc.krylov submodule. This routine may be used as follows from within Python: + + + + NOTE: This routine stores a pointer to the fluxes for the Solver + to use during transport sweeps and other calculations. Hence, the + flux array pointer is shared between NumPy and the Solver. + +Parameters +---------- +* in_fluxes : + an array with the fluxes to use +* num_fluxes : + the number of flux values (# groups x # FSRs) +"; + +%feature("docstring") CPUSolver::computeFSRFissionSources " +computeFSRFissionSources() + +Computes the total fission source in each FSR. + +This method is a helper routine for the openmoc.krylov submodule. +"; + +%feature("docstring") CPUSolver::computeKeff " +computeKeff() + +Compute $ k_{eff} $ from successive fission sources. +"; + +%feature("docstring") CPUSolver::initializeFixedSources " +initializeFixedSources() + +Populates array of fixed sources assigned by FSR. +"; + +%feature("docstring") CPUSolver::addSourceToScalarFlux " +addSourceToScalarFlux() + +Add the source term contribution in the transport equation to the FSR scalar flux. +"; + +%feature("docstring") CPUSolver::getFluxes " +getFluxes(FP_PRECISION *out_fluxes, int num_fluxes) + +Fills an array with the scalar fluxes. + +This class method is a helper routine called by the OpenMOC Python \"openmoc.krylov\" +module for Krylov subspace methods. Although this method appears to require two arguments, +in reality it only requires one due to SWIG and would be called from within Python as +follows: + + +Parameters +---------- +* fluxes : + an array of FSR scalar fluxes in each energy group +* num_fluxes : + the total number of FSR flux values +"; + +%feature("docstring") CPUSolver::zeroTrackFluxes " +zeroTrackFluxes() + +Zero each Track's boundary fluxes for each energy group and polar angle in the \"forward\" +and \"reverse\" directions. +"; + +%feature("docstring") CPUSolver::CPUSolver " +CPUSolver(TrackGenerator *track_generator=NULL) + +Constructor initializes array pointers for Tracks and Materials. + +The constructor retrieves the number of energy groups and FSRs and azimuthal angles from +the Geometry and TrackGenerator if passed in as parameters by the user. The constructor +initalizes the number of OpenMP threads to a default of 1. + +Parameters +---------- +* track_generator : + an optional pointer to the TrackGenerator +"; + +%feature("docstring") CPUSolver::normalizeFluxes " +normalizeFluxes() + +Normalizes all FSR scalar fluxes and Track boundary angular fluxes to the total fission +source (times $ \\nu $). +"; + +%feature("docstring") CPUSolver::setNumThreads " +setNumThreads(int num_threads) + +Sets the number of shared memory OpenMP threads to use (>0). + +Parameters +---------- +* num_threads : + the number of threads +"; + +%feature("docstring") CPUSolver::getNumThreads " +getNumThreads() -> int + +Returns the number of shared memory OpenMP threads in use. + +Returns +------- +the number of threads +"; + +%feature("docstring") CPUSolver::initializeFSRs " +initializeFSRs() + +Initializes the FSR volumes and Materials array. + +This method gets an array of OpenMP mutual exclusion locks for each FSR for use in the +transport sweep algorithm. +"; + +%feature("docstring") CPUSolver::computeResidual " +computeResidual(residualType res_type) -> double + +Computes the residual between source/flux iterations. + +Parameters +---------- +* res_type : + the type of residuals to compute (SCALAR_FLUX, FISSION_SOURCE, TOTAL_SOURCE) + +Returns +------- +the average residual in each FSR +"; + +%feature("docstring") CPUSolver::initializeSourceArrays " +initializeSourceArrays() + +Allocates memory for FSR source arrays. + +Deletes memory for old source arrays if they were allocated for a previous simulation. +"; + +%feature("docstring") CPUSolver::computeFSRSources " +computeFSRSources() + +Computes the total source (fission, scattering, fixed) in each FSR. + +This method computes the total source in each FSR based on this iteration's current +approximation to the scalar flux. +"; + +%feature("docstring") CPUSolver::storeFSRFluxes " +storeFSRFluxes() + +Stores the FSR scalar fluxes in the old scalar flux array. +"; + +%feature("docstring") CPUSolver::computeFSRFissionRates " +computeFSRFissionRates(double *fission_rates, int num_FSRs) + +Computes the volume-integrated, energy-integrated nu-fission rate in each FSR and stores +them in an array indexed by FSR ID. + +This is a helper method for SWIG to allow users to retrieve FSR nu-fission rates as a +NumPy array. An example of how this method can be called from Python is as follows: + + +Parameters +---------- +* fission_rates : + an array to store the nu-fission rates (implicitly passed in as a NumPy array from + Python) +* num_FSRs : + the number of FSRs passed in from Python +"; + +// File: structdev__material.xml + + +%feature("docstring") dev_material " + +A Material's nuclear data to be stored on a GPU. + +Attributes +---------- +* _id : int + A user-defined ID for each Material created + +* _sigma_t : FP_PRECISION * + An array of the total cross-sections for each energy group + +* _sigma_f : FP_PRECISION * + A 2D array of the scattering cross-section matrix. The first index is row number and + second index is column number + +* _nu_sigma_f : FP_PRECISION * + An array of the fission cross-sections multiplied by nu $ \\nu $ for each energy group + +* _chi : FP_PRECISION * + An array of the chi $ \\chi $ values for each energy group + +* _fiss_matrix : FP_PRECISION * + A 2D array of the fission matrix from/into each group + +* _sigma_s : FP_PRECISION * + A 2D array of the scattering cross-section matrix from/into each group + +C++ includes: DeviceMaterial.h +"; + +%feature("docstring") dev_material::dev_material " +dev_material() + +Constructor for a dev_material struct on a GPU. +"; + +%feature("docstring") dev_material::~dev_material " +~dev_material() + +Destructor releases data for all Material's cross-sections on GPU. +"; + +// File: structdev__segment.xml + + +%feature("docstring") dev_segment " + +A dev_segment represents a line segment within a single flat source region along a track. + +The dev_segment is intended for use on the GPU. + +Attributes +---------- +* _length : FP_PRECISION + The length of the segment (cm) + +* _material_index : int + An index into the _materials array that contains Material pointers + +* _region_uid : int + The ID for flat source region in which this segment resides + +C++ includes: DeviceTrack.h +"; + +// File: structdev__track.xml + + +%feature("docstring") dev_track " + +A dev_track represents a characteristic line across the geometry. + +A dev_track has particular starting and ending points on the boundaries of the geometry +and an azimuthal angle. The dev_track is intended for use on the GPU. + +Attributes +---------- +* _uid : int + A monotonically increasing unique ID for each Track created + +* _azim_angle_index : int + The azimuthal angle index into the global 2D ragged array of Tracks + +* _segments : dev_segment * + A vector of segments making up this track + +* _num_segments : int + The number of segments making up this Track + +* _track_in : int + Index of the next Track when traveling along this Track in the \"forward\" direction. + +* _track_out : int + Index of the next Track when traveling along this Track in the \"reverse\" direction. + +* _next_in : bool + A boolean to indicate whether to give the flux to the \"forward\" (false) or + \"reverse\" (true) direction of the next Track going in the \"forward\" direction. + +* _next_out : bool + A boolean to indicate whether to give the flux to the \"forward\" (false) or + \"reverse\" (true) direction of the next Track going in the \"reverse\" direction. + +* _transfer_flux_in : bool + A boolean to indicate whether the outgoing angular flux along this Track's \"forward\" + direction should be transferred to the outgoing Track. + +* _transfer_flux_out : bool + A boolean to indicate whether the outgoing angular flux along this Track's \"reverse\" + direction should be transferred to the incoming Track. + +C++ includes: DeviceTrack.h +"; + +// File: classEqualAnglesPolarQuad.xml + + +%feature("docstring") EqualAnglesPolarQuad " + +Equal angles polar quadrature. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") EqualAnglesPolarQuad::EqualAnglesPolarQuad " +EqualAnglesPolarQuad() + +Dummy constructor calls the parent constructor. +"; + +%feature("docstring") EqualAnglesPolarQuad::initialize " +initialize() + +Routine to initialize the polar quadrature. + +This routine generates the sine thetas and weights. +"; + +%feature("docstring") EqualAnglesPolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles +"; + +// File: classEqualWeightsPolarQuad.xml + + +%feature("docstring") EqualWeightsPolarQuad " + +Equal weights polar quadrature. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") EqualWeightsPolarQuad::EqualWeightsPolarQuad " +EqualWeightsPolarQuad() + +Dummy constructor calls the parent constructor. +"; + +%feature("docstring") EqualWeightsPolarQuad::initialize " +initialize() + +Routine to initialize the polar quadrature. + +This routine generates the sine thetas and weights. +"; + +%feature("docstring") EqualWeightsPolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles +"; + +// File: classExpEvaluator.xml + + +%feature("docstring") ExpEvaluator " + +This is a class for evaluating exponentials. + +The ExpEvaluator includes different algorithms to evaluate exponentials with varying +degrees of accuracy and speed. This is a helper class for the Solver and its subclasses +and it not intended to be initialized as a standalone object. + +C++ includes: src/ExpEvaluator.h +"; + +%feature("docstring") ExpEvaluator::getTableSize " +getTableSize() -> int + +Get the number of entries in the exponential interpolation table. + +Parameters +---------- +* entries : + in the interpolation table +"; + +%feature("docstring") ExpEvaluator::setPolarQuadrature " +setPolarQuadrature(PolarQuad *polar_quad) + +Set the PolarQuad to use when computing exponentials. + +Parameters +---------- +* polar_quad : + a PolarQuad object pointer +"; + +%feature("docstring") ExpEvaluator::getTableSpacing " +getTableSpacing() -> FP_PRECISION + +Returns the exponential table spacing. + +Returns +------- +exponential table spacing +"; + +%feature("docstring") ExpEvaluator::setExpPrecision " +setExpPrecision(FP_PRECISION exp_precision) + +Sets the maximum acceptable approximation error for exponentials. + +This routine only affects the construction of the linear interpolation table for +exponentials, if in use. By default, a value of 1E-5 is used for the table, as recommended +by the analysis of Yamamoto in his 2004 paper on the subject. + +Parameters +---------- +* exp_precision : + the maximum exponential approximation error +"; + +%feature("docstring") ExpEvaluator::setMaxOpticalLength " +setMaxOpticalLength(FP_PRECISION max_optical_length) + +Sets the maximum optical length covered in the exponential interpolation table. + +Parameters +---------- +* max_optical_length : + the maximum optical length +"; + +%feature("docstring") ExpEvaluator::useIntrinsic " +useIntrinsic() + +Use the exponential intrinsic exp(...) to compute exponentials. +"; + +%feature("docstring") ExpEvaluator::isUsingInterpolation " +isUsingInterpolation() -> bool + +Returns true if using linear interpolation to compute exponentials. + +Returns +------- +true if so, false otherwise +"; + +%feature("docstring") ExpEvaluator::getExpTable " +getExpTable() -> FP_PRECISION * + +Returns a pointer to the exponential interpolation table. + +Returns +------- +pointer to the exponential interpolation table +"; + +%feature("docstring") ExpEvaluator::useInterpolation " +useInterpolation() + +Use linear interpolation to compute exponentials. +"; + +%feature("docstring") ExpEvaluator::getExpPrecision " +getExpPrecision() -> FP_PRECISION + +Gets the maximum acceptable approximation error for exponentials. + +Returns +------- +the maximum exponential approximation error +"; + +%feature("docstring") ExpEvaluator::getMaxOpticalLength " +getMaxOpticalLength() -> FP_PRECISION + +Gets the maximum optical length covered with the exponential interpolation table. + +Returns +------- +max_optical_length the maximum optical length +"; + +%feature("docstring") ExpEvaluator::ExpEvaluator " +ExpEvaluator() + +Constructor initializes array pointers to NULL. + +The constructor sets the interpolation scheme as the default for computing exponentials. +"; + +%feature("docstring") ExpEvaluator::computeExponential " +computeExponential(FP_PRECISION tau, int polar) -> FP_PRECISION + +Computes the exponential term for a optical length and polar angle. + +This method computes $ 1 - exp(-\\tau/sin(\\theta_p)) $ for some optical path length and +polar angle. This method uses either a linear interpolation table (default) or the +exponential intrinsic exp(...) function. + +Parameters +---------- +* tau : + the optical path length (e.g., sigma_t times length) +* polar : + the polar angle index + +Returns +------- +the evaluated exponential +"; + +%feature("docstring") ExpEvaluator::initialize " +initialize() + +If using linear interpolation, builds the table for each polar angle. + +Parameters +---------- +* tolerance : + the minimum acceptable interpolation accuracy +"; + +%feature("docstring") ExpEvaluator::~ExpEvaluator " +~ExpEvaluator() + +Destructor deletes table for linear interpolation of exponentials. +"; + +// File: classFixedHashMap.xml + + +%feature("docstring") FixedHashMap " + +A fixed-size hash map supporting insertion and lookup operations. + +The FixedHashMap class supports insertion and lookup operations but not deletion as +deletion is not needed in the OpenMOC application. This hash table uses chaining for +collisions and does not incorporate concurrency objects except for tracking the number of +entries in the table for which an atomic increment is used. This hash table is not thread +safe but is used as a building block for the ParallelHashMap class. This table guarantees +O(1) insertions and lookups on average. + +C++ includes: src/ParallelHashMap.h +"; + +%feature("docstring") FixedHashMap::clear " +clear() + +Clears all key/value pairs form the hash table. +"; + +%feature("docstring") FixedHashMap::keys " +keys() -> K * + +Returns an array of the keys in the fixed-size table. + +All buckets are scanned in order to form a list of all keys present in the table and then +the list is returned. WARNING: The user is responsible for freeing the allocated memory +once the array is no longer needed. + +Returns +------- +an array of keys in the map whose length is the number of key/value pairs in the table. +"; + +%feature("docstring") FixedHashMap::bucket_count " +bucket_count() -> size_t + +Returns the number of buckets in the fixed-size table. + +Returns +------- +number of buckets in the map +"; + +%feature("docstring") FixedHashMap::values " +values() -> V * + +Returns an array of the values in the fixed-size table. + +All buckets are scanned in order to form a list of all values present in the table and +then the list is returned. WARNING: The user is responsible for freeing the allocated +memory once the array is no longer needed. + +Returns +------- +an array of values in the map whose length is the number of key/value pairs in the table. +"; + +%feature("docstring") FixedHashMap::at " +at(K key) -> V & + +Determine the value associated with a given key in the fixed-size table. + +The linked list in the bucket associated with the key is searched and once the key is +found, the corresponding value is returned. An exception is thrown if the key is not +present in the map. + +Parameters +---------- +* key : + key whose corresponding value is desired + +Returns +------- +value associated with the given key +"; + +%feature("docstring") FixedHashMap::size " +size() -> size_t + +Returns the number of key/value pairs in the fixed-size table. + +Returns +------- +number of key/value pairs in the map +"; + +%feature("docstring") FixedHashMap::insert_and_get_count " +insert_and_get_count(K key, V value) -> int + +Inserts a key/value pair into the fixed-size table and returns the order number with which +it was inserted. + +The specified key value pair is inserted into the fixed-size table. If the key already +exists in the table, the pair is not inserted and the function returns -1. + +Parameters +---------- +* key : + key of the key/value pair to be inserted +* value : + value of the key/value pair to be inserted + +Returns +------- +order number in which key/value pair was inserted, -1 is returned if key was already +present in map. +"; + +%feature("docstring") FixedHashMap::insert " +insert(K key, V value) + +Inserts a key/value pair into the fixed-size table. + +The specified key value pair is inserted into the fixed-size table. If the key already +exists in the table, the pair is not inserted and the function returns. + +Parameters +---------- +* key : + key of the key/value pair to be inserted +* value : + value of the key/value pair to be inserted +"; + +%feature("docstring") FixedHashMap::~FixedHashMap " +~FixedHashMap() + +Destructor deletes all nodes in the linked lists associated with each bucket in the fixed- +size table and their pointers. +"; + +%feature("docstring") FixedHashMap::print_buckets " +print_buckets() + +Prints the contents of each bucket to the screen. + +All buckets are scanned and the contents of the buckets are printed, which are pointers to +linked lists. If the pointer is NULL suggesting that the linked list is empty, NULL is +printed to the screen. +"; + +%feature("docstring") FixedHashMap::contains " +contains(K key) -> bool + +Determine whether the fixed-size table contains a given key. + +The linked list in the bucket associated with the key is searched to determine whether the +key is present. + +Parameters +---------- +* key : + key to be searched + +Returns +------- +boolean value referring to whether the key is contained in the map +"; + +%feature("docstring") FixedHashMap::FixedHashMap " +FixedHashMap(size_t M=64) + +Constructor initializes fixed-size table of buckets filled with empty linked lists. + +The constructor initializes a fixed-size hash map with the size as an input parameter. If +no size is given the default size (64) is used. Buckets are filled with empty linked lists +presented as NULL pointers. + +Parameters +---------- +* M : + size of fixed hash map +"; + +// File: structfsr__data.xml + + +%feature("docstring") fsr_data " + +A fsr_data struct represents an FSR with a unique FSR ID and a characteristic point that +lies within the FSR that can be used to recompute the hierarchical LocalCoords linked +list. + +Attributes +---------- +* _fsr_id : int + The FSR ID + +* _cmfd_cell : int + The CMFD Cell + +* _mat_id : int + The Material ID + +* _point : Point * + Characteristic point in Root Universe that lies in FSR + +* _centroid : Point * + Global numerical centroid in Root Universe + +C++ includes: Geometry.h +"; + +%feature("docstring") fsr_data::~fsr_data " +~fsr_data() + +Destructor for fsr_data +"; + +%feature("docstring") fsr_data::fsr_data " +fsr_data() + +Constructor for FSR data initializes centroids and points to NULL +"; + +// File: classGeometry.xml + + +%feature("docstring") Geometry " + +The master class containing references to all geometry-related objects - Surfaces, Cells, +Universes and Lattices - and Materials. + +The primary purpose for the geometry is to serve as a collection of all geometry-related +objects, as well as for ray tracing of characteristic tracks across the Geometry and +computing FSR-to-cell offset maps. + +C++ includes: src/Geometry.h +"; + +%feature("docstring") Geometry::getAllUniverses " +getAllUniverses() -> std::map< int, Universe * > + +Return a std::map container of Universe IDs (keys) with Unierses pointers (values). + +Returns +------- +a std::map of Universes indexed by Universe ID in the geometry +"; + +%feature("docstring") Geometry::initializeFSRVectors " +initializeFSRVectors() + +Initialize key and material ID vectors for lookup by FSR ID This function initializes and +sets reverse lookup vectors by FSR ID. This is called after the FSRs have all been +identified and allocated during segmentation. This function must be called after +Geometry::segmentize() has completed. It should not be called if tracks are loaded from a +file. +"; + +%feature("docstring") Geometry::findCellContainingFSR " +findCellContainingFSR(int fsr_id) -> Cell * + +Finds the Cell containing a given fsr ID. + +Parameters +---------- +* fsr_id : + an FSR ID. +"; + +%feature("docstring") Geometry::getAllMaterialCells " +getAllMaterialCells() -> std::map< int, Cell * > + +Return a std::map container of Cell IDs (keys) with Cells pointers (values). + +Returns +------- +a std::map of Cells indexed by Cell ID in the geometry +"; + +%feature("docstring") Geometry::getMaxZ " +getMaxZ() -> double + +Return the maximum z-coordinate contained by the Geometry. + +Returns +------- +the maximum z-coordinate (cm) +"; + +%feature("docstring") Geometry::getMaxY " +getMaxY() -> double + +Return the maximum y-coordinate contained by the Geometry. + +Returns +------- +the maximum y-coordinate (cm) +"; + +%feature("docstring") Geometry::getMaxX " +getMaxX() -> double + +Return the maximum x-coordinate contained by the Geometry. + +Returns +------- +the maximum x-coordinate (cm) +"; + +%feature("docstring") Geometry::initializeFSRs " +initializeFSRs(bool neighbor_cells=false) + +Compute the number of flat source regions in the Geometry and initialize CMFD. + +This method is intended to be called by the user before initiating source iteration. This +method first subdivides all Cells by calling the Geometry::subdivideCells() method. Then +it initializes the CMFD object. neighbor_cells whether to use neighbor cell optimizations +"; + +%feature("docstring") Geometry::segmentize " +segmentize(Track *track) + +This method performs ray tracing to create Track segments within each flat source region +in the Geometry. + +This method starts at the beginning of a Track and finds successive intersection points +with FSRs as the Track crosses through the Geometry and creates segment structs and adds +them to the Track. + +Parameters +---------- +* track : + a pointer to a track to segmentize +"; + +%feature("docstring") Geometry::getFSRsToKeys " +getFSRsToKeys() -> std::vector< std::string > & + +Returns the vector that maps FSR IDs to FSR key hashes. + +Returns +------- +_FSR_keys_map map of FSR keys to FSR IDs +"; + +%feature("docstring") Geometry::setCmfd " +setCmfd(Cmfd *cmfd) + +Sets the pointer to a CMFD object used for acceleration. + +Parameters +---------- +* cmfd : + a pointer to the CMFD object +"; + +%feature("docstring") Geometry::getFSRId " +getFSRId(LocalCoords *coords) -> int + +Return the ID of the flat source region that a given LocalCoords object resides within. + +Parameters +---------- +* coords : + a LocalCoords object pointer + +Returns +------- +the FSR ID for a given LocalCoords object +"; + +%feature("docstring") Geometry::getFSRCentroid " +getFSRCentroid(int fsr_id) -> Point * + +Return the centroid for a given FSR ID. + +Parameters +---------- +* fsr_id : + the FSR ID + +Returns +------- +the FSR's centroid +"; + +%feature("docstring") Geometry::getFSRKeysMap " +getFSRKeysMap() -> ParallelHashMap< std::string, fsr_data * > & + +Returns a pointer to the map that maps FSR keys to FSR IDs. + +Returns +------- +pointer to _FSR_keys_map map of FSR keys to FSR IDs +"; + +%feature("docstring") Geometry::getMinY " +getMinY() -> double + +Return the minimum y-coordinate contained by the Geometry. + +Returns +------- +the minimum y-coordinate (cm) +"; + +%feature("docstring") Geometry::getMinX " +getMinX() -> double + +Return the minimum x-coordinate contained by the Geometry. + +Returns +------- +the minimum x-coordinate (cm) +"; + +%feature("docstring") Geometry::getMinZ " +getMinZ() -> double + +Return the minimum z-coordinate contained by the Geometry. + +Returns +------- +the minimum z-coordinate (cm) +"; + +%feature("docstring") Geometry::getMaxYBoundaryType " +getMaxYBoundaryType() -> boundaryType + +Returns the boundary conditions (REFLECTIVE or VACUUM) at the maximum y-coordinate in the +Geometry. + +Returns +------- +the boundary conditions for the maximum y-coordinate in the Geometry +"; + +%feature("docstring") Geometry::getAllCells " +getAllCells() -> std::map< int, Cell * > + +Return a std::map container of Cell IDs (keys) with Cells pointers (values). + +Returns +------- +a std::map of Cells indexed by Cell ID in the geometry +"; + +%feature("docstring") Geometry::getNumCells " +getNumCells() -> int + +Returns the number of Cells in the Geometry. + +Returns +------- +the number of Cells +"; + +%feature("docstring") Geometry::getFSRKey " +getFSRKey(LocalCoords *coords) -> std::string + +Generate a string FSR \"key\" that identifies an FSR by its unique hierarchical +lattice/universe/cell structure. + +Since not all FSRs will reside on the absolute lowest universe level and Cells might +overlap other cells, it is important to have a method for uniquely identifying FSRs. This +method creates a unique FSR key by constructing a structured string that describes the +hierarchy of lattices/universes/cells. + +Parameters +---------- +* coords : + a LocalCoords object pointer + +Returns +------- +the FSR key +"; + +%feature("docstring") Geometry::subdivideCells " +subdivideCells() + +Subdivides all Cells in the Geometry into rings and angular sectors aligned with the +z-axis. + +This method is called by the Geometry::initializeFSRs() method but may also be called by +the user in Python if needed: + + +"; + +%feature("docstring") Geometry::getRootUniverse " +getRootUniverse() -> Universe * + +Returns the Universe at the root node in the CSG tree. + +Returns +------- +the root Universe +"; + +%feature("docstring") Geometry::setRootUniverse " +setRootUniverse(Universe *root_universe) + +Sets the root Universe for the CSG tree. + +Parameters +---------- +* root_universe : + the root Universe of the CSG tree. +"; + +%feature("docstring") Geometry::computeFissionability " +computeFissionability(Universe *univ=NULL) + +Determines the fissionability of each Universe within this Geometry. + +A Universe is determined fissionable if it contains a Cell filled by a Material with a +non-zero fission cross-section. Note that this method recurses through all Universes at +each level in the nested Universe hierarchy. Users should only call this method without a +parameter (the default) from Python as follows to ensure that the recursion starts from +the uppermost Universe level: + + +Parameters +---------- +* univ : + the Universe of interest (default is NULL) +"; + +%feature("docstring") Geometry::getNumEnergyGroups " +getNumEnergyGroups() -> int + +Returns the number of energy groups for each Material's nuclear data. + +Returns +------- +the number of energy groups +"; + +%feature("docstring") Geometry::Geometry " +Geometry() + +Constructor initializes an empty Geometry. +"; + +%feature("docstring") Geometry::findCellContainingCoords " +findCellContainingCoords(LocalCoords *coords) -> Cell * + +Find the Cell that this LocalCoords object is in at the lowest level of the nested +Universe hierarchy. + +This method assumes that the LocalCoords has been initialized with coordinates and a +Universe ID. The method will recursively find the Cell on the lowest level of the nested +Universe hierarchy by building a linked list of LocalCoords from the LocalCoord passed in +as an argument down to the lowest level Cell found. In the process it will set the +coordinates at each level of the hierarchy for each LocalCoord in the linked list for the +Lattice or Universe that it is in. If the LocalCoords is outside the bounds of the +Geometry or on the boundaries this method will return NULL; otherwise it will return a +pointer to the Cell that is found by the recursive Geometry::findCell(...) method. + +Parameters +---------- +* coords : + pointer to a LocalCoords object + +Returns +------- +returns a pointer to a Cell if found, NULL if no Cell found +"; + +%feature("docstring") Geometry::getWidthZ " +getWidthZ() -> double + +Returns the total width in the z-direction of the Geometry in cm. + +Returns +------- +the total width of the Geometry in the z-direction (cm) +"; + +%feature("docstring") Geometry::getWidthY " +getWidthY() -> double + +Returns the total width in the y-direction of the Geometry in cm. + +Returns +------- +the total width of the Geometry in the y-direction (cm) +"; + +%feature("docstring") Geometry::getWidthX " +getWidthX() -> double + +Returns the total width in the x-direction of the Geometry in cm. + +Returns +------- +the total width of the Geometry in the x-direction (cm) +"; + +%feature("docstring") Geometry::findFSRMaterial " +findFSRMaterial(int fsr_id) -> Material * + +Find the Material for a flat source region ID. + +Parameters +---------- +* fsr_id : + a FSR id + +Returns +------- +a pointer to the Material that this FSR is in +"; + +%feature("docstring") Geometry::printString " +printString() + +Prints a string representation of all of the Geometry's attributes to the console. + +This method calls the printString() method for all Materials, Surfaces, Cell, Universes +and Lattices contained by the Geometry. +"; + +%feature("docstring") Geometry::getNumFSRs " +getNumFSRs() -> int + +Returns the number of flat source regions in the Geometry. + +Returns +------- +number of FSRs +"; + +%feature("docstring") Geometry::findFSRId " +findFSRId(LocalCoords *coords) -> int + +Find and return the ID of the flat source region that a given LocalCoords object resides +within. + +Parameters +---------- +* coords : + a LocalCoords object pointer + +Returns +------- +the FSR ID for a given LocalCoords object +"; + +%feature("docstring") Geometry::getCmfd " +getCmfd() -> Cmfd * + +Returns a pointer to the CMFD object. + +Returns +------- +A pointer to the CMFD object +"; + +%feature("docstring") Geometry::withinBounds " +withinBounds(LocalCoords *coords) -> bool + +Determins whether a point is within the bounding box of the geometry. + +Parameters +---------- +* coords : + a populated LocalCoords linked list + +Returns +------- +boolean indicating whether the coords is within the geometry +"; + +%feature("docstring") Geometry::getMaxXBoundaryType " +getMaxXBoundaryType() -> boundaryType + +Returns the boundary conditions (REFLECTIVE or VACUUM) at the maximum x-coordinate in the +Geometry. + +Returns +------- +the boundary conditions for the maximum z-coordinate in the Geometry +"; + +%feature("docstring") Geometry::getMinYBoundaryType " +getMinYBoundaryType() -> boundaryType + +Returns the boundary conditions (REFLECTIVE or VACUUM) at the minimum y-coordinate in the +Geometry. + +Returns +------- +the boundary conditions for the minimum y-coordinate in the Geometry +"; + +%feature("docstring") Geometry::getAllMaterials " +getAllMaterials() -> std::map< int, Material * > + +Return a std::map container of Material IDs (keys) with Materials pointers (values). + +Returns +------- +a std::map of Materials indexed by Material ID in the geometry +"; + +%feature("docstring") Geometry::getAllSurfaces " +getAllSurfaces() -> std::map< int, Surface * > + +Return a std::map container of Surface IDs (keys) with Surfaces pointers (values). + +Returns +------- +a std::map of Surfaces indexed by Surface ID in the geometry +"; + +%feature("docstring") Geometry::getMinXBoundaryType " +getMinXBoundaryType() -> boundaryType + +Returns the boundary conditions (REFLECTIVE or VACUUM) at the minimum x-coordinate in the +Geometry. + +Returns +------- +the boundary conditions for the minimum x-coordinate in the Geometry +"; + +%feature("docstring") Geometry::getFSRPoint " +getFSRPoint(int fsr_id) -> Point * + +Return the characteristic point for a given FSR ID. + +Parameters +---------- +* fsr_id : + the FSR ID + +Returns +------- +the FSR's characteristic point +"; + +%feature("docstring") Geometry::initializeCmfd " +initializeCmfd() + +This is a method that initializes the CMFD Lattice and sets CMFD parameters. +"; + +%feature("docstring") Geometry::toString " +toString() -> std::string + +Converts this Geometry's attributes to a character array. + +This method calls the toString() method for all Surfaces, Cells, Universes and Lattices +contained by the Geometry. Since this routine provides the metadata used by the +TrackGenerator to discriminate between geometries when exporting / importing binary track +files. + +Returns +------- +a character array of this Geometry's class attributes + +Add string data for all Cells + +Add string data for the Surfaces in this Cell + +Add string data for all Universes +"; + +%feature("docstring") Geometry::getNumMaterials " +getNumMaterials() -> int + +Returns the number of Materials in the Geometry. + +Returns +------- +the number of Materials +"; + +%feature("docstring") Geometry::setFSRCentroid " +setFSRCentroid(int fsr, Point *centroid) + +Sets the centroid for an FSR. + +The _FSR_keys_map stores a hash of a std::string representing the Lattice/Cell/Universe +hierarchy for a unique region and the associated FSR data. _centroid is a point that +represents the numerical centroid of an FSR computed using all segments contained in the +FSR. This method is used by the TrackGenerator to set the centroid after segments have +been created. It is important to note that this method is a helper function for the +TrackGenerator and should not be explicitly called by the user. + +Parameters +---------- +* fsr : + a FSR ID +* centroid : + a Point representing the FSR centroid +"; + +%feature("docstring") Geometry::~Geometry " +~Geometry() + +Destructor clears FSR to Cells and Materials maps. +"; + +// File: classGLPolarQuad.xml + + +%feature("docstring") GLPolarQuad " + +Gauss-Legendre's polar quadrature. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") GLPolarQuad::GLPolarQuad " +GLPolarQuad() + +Dummy constructor calls the parent constructor. +"; + +%feature("docstring") GLPolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles (maximum 6) +"; + +%feature("docstring") GLPolarQuad::initialize " +initialize() + +Routine to initialize the polar quadrature. + +This routine uses the tabulated values for the Gauss-Legendre polar angle quadrature, +including the sine thetas and weights. +"; + +// File: classGPUExpEvaluator.xml + + +%feature("docstring") GPUExpEvaluator " + +This is a class for evaluating exponentials on GPUs. + +The ExpEvaluator includes different algorithms to evaluate exponentials with varying +degrees of accuracy and speed. This is a helper class for the Solver and its subclasses +and it not intended to be initialized as a standalone object. + +Attributes +---------- +* _exp_table : FP_PRECISION * + The exponential linear interpolation table + +C++ includes: src/accel/cuda/ExpEvaluator.h +"; + +%feature("docstring") GPUExpEvaluator::computeExponential " +computeExponential(FP_PRECISION tau, int polar) -> __device__ FP_PRECISION + +Computes the exponential term for a optical length and polar angle. + +This method computes $ 1 - exp(-\\tau/sin(\\theta_p)) $ for some optical path length and +polar angle. This method uses either a linear interpolation table (default) or the +exponential intrinsic exp(...) function. + +Parameters +---------- +* tau : + the optical path length (e.g., sigma_t times length) +* polar : + the polar angle index + +Returns +------- +the evaluated exponential +"; + +// File: classGPUSolver.xml + + +%feature("docstring") GPUSolver " + +This a subclass of the Solver class for NVIDIA Graphics Processing Units (GPUs). + +The source code for this class includes C++ coupled with compute intensive CUDA kernels +for execution on the GPU. + +C++ includes: openmoc/src/dev/gpu/GPUSolver.h +"; + +%feature("docstring") GPUSolver::initializeFSRs " +initializeFSRs() + +Initializes the FSR volumes and dev_materials array on the GPU. + +This method assigns each FSR a unique, monotonically increasing ID, sets the Material for +each FSR, and assigns a volume based on the cumulative length of all of the segments +inside the FSR. +"; + +%feature("docstring") GPUSolver::zeroTrackFluxes " +zeroTrackFluxes() + +Zero each Track's boundary fluxes for each energy group and polar angle in the \"forward\" +and \"reverse\" directions. +"; + +%feature("docstring") GPUSolver::normalizeFluxes " +normalizeFluxes() + +Normalizes all FSR scalar fluxes and Track boundary angular fluxes to the total fission +source (times $ \\nu $). + +Create Thrust vector of fission sources in each FSR +"; + +%feature("docstring") GPUSolver::getNumThreadsPerBlock " +getNumThreadsPerBlock() -> int + +Returns the number of threads per block to execute on the GPU. + +Returns +------- +the number of threads per block +"; + +%feature("docstring") GPUSolver::computeResidual " +computeResidual(residualType res_type) -> double + +Computes the residual between source/flux iterations. + +Parameters +---------- +* res_type : + the type of residuals to compute (SCALAR_FLUX, FISSION_SOURCE, TOTAL_SOURCE) + +Returns +------- +the average residual in each flat source region +"; + +%feature("docstring") GPUSolver::setNumThreadsPerBlock " +setNumThreadsPerBlock(int num_threads) + +Sets the number of threads per block (>0) for CUDA kernels. + +Parameters +---------- +* num_threads : + the number of threads per block +"; + +%feature("docstring") GPUSolver::initializePolarQuadrature " +initializePolarQuadrature() + +Creates a polar quadrature object for the GPUSolver on the GPU. +"; + +%feature("docstring") GPUSolver::~GPUSolver " +~GPUSolver() + +Solver destructor frees all memory on the device, including arrays for the FSR scalar +fluxes and sources and Track boundary fluxes. +"; + +%feature("docstring") GPUSolver::setNumThreadBlocks " +setNumThreadBlocks(int num_blocks) + +Sets the number of thread blocks (>0) for CUDA kernels. + +Parameters +---------- +* num_blocks : + the number of thread blocks +"; + +%feature("docstring") GPUSolver::getNumThreadBlocks " +getNumThreadBlocks() -> int + +Returns the number of thread blocks to execute on the GPU. + +Returns +------- +the number of thread blocks +"; + +%feature("docstring") GPUSolver::addSourceToScalarFlux " +addSourceToScalarFlux() + +Add the source term contribution in the transport equation to the FSR scalar flux. +"; + +%feature("docstring") GPUSolver::initializeTracks " +initializeTracks() + +Allocates memory for all Tracks on the GPU. +"; + +%feature("docstring") GPUSolver::storeFSRFluxes " +storeFSRFluxes() + +Stores the FSR scalar fluxes in the old scalar flux array. +"; + +%feature("docstring") GPUSolver::getFSRSource " +getFSRSource(int fsr_id, int group) -> FP_PRECISION + +Returns the source for some energy group for a flat source region. + +This is a helper routine used by the openmoc.process module. + +Parameters +---------- +* fsr_id : + the ID for the FSR of interest +* group : + the energy group of interest + +Returns +------- +the flat source region source +"; + +%feature("docstring") GPUSolver::initializeMaterials " +initializeMaterials(solverMode mode=ADJOINT) + +Allocates all Materials data on the GPU. + +This method loops over the materials in the host_materials map. Since CUDA does not +support std::map data types on the device, the materials map must be converted to an array +and a map created that maps a material ID to an indice in the new materials array. In +initializeTracks, this map is used to convert the Material ID associated with every +segment to an index in the materials array. + +Parameters +---------- +* mode : + the solution type (FORWARD or ADJOINT) +"; + +%feature("docstring") GPUSolver::GPUSolver " +GPUSolver(TrackGenerator *track_generator=NULL) + +Constructor initializes arrays for dev_tracks and dev_materials.. + +The constructor initalizes the number of CUDA threads and thread blocks each to a default +of 64. + +Parameters +---------- +* track_generator : + an optional pointer to the TrackjGenerator +"; + +%feature("docstring") GPUSolver::getFlux " +getFlux(int fsr_id, int group) -> FP_PRECISION + +Returns the scalar flux for some FSR and energy group. + +Parameters +---------- +* fsr_id : + the ID for the FSR of interest +* group : + the energy group of interest + +Returns +------- +the FSR scalar flux +"; + +%feature("docstring") GPUSolver::computeFSRFissionSources " +computeFSRFissionSources() + +Computes the fission source in each FSR. + +This method computes the fission source in each FSR based on this iteration's current +approximation to the scalar flux. +"; + +%feature("docstring") GPUSolver::computeKeff " +computeKeff() + +Compute $ k_{eff} $ from successive fission sources. + +This method computes the current approximation to the multiplication factor on this +iteration as follows: $ k_{eff} = \\frac{\\displaystyle\\sum_{i \\in I} +\\displaystyle\\sum_{g \\in G} \\nu \\Sigma^F_g \\Phi V_{i}} {\\displaystyle\\sum_{i \\in +I} \\displaystyle\\sum_{g \\in G} (\\Sigma^T_g \\Phi V_{i} - \\Sigma^S_g \\Phi V_{i} - +L_{i,g})} $ +"; + +%feature("docstring") GPUSolver::transportSweep " +transportSweep() + +This method performs one transport sweep of all azimuthal angles, Tracks, Track segments, +polar angles and energy groups. + +The method integrates the flux along each Track and updates the boundary fluxes for the +corresponding output Track, while updating the scalar flux in each flat source region. +"; + +%feature("docstring") GPUSolver::computeFSRSources " +computeFSRSources() + +Computes the total source (fission, scattering, fixed) in each FSR. + +This method computes the total source in each FSR based on this iteration's current +approximation to the scalar flux. +"; + +%feature("docstring") GPUSolver::initializeFixedSources " +initializeFixedSources() + +Populates array of fixed sources assigned by FSR. +"; + +%feature("docstring") GPUSolver::initializeExpEvaluator " +initializeExpEvaluator() + +Initializes new GPUExpEvaluator object to compute exponentials. +"; + +%feature("docstring") GPUSolver::computeFSRScatterSources " +computeFSRScatterSources() + +Computes the scatter source in each FSR. + +This method computes the scatter source in each FSR based on this iteration's current +approximation to the scalar flux. +"; + +%feature("docstring") GPUSolver::initializeFluxArrays " +initializeFluxArrays() + +Allocates memory for Track boundary angular and FSR scalar fluxes. + +Deletes memory for old flux vectors if they were allocated for a previous simulation. +"; + +%feature("docstring") GPUSolver::setGeometry " +setGeometry(Geometry *geometry) + +Sets the Geometry for the Solver. + +This is a private setter method for the Solver and is not intended to be called by the +user. + +Parameters +---------- +* geometry : + a pointer to a Geometry object +"; + +%feature("docstring") GPUSolver::getFluxes " +getFluxes(FP_PRECISION *out_fluxes, int num_fluxes) + +Fills an array with the scalar fluxes on the GPU. + +This class method is a helper routine called by the OpenMOC Python \"openmoc.krylov\" +module for Krylov subspace methods. Although this method appears to require two arguments, +in reality it only requires one due to SWIG and would be called from within Python as +follows: + + +Parameters +---------- +* fluxes : + an array of FSR scalar fluxes in each energy group +* num_fluxes : + the total number of FSR flux values +"; + +%feature("docstring") GPUSolver::setFluxes " +setFluxes(FP_PRECISION *in_fluxes, int num_fluxes) + +Set the flux array for use in transport sweep source calculations. This is a helper +method for the checkpoint restart capabilities, as well as the IRAMSolver in the +openmoc.krylov submodule. This routine may be used as follows from within Python: + + + + NOTE: This routine stores a pointer to the fluxes for the Solver + to use during transport sweeps and other calculations. Hence, the + flux array pointer is shared between NumPy and the Solver. + +Parameters +---------- +* in_fluxes : + an array with the fluxes to use +* num_fluxes : + the number of flux values (# groups x # FSRs) +"; + +%feature("docstring") GPUSolver::flattenFSRFluxes " +flattenFSRFluxes(FP_PRECISION value) + +Set the scalar flux for each FSR and energy group to some value. + +Parameters +---------- +* value : + the value to assign to each FSR scalar flux +"; + +%feature("docstring") GPUSolver::computeFSRFissionRates " +computeFSRFissionRates(double *fission_rates, int num_FSRs) + +Computes the volume-averaged, energy-integrated nu-fission rate in each FSR and stores +them in an array indexed by FSR ID. + +This is a helper method for SWIG to allow users to retrieve FSR nu-fission rates as a +NumPy array. An example of how this method can be called from Python is as follows: + + +Parameters +---------- +* fission_rates : + an array to store the nu-fission rates (implicitly passed in as a NumPy array from + Python) +* num_FSRs : + the number of FSRs passed in from Python +"; + +%feature("docstring") GPUSolver::initializeSourceArrays " +initializeSourceArrays() + +Allocates memory for FSR source vectors on the GPU. + +Deletes memory for old source vectors if they were allocated for a previous simulation. +"; + +%feature("docstring") GPUSolver::setTrackGenerator " +setTrackGenerator(TrackGenerator *track_generator) + +Sets the Solver's TrackGenerator with characteristic Tracks. + +The TrackGenerator must already have generated Tracks and have used ray tracing to +segmentize them across the Geometry. This should be initated in Python prior to assigning +the TrackGenerator to the Solver: + + +Parameters +---------- +* track_generator : + a pointer to a TrackGenerator object +"; + +// File: structisinf__test.xml + + +%feature("docstring") isinf_test " + +A struct used to check if a value on the GPU is equal to INF. + +This is used as a predicate in Thrust routines. +"; + +// File: structisnan__test.xml + + +%feature("docstring") isnan_test " + +A struct used to check if a value on the GPU is equal to NaN. + +This is used as a predicate in Thrust routines. +"; + +// File: classLattice.xml + + +%feature("docstring") Lattice " + +Represents a repeating 3D Lattice of Universes. + +C++ includes: src/Universe.h +"; + +%feature("docstring") Lattice::withinBounds " +withinBounds(Point *point) -> bool + +Checks if a Point is within the bounds of a Lattice. + +Parameters +---------- +* point : + a pointer to the Point of interest + +Returns +------- +true if the Point is in the bounds, false if not +"; + +%feature("docstring") Lattice::printString " +printString() + +Prints a string representation of all of the Lattice's attributes to the console. +"; + +%feature("docstring") Lattice::subdivideCells " +subdivideCells(double max_radius=INFINITY) + +Subdivides all of the Material-filled Cells within this Lattice into rings and angular +sectors aligned with the z-axis. + +Parameters +---------- +* max_radius : + the maximum allowable radius used in the subdivisions +"; + +%feature("docstring") Lattice::getUniverses " +getUniverses() -> std::vector< std::vector< std::vector< std::pair< int, Universe * > > > + > * + +Return a 3D vector of the Universes in the Lattice. + +Returns +------- +3D vector of Universes +"; + +%feature("docstring") Lattice::getMinZ " +getMinZ() -> double + +Returns the minimum reachable z-coordinate in the Lattice. + +Returns +------- +the minimum reachable z-coordinate +"; + +%feature("docstring") Lattice::getMinX " +getMinX() -> double + +Returns the minimum reachable x-coordinate in the Lattice. + +Returns +------- +the minimum reachable x-coordinate +"; + +%feature("docstring") Lattice::getMinY " +getMinY() -> double + +Returns the minimum reachable y-coordinate in the Lattice. + +Returns +------- +the minimum reachable y-coordinate +"; + +%feature("docstring") Lattice::minSurfaceDist " +minSurfaceDist(LocalCoords *coords) -> double + +Finds the distance to the nearest surface. + +Knowing that a Lattice must be cartesian, this function computes the distance to the +nearest boundary between lattice cells in the direction of the track. + +Parameters +---------- +* coords : + a pointer to a localcoords object + +Returns +------- +the distance to the nearest Lattice cell boundary +"; + +%feature("docstring") Lattice::findCell " +findCell(LocalCoords *coords) -> Cell * + +Finds the Cell within this Lattice that a LocalCoords is in. + +This method first find the Lattice cell, then searches the Universe inside that Lattice +cell. If LocalCoords is outside the bounds of the Lattice, this method will return NULL. + +Parameters +---------- +* coords : + the LocalCoords of interest + +Returns +------- +a pointer to the Cell this LocalCoord is in or NULL +"; + +%feature("docstring") Lattice::getLatZ " +getLatZ(Point *point) -> int + +Finds the Lattice cell z index that a point lies in. + +Parameters +---------- +* point : + a pointer to a point being evaluated. + +Returns +------- +the Lattice cell z index. +"; + +%feature("docstring") Lattice::getLatY " +getLatY(Point *point) -> int + +Finds the Lattice cell y index that a point lies in. + +Parameters +---------- +* point : + a pointer to a point being evaluated. + +Returns +------- +the Lattice cell y index. +"; + +%feature("docstring") Lattice::setUniverses " +setUniverses(int num_z, int num_y, int num_x, Universe **universes) + +Sets the array of Universe pointers filling each Lattice cell. + +This is a helper method for SWIG to allow users to assign Universes to a Lattice using a +3D Python list (list of lists of lists). An example how this method can be called from +Python is as follows: + + +Parameters +---------- +* num_z : + the number of Lattice cells along z +* num_y : + the number of Lattice cells along y +* num_x : + the number of Lattice cells along x +* universes : + the array of Universes for each Lattice cell +"; + +%feature("docstring") Lattice::removeUniverse " +removeUniverse(Universe *universe) + +Removes all references to a Universe from the Lattice. + +Parameters +---------- +* universe : + the Universe to remove +"; + +%feature("docstring") Lattice::getUniverse " +getUniverse(int lat_x, int lat_y, int lat_z) const -> Universe * + +Returns a pointer to the Universe within a specific Lattice cell. + +Parameters +---------- +* lat_x : + the x index to the Lattice cell +* lat_y : + the y index to the Lattice cell +* lat_z : + the z index to the Lattice cell + +Returns +------- +pointer to a Universe filling the Lattice cell +"; + +%feature("docstring") Lattice::buildNeighbors " +buildNeighbors() + +Builds collections of neighboring Cells for all Cells in each Universe in the Lattice for +optimized ray tracing. +"; + +%feature("docstring") Lattice::Lattice " +Lattice(const int id=-1, const char *name=\"\") + +Constructor sets the user-specified and unique IDs for this Lattice. + +Parameters +---------- +* id : + the user-specified optional Lattice (Universe) ID +* name : + the user-specified optional Lattice (Universe) name +"; + +%feature("docstring") Lattice::setNumZ " +setNumZ(int num_z) + +Set the number of Lattice cells along the z-axis. + +Parameters +---------- +* num_z : + the number of Lattice cells along z +"; + +%feature("docstring") Lattice::setNumX " +setNumX(int num_x) + +Set the number of Lattice cells along the x-axis. + +Parameters +---------- +* num_x : + the number of Lattice cells along x +"; + +%feature("docstring") Lattice::setNumY " +setNumY(int num_y) + +Set the number of Lattice cells along the y-axis. + +Parameters +---------- +* num_y : + the number of Lattice cells along y +"; + +%feature("docstring") Lattice::getLatX " +getLatX(Point *point) -> int + +Finds the Lattice cell x index that a point lies in. + +Parameters +---------- +* point : + a pointer to a point being evaluated. + +Returns +------- +the Lattice cell x index. +"; + +%feature("docstring") Lattice::setOffset " +setOffset(double x, double y, double z) + +Set the offset in global coordinates for this Lattice. + +A lattice is assumed to be a rectilinear grid with the center/origin of the grid located +in the center of the Lattice's parent universe. The offset represents the offset of the +lattice center/origin with respect to the center of the parent universe. Therefore an +offset of (-1,2) would move the center/origin of the lattice to the left 1 cm and up 2 cm. + +Parameters +---------- +* x : + the offset in the x direction +* y : + the offset in the y direction +* z : + the offset in the z direction +"; + +%feature("docstring") Lattice::getWidthX " +getWidthX() const -> double + +Return the width of the Lattice along the x-axis. + +Returns +------- +the width of the Lattice cells along x +"; + +%feature("docstring") Lattice::getWidthY " +getWidthY() const -> double + +Return the width of the Lattice along the y-axis. + +Returns +------- +the width of the Lattice cells along y +"; + +%feature("docstring") Lattice::getWidthZ " +getWidthZ() const -> double + +Return the width of the Lattice along the z-axis. + +Returns +------- +the width of the Lattice cells along z +"; + +%feature("docstring") Lattice::getDistanceToSurface " +getDistanceToSurface(int cell, Point *point, int surface) -> double + +Finds the distance from a point to a particular lattice cell surface. + +Parameters +---------- +* cell : + the cell index that the point is in. +* point : + a pointer to a point being evaluated. +* surface : + a surface id to get the distance to. + +Returns +------- +the distance to the lattice cell surface of interest. +"; + +%feature("docstring") Lattice::getOffset " +getOffset() -> Point * + +Return a pointer to the offset for this Cell (in global coordinates). + +Returns +------- +the offset of the Cell +"; + +%feature("docstring") Lattice::setWidth " +setWidth(double width_x, double width_y, double width_z=std::numeric_limits< double + >::infinity()) + +Set the width of each Lattice cell. + +Parameters +---------- +* width_x : + the width along the x-axis in centimeters +* width_y : + the width along the y-axis in centimeters +* width_z : + the width along the z-axis in centimeters +"; + +%feature("docstring") Lattice::getUniqueUniverses " +getUniqueUniverses() -> std::map< int, Universe * > + +Aggregates a list (vector) of the IDs of all Universes within the FILL type Cells filling +this Universe. + +Note that this method only searches the first level of Cells below this Universe within +the nested Universe coordinate system. + +Returns +------- +a vector of Universe IDs +"; + +%feature("docstring") Lattice::getLatticeSurface " +getLatticeSurface(int cell, Point *point) -> int + +Finds the Lattice cell surface that a point lies on. If the point is not on a surface, -1 +is returned. + +The surface indices are defined in constants.h as they need to be consistent with the +surface constant definitions used in Cmfd. The index returned takes into account the cell +index and returns NUM_SURFACES*cell_index + surface_index. + +Parameters +---------- +* cell : + the cell index that the point is in. +* point : + a pointer to a point being evaluated. + +Returns +------- +the Lattice surface index. +"; + +%feature("docstring") Lattice::getAllUniverses " +getAllUniverses() -> std::map< int, Universe * > + +Returns the std::map of all nested Universe IDs and Universe pointers filling this +Lattice. + +Returns +------- +std::map of Universe IDs and pointers +"; + +%feature("docstring") Lattice::getNumZ " +getNumZ() const -> int + +Return the number of Lattice cells along the z-axis. + +Returns +------- +the number of Lattice cells along z +"; + +%feature("docstring") Lattice::getNumX " +getNumX() const -> int + +Return the number of Lattice cells along the x-axis. + +Returns +------- +the number of Lattice cells along x +"; + +%feature("docstring") Lattice::getNumY " +getNumY() const -> int + +Return the number of Lattice cells along the y-axis. + +Returns +------- +the number of Lattice cells along y +"; + +%feature("docstring") Lattice::getAllCells " +getAllCells() -> std::map< int, Cell * > + +Returns the std::map of Cell IDs and Cell pointers in this Lattice at all nested Universe +levels. + +Returns +------- +std::map of Cell IDs and pointers +"; + +%feature("docstring") Lattice::getLatticeCell " +getLatticeCell(Point *point) -> int + +Finds the Lattice cell index that a point lies in. + +Lattice cells are numbered starting with 0 x-min/y-min/z-min corner. Lattice cell IDs then +increase monotonically from x-min to x-max, y-min to y-max, and z-min to z-max. Note that +values increase first on the x-axis, followed by the y-axis, then on the z-axis. For +example, the indices for a 4 x 4 x 1 lattice: 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3 + +Parameters +---------- +* point : + a pointer to a point being evaluated. + +Returns +------- +the Lattice cell index. +"; + +%feature("docstring") Lattice::toString " +toString() -> std::string + +Converts a Lattice's attributes to a character array representation. + +Returns +------- +character array of this Lattice's attributes +"; + +%feature("docstring") Lattice::getMaxX " +getMaxX() -> double + +Returns the maximum reachable x-coordinate in the Lattice. + +Returns +------- +the maximum reachable x-coordinate +"; + +%feature("docstring") Lattice::getMaxY " +getMaxY() -> double + +Returns the maximum reachable y-coordinate in the Lattice. + +Returns +------- +the maximum reachable y-coordinate +"; + +%feature("docstring") Lattice::getMaxZ " +getMaxZ() -> double + +Returns the maximum reachable z-coordinate in the Lattice. + +Returns +------- +the maximum reachable z-coordinate +"; + +%feature("docstring") Lattice::~Lattice " +~Lattice() + +Destructor clears memory for all of Universes pointers. +"; + +// File: classLeonardPolarQuad.xml + + +%feature("docstring") LeonardPolarQuad " + +Leonard's polar quadrature. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") LeonardPolarQuad::initialize " +initialize() + +Routine to initialize the polar quadrature. + +This routine uses the tabulated values for the Leonard polar angle quadrature, including +the sine thetas and weights. +"; + +%feature("docstring") LeonardPolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles (2 or 3) +"; + +%feature("docstring") LeonardPolarQuad::LeonardPolarQuad " +LeonardPolarQuad() + +Dummy constructor calls the parent constructor. +"; + +// File: classLocalCoords.xml + + +%feature("docstring") LocalCoords " + +The LocalCoords represents a set of local coordinates on some level of nested Universes +making up the geometry. + +C++ includes: openmoc/src/host/LocalCoords.h +"; + +%feature("docstring") LocalCoords::getPhi " +getPhi() const -> double + +Returns the direction angle in radians with respect to the x-axis. + +Returns +------- +the direction angle in radians +"; + +%feature("docstring") LocalCoords::~LocalCoords " +~LocalCoords() + +Destructor. +"; + +%feature("docstring") LocalCoords::setPhi " +setPhi(double phi) + +Set the direction angle in radians for this LocalCoords. + +Parameters +---------- +* angle : + the direction angle in radians +"; + +%feature("docstring") LocalCoords::getLattice " +getLattice() const -> Lattice * + +Return the Lattice within which this LocalCoords resides. + +Returns +------- +the Lattice +"; + +%feature("docstring") LocalCoords::setCell " +setCell(Cell *cell) + +Set the Cell within which this LocalCoords resides. + +Parameters +---------- +* cell : + the Cell +"; + +%feature("docstring") LocalCoords::getPrev " +getPrev() const -> LocalCoords * + +Return a pointer to the LocalCoord at the next higher nested Universe level if one exists. + +Returns +------- +pointer to the previous LocalCoord +"; + +%feature("docstring") LocalCoords::getCell " +getCell() const -> Cell * + +Return the Cell within which this LocalCoords resides. + +Returns +------- +the Cell +"; + +%feature("docstring") LocalCoords::prune " +prune() + +Removes and frees memory for all LocalCoords beyond this one in the linked list. +"; + +%feature("docstring") LocalCoords::setNext " +setNext(LocalCoords *next) + +Sets the pointer to the LocalCoords on the next lower nested Universe level. + +Parameters +---------- +* next : + pointer to the next LocalCoords +"; + +%feature("docstring") LocalCoords::getZ " +getZ() const -> double + +Returns the z-coordinate for this LocalCoords location. + +Returns +------- +the z-coordinate of this LocalCoords location +"; + +%feature("docstring") LocalCoords::getNext " +getNext() const -> LocalCoords * + +Return a pointer to the LocalCoord at the next lower nested Universe level if one exists. + +Returns +------- +pointer to the next LocalCoord +"; + +%feature("docstring") LocalCoords::setZ " +setZ(double z) + +Set the z-coordinate for this Localcoords. + +Parameters +---------- +* z : + the z-coordinate +"; + +%feature("docstring") LocalCoords::setX " +setX(double x) + +Set the x-coordinate for this LocalCoords. + +Parameters +---------- +* x : + the x-coordinate +"; + +%feature("docstring") LocalCoords::setY " +setY(double y) + +Set the y-coordinate for this Localcoords. + +Parameters +---------- +* y : + the y-coordinate +"; + +%feature("docstring") LocalCoords::getLowestLevel " +getLowestLevel() -> LocalCoords * + +Find and return the last LocalCoords in the linked list which represents the local +coordinates on the lowest level of a geometry of nested universes. + +Traverses a linked list of LocalCoords to find the one at the lowest nested Universe +level. + +Returns +------- +a pointer to the last LocalCoords object in the list +"; + +%feature("docstring") LocalCoords::setType " +setType(coordType type) + +Set the type of LocalCoords (UNIV or LAT). + +Parameters +---------- +* type : + the type for LocalCoords (UNIV or LAT) +"; + +%feature("docstring") LocalCoords::setLatticeZ " +setLatticeZ(int lattice_z) + +Sets the z index for the Lattice cell within which this LocalCoords resides. + +Parameters +---------- +* lattice_z : + the z Lattice cell index +"; + +%feature("docstring") LocalCoords::setLatticeY " +setLatticeY(int lattice_y) + +Sets the y index for the Lattice cell within which this LocalCoords resides. + +Parameters +---------- +* lattice_y : + the y Lattice cell index +"; + +%feature("docstring") LocalCoords::getLatticeZ " +getLatticeZ() const -> int + +Return the third index of the Lattice cell within which this LocalCoords resides. + +Returns +------- +the third Lattice cell index +"; + +%feature("docstring") LocalCoords::getLatticeY " +getLatticeY() const -> int + +Return the second index of the Lattice cell within which this LocalCoords resides. + +Returns +------- +the second Lattice cell index +"; + +%feature("docstring") LocalCoords::getLatticeX " +getLatticeX() const -> int + +Return the first index of the Lattice cell within which this LocalCoords resides. + +Returns +------- +the first Lattice cell index +"; + +%feature("docstring") LocalCoords::getUniverse " +getUniverse() const -> Universe * + +Return the Universe within which this LocalCoords resides. + +Returns +------- +the Universe +"; + +%feature("docstring") LocalCoords::updateMostLocal " +updateMostLocal(Point *point) + +Update the last element in the linked list (the one at the lowest level of nested +Universes) to have the same coordinates as a given point. + +Parameters +---------- +* point : + a pointer to a point of interest +"; + +%feature("docstring") LocalCoords::toString " +toString() -> std::string + +Converts this LocalCoords's attributes to a character array representation. + +Returns +------- +a character array of the LocalCoord's attributes +"; + +%feature("docstring") LocalCoords::incrementPhi " +incrementPhi(double phi) + +Increment the direction angle in radians for this LocalCoords. + +Parameters +---------- +* phi : + the incremental direction angle in radians +"; + +%feature("docstring") LocalCoords::copyCoords " +copyCoords(LocalCoords *coords) + +Copies a LocalCoords' values to this one. details Given a pointer to a LocalCoords, it +first prunes it and then creates a copy of the linked list of LocalCoords in the linked +list below this one to give to the input LocalCoords. + +Parameters +---------- +* coords : + a pointer to the LocalCoords to give the linked list copy to +"; + +%feature("docstring") LocalCoords::setLattice " +setLattice(Lattice *lattice) + +Sets the Lattice within which this LocalCoords resides. + +Parameters +---------- +* lattice : + the Lattice +"; + +%feature("docstring") LocalCoords::adjustCoords " +adjustCoords(double delta) + +Translate all of the x,y coordinates for each LocalCoords object in the linked list. + +This method will traverse the entire linked list and apply the translation to each +element. + +Parameters +---------- +* delta : + amount we wish to move the point by +"; + +%feature("docstring") LocalCoords::getHighestLevel " +getHighestLevel() -> LocalCoords * + +Find and return the first LocalCoords in the linked list which represents the local +coordinates on the highest level of a geometry of nested universes. + +Traverses a linked list of LocalCoords to find the one at the highest nested Universe +level. + +Returns +------- +a pointer to the first LocalCoords object in the list +"; + +%feature("docstring") LocalCoords::setUniverse " +setUniverse(Universe *universe) + +Set the Universe within which this LocalCoords resides. + +Parameters +---------- +* universe : + the Universe +"; + +%feature("docstring") LocalCoords::getX " +getX() const -> double + +Returns the x-coordinate for this LocalCoords location. + +Returns +------- +the x-coordinate of this LocalCoords location +"; + +%feature("docstring") LocalCoords::getY " +getY() const -> double + +Returns the y-coordinate for this LocalCoords location. + +Returns +------- +the y-coordinate of this LocalCoords location +"; + +%feature("docstring") LocalCoords::getPoint " +getPoint() -> Point * + +Returns a pointer to the Point containing the coordinates for this LocalCoord. + +Returns +------- +pointer to the Point containing the x and y coordinates +"; + +%feature("docstring") LocalCoords::getType " +getType() -> coordType + +Return the level (UNIV or LAT) of this LocalCoords. + +Returns +------- +the nested Universe level (UNIV or LAT) +"; + +%feature("docstring") LocalCoords::LocalCoords " +LocalCoords(double x, double y, double z) + +Constructor sets the x and y coordinates. + +Parameters +---------- +* x : + the x-coordinate +* y : + the y-coordinate +"; + +%feature("docstring") LocalCoords::setLatticeX " +setLatticeX(int lattice_x) + +Sets the x index for the Lattice cell within which this LocalCoords resides. + +Parameters +---------- +* lattice_x : + the x Lattice cell index +"; + +%feature("docstring") LocalCoords::setPrev " +setPrev(LocalCoords *coords) + +Sets the pointer to the LocalCoords on the next higher nested Universe level. + +Parameters +---------- +* prev : + pointer to the previous LocalCoords +"; + +// File: classMaterial.xml + + +%feature("docstring") Material " + +The Material class represents a unique material and its relevant nuclear data (i.e., +multigroup cross-sections) for neutron transport. + +C++ includes: src/Material.h +"; + +%feature("docstring") Material::setChiByGroup " +setChiByGroup(double xs, int group) + +Set the Material's chi value for some energy group. + +Parameters +---------- +* xs : + the chi value ( $ \\Chi $) +* group : + the energy group +"; + +%feature("docstring") Material::getChiByGroup " +getChiByGroup(int group) -> FP_PRECISION + +Get the Material's fission spectrum for some energy group. + +Parameters +---------- +* group : + the energy group + +Returns +------- +the fission spectrum +"; + +%feature("docstring") Material::clone " +clone() -> Material * + +Create a duplicate of the Material. + +Returns +------- +a pointer to the clone +"; + +%feature("docstring") Material::getSigmaFByGroup " +getSigmaFByGroup(int group) -> FP_PRECISION + +Get the Material's fission cross section for some energy group. + +Parameters +---------- +* group : + the energy group + +Returns +------- +the fission cross section +"; + +%feature("docstring") Material::setSigmaF " +setSigmaF(double *xs, int num_groups) + +Set the Material's array of fission cross-sections. + +This method is a helper function to allow OpenMOC users to assign the Material's nuclear +data in Python. A user must initialize a NumPy array of the correct size (e.g., a float64 +array the length of the number of energy groups) as input to this function. This function +then fills the NumPy array with the data values for the Material's fission cross-sections. +An example of how this function might be called in Python is as follows: + + +Parameters +---------- +* xs : + the array of fission cross-sections +* num_groups : + the number of energy groups +"; + +%feature("docstring") Material::toString " +toString() -> std::string + +Converts this Material's attributes to a character array representation. + +The character array returned includes the user-defined ID, and each of the absorption, +total, fission, nu multiplied by fission and scattering cross-sections and chi for all +energy groups. + +Returns +------- +character array of this Material's attributes +"; + +%feature("docstring") Material::buildFissionMatrix " +buildFissionMatrix() + +Builds the fission matrix from chi and the fission cross-section. + +The fission matrix is constructed as the outer product of the chi and fission cross- +section vectors. This routine is intended for internal use and is called by the Solver at +runtime. +"; + +%feature("docstring") Material::getId " +getId() const -> int + +Return the Material's user-defined ID. + +Returns +------- +the Material's user-defined ID +"; + +%feature("docstring") Material::setSigmaSByGroup " +setSigmaSByGroup(double xs, int origin, int destination) + +Set the Material's scattering cross-section for some energy group. + +Parameters +---------- +* xs : + the scattering cross-section +* origin : + the column index in the scattering matrix +* destination : + the row index in the scattering matrix +"; + +%feature("docstring") Material::setSigmaS " +setSigmaS(double *xs, int num_groups) + +Set the Material's 2D array of scattering cross-sections. + +The array should be passed to OpenMOC as a 1D array in column-major order. This assumes +the standard convention, where column index is the origin group and the row index is the +destination group. That is, the array should be ordered as follows: 1 -> 1 1 -> 2 1 -> 3 +... 2 -> 1 2 -> 2 ... + +Note that if the scattering matrix is defined in NumPy by the standard convention, +\"flat\" will put the matrix into row major order. Thus, one should transpose the matrix +before flattening. + +For cache efficiency, the transpose of the input is actually stored in OpenMOC. + +This method is a helper function to allow OpenMOC users to assign the Material's nuclear +data in Python. A user must initialize a NumPy array of the correct size (e.g., a float64 +array the length of the square of the number of energy groups) as input to this function. +This function then fills the NumPy array with the data values for the Material's +scattering cross-sections. An example of how this function might be called in Python is as +follows: + + +Parameters +---------- +* xs : + the array of scattering cross-sections +* num_groups_squared : + the number of energy groups squared +"; + +%feature("docstring") Material::getFissionMatrix " +getFissionMatrix() -> FP_PRECISION * + +Return the array of the Material's fission matrix. + +Returns +------- +the pointer to the Material's fission matrix array +"; + +%feature("docstring") Material::setSigmaT " +setSigmaT(double *xs, int num_groups) + +Set the Material's array of total cross-sections. + +This method is a helper function to allow OpenMOC users to assign the Material's nuclear +data in Python. A user must initialize a NumPy array of the correct size (e.g., a float64 +array the length of the number of energy groups) as input to this function. This function +then fills the NumPy array with the data values for the Material's total cross-sections. +An example of how this function might be called in Python is as follows: + + + + NOTE: This routine will override an zero-valued cross-sections + (e.g., in void or gap regions) with a minimum value of 1E-10 to + void numerical issues in the MOC solver. + +Parameters +---------- +* xs : + the array of total cross-sections +* num_groups : + the number of energy groups +"; + +%feature("docstring") Material::isDataAligned " +isDataAligned() -> bool + +Returns true if the data is vector aligned, false otherwise (default). + +Returns +------- +Whether or not the Material's data is vector aligned +"; + +%feature("docstring") Material::setNumEnergyGroups " +setNumEnergyGroups(const int num_groups) + +Set the number of energy groups for this Material. + +Parameters +---------- +* num_groups : + the number of energy groups. +"; + +%feature("docstring") Material::alignData " +alignData() + +Reallocates the Material's cross-section data structures along word-aligned boundaries. + +This method is used to assist with SIMD auto-vectorization of the MOC routines in the +Solver classes. Rather than using the assigned number of energy groups, this method adds +\"dummy\" energy groups such that the total number of groups is some multiple of +VEC_LENGTH (typically 4, 8, or 16). As a result, the SIMD-vectorized Solver subclasses can +break up loops over energy groups in such a way to \"expose\" the SIMD nature of the +algorithm. +"; + +%feature("docstring") Material::getName " +getName() const -> char * + +Return the user-defined name of the Material. + +Returns +------- +the Material name +"; + +%feature("docstring") Material::printString " +printString() + +Prints a string representation of all of the Material's attributes to the console. +"; + +%feature("docstring") Material::~Material " +~Material() + +Destructor deletes all cross-section data structures from memory. +"; + +%feature("docstring") Material::getSigmaSByGroup " +getSigmaSByGroup(int origin, int destination) -> FP_PRECISION + +Get the Material's scattering cross section for some energy group. + +Parameters +---------- +* origin : + the incoming energy group +* destination : + the outgoing energy group + +Returns +------- +the scattering cross section +"; + +%feature("docstring") Material::getNumInstances " +getNumInstances() -> int + +Return the number of instances of this Material in the Geometry. + +The number of instances of this Material in the Geometry is determined during track +generation. + +Returns +------- +the number of material instances +"; + +%feature("docstring") Material::getNuSigmaFByGroup " +getNuSigmaFByGroup(int group) -> FP_PRECISION + +Get the Material's nu-fission cross section for some energy group. + +Parameters +---------- +* group : + the energy group + +Returns +------- +the nu-fission cross section +"; + +%feature("docstring") Material::getNumEnergyGroups " +getNumEnergyGroups() const -> int + +Returns the number of energy groups for this Material's nuclear data. + +Returns +------- +the number of energy groups +"; + +%feature("docstring") Material::isFissionable " +isFissionable() -> bool + +Returns whether or not the Material contains a fissionable (non-zero) fission cross- +section. + +Returns +------- +true if fissionable, false otherwise +"; + +%feature("docstring") Material::setNumInstances " +setNumInstances(int num_instances) + +Set the number of instances of this Material. + +Parameters +---------- +* num_instances : + the number of instances of this Material in the Geometry +"; + +%feature("docstring") Material::getFissionMatrixByGroup " +getFissionMatrixByGroup(int origin, int destination) -> FP_PRECISION + +Get the Material's fission matrix for some energy group. + +Parameters +---------- +* origin : + the incoming energy group $ E_{0} $ +* destination : + the outgoing energy group $ E_{1} $ + +Returns +------- +the fission matrix entry $ \\nu\\Sigma_{f}(E_{0}) * \\chi(E_{1})$ +"; + +%feature("docstring") Material::getVolume " +getVolume() -> double + +Return the aggregate volume/area of all instances of this Material. + +The volume/area of the Material is computed from track segments which overlap this +Material during track generation. + +Returns +------- +the volume/area of the Material +"; + +%feature("docstring") Material::setName " +setName(const char *name) + +Sets the name of the Material. + +Parameters +---------- +* name : + the Material name string +"; + +%feature("docstring") Material::incrementNumInstances " +incrementNumInstances() + +Increment the number of instances of this Material. + +This routine is called by the TrackGenerator during track generation and segmentation. +"; + +%feature("docstring") Material::getChi " +getChi() -> FP_PRECISION * + +Return the array of the Material's chi $ \\chi $. + +Returns +------- +the pointer to the Material's array of chi $ \\chi $ values +"; + +%feature("docstring") Material::setNuSigmaF " +setNuSigmaF(double *xs, int num_groups) + +Set the Material's array of fission cross-sections multiplied by $ \\nu $. + +Parameters +---------- +* xs : + the array of fission cross-sections multiplied by nu $ \\nu $ +* num_groups : + the number of energy groups +"; + +%feature("docstring") Material::setSigmaTByGroup " +setSigmaTByGroup(double xs, int group) + +Set the Material's total cross-section for some energy group. + +Parameters +---------- +* xs : + the total cross-section +* group : + the energy group +"; + +%feature("docstring") Material::Material " +Material(int id=0, const char *name=\"\") + +Constructor sets the ID and unique ID for the Material. + +Parameters +---------- +* id : + the user-specified optional Material ID +* name : + the user-specified optional Material name +"; + +%feature("docstring") Material::incrementVolume " +incrementVolume(double volume) + +Increment the volume/area of the Material by some amount. + +This routine is called by the TrackGenerator during track generation and segmentation. + +Parameters +---------- +* volume : + the amount to increment the current volume by +"; + +%feature("docstring") Material::setVolume " +setVolume(double volume) + +Set the volume/area of the Material. + +Parameters +---------- +* volume : + the volume/area of the Material +"; + +%feature("docstring") Material::getNumVectorGroups " +getNumVectorGroups() -> int + +Returns the rounded up number of energy groups to fill an integral number of vector +lengths. + +Returns +------- +The number of vector-aligned energy groups +"; + +%feature("docstring") Material::getSigmaT " +getSigmaT() -> FP_PRECISION * + +Return the array of the Material's total cross-sections. + +Returns +------- +the pointer to the Material's array of total cross-sections +"; + +%feature("docstring") Material::getSigmaS " +getSigmaS() -> FP_PRECISION * + +Return the array of the Material's scattering cross-section matrix. + +Returns +------- +the pointer to the Material's array of scattering cross-sections +"; + +%feature("docstring") Material::transposeProductionMatrices " +transposeProductionMatrices() + +Transposes the scattering and fission matrices. + +This routine is used by the Solver when performing adjoint flux caclulations. +"; + +%feature("docstring") Material::setNuSigmaFByGroup " +setNuSigmaFByGroup(double xs, int group) + +Set the Material's fission cross-section multiplied by $ \\nu $ for some energy group. + +This method is a helper function to allow OpenMOC users to assign the Material's nuclear +data in Python. A user must initialize a NumPy array of the correct size (e.g., a float64 +array the length of the number of energy groups) as input to this function. This function +then fills the NumPy array with the data values for the Material's nu*fission cross- +sections. An example of how this function might be called in Python is as follows: + + +Parameters +---------- +* xs : + the fission cross-section multiplied by nu $ \\nu $ +* group : + the energy group +"; + +%feature("docstring") Material::setSigmaFByGroup " +setSigmaFByGroup(double xs, int group) + +Set the Material's fission cross-section for some energy group. + +Parameters +---------- +* xs : + the fission cross-section +* group : + the energy group +"; + +%feature("docstring") Material::setChi " +setChi(double *xs, int num_groups) + +Set the Material's array of chi $ \\chi $ values. + +This method is a helper function to allow OpenMOC users to assign the Material's nuclear +data in Python. A user must initialize a NumPy array of the correct size (e.g., a float64 +array the length of the number of energy groups) as input to this function. This function +then fills the NumPy array with the data values for the Material's chi distribution. An +example of how this function might be called in Python is as follows: + + +Parameters +---------- +* xs : + the array of chi $ \\chi $ values +* num_groups : + the number of energy groups +"; + +%feature("docstring") Material::getSigmaF " +getSigmaF() -> FP_PRECISION * + +Return the array of the Material's fission cross-sections. + +Returns +------- +the pointer to the Material's array of fission cross-sections +"; + +%feature("docstring") Material::getSigmaTByGroup " +getSigmaTByGroup(int group) -> FP_PRECISION + +Get the Material's total cross section for some energy group. + +Parameters +---------- +* group : + the energy group + +Returns +------- +the total cross section +"; + +%feature("docstring") Material::getNuSigmaF " +getNuSigmaF() -> FP_PRECISION * + +Return the array of the Material's fission cross-sections multiplied by nu $ \\nu $. + +Returns +------- +the pointer to the Material's array of fission cross-sections multiplied by nu $ \\nu $ +"; + +// File: classMatrix.xml + + +%feature("docstring") Matrix " +"; + +%feature("docstring") Matrix::getNNZ " +getNNZ() -> int + +Get the number of non-zero values in the matrix. + +Returns +------- +The number of non-zero values in the matrix. +"; + +%feature("docstring") Matrix::printString " +printString() + +Print the matrix object to the log file. +"; + +%feature("docstring") Matrix::getNumRows " +getNumRows() -> int + +Get the number of rows in the matrix. + +Returns +------- +The number of rows in the matrix. +"; + +%feature("docstring") Matrix::getA " +getA() -> FP_PRECISION * + +Get the A component of the CSR form of the matrix object. + +Returns +------- +A pointer to the A component of the CSR form matrix object. +"; + +%feature("docstring") Matrix::incrementValue " +incrementValue(int cell_from, int group_from, int cell_to, int group_to, FP_PRECISION val) + +Increment a value in the matrix. This method takes a cell and group of origin (cell/group +from) and cell and group of destination (cell/group to) and floating point value. The +origin and destination are used to compute the row and column in the matrix. If a value +exists for the row/column, the value is incremented by val; otherwise, it is set to val. + +Parameters +---------- +* cell_from : + The origin cell. +* group_from : + The origin group. +* cell_to : + The destination cell. +* group_from : + The destination group. +* val : + The value used to increment the row/column location. +"; + +%feature("docstring") Matrix::getValue " +getValue(int cell_from, int group_from, int cell_to, int group_to) -> FP_PRECISION + +Get a value in the matrix. This method takes a cell and group of origin (cell/group from) +and cell and group of destination (cell/group to). The origin and destination are used to +compute the row and column in the matrix. The value at the location specified by the +row/column is returned. + +Parameters +---------- +* cell_from : + The origin cell. +* group_from : + The origin group. +* cell_to : + The destination cell. +* group_from : + The destination group. + +Returns +------- +The value at the corresponding row/column location. +"; + +%feature("docstring") Matrix::getDiag " +getDiag() -> FP_PRECISION * + +Get the diagonal component of the matrix object. + +Returns +------- +A pointer to the diagonal component of the matrix object. +"; + +%feature("docstring") Matrix::getIA " +getIA() -> int * + +Get the IA component of the CSR form of the matrix object. + +Returns +------- +A pointer to the IA component of the CSR form matrix object. +"; + +%feature("docstring") Matrix::getNumGroups " +getNumGroups() -> int + +Get the number of groups in each cell. + +Returns +------- +The number of groups in each cell. +"; + +%feature("docstring") Matrix::setValue " +setValue(int cell_from, int group_from, int cell_to, int group_to, FP_PRECISION val) + +Set a value in the matrix. This method takes a cell and group of origin (cell/group from) +and cell and group of destination (cell/group to) and floating point value. The origin and +destination are used to compute the row and column in the matrix. The location specified +by the row/column is set to val. + +Parameters +---------- +* cell_from : + The origin cell. +* group_from : + The origin group. +* cell_to : + The destination cell. +* group_from : + The destination group. +* val : + The value used to set the row/column location. +"; + +%feature("docstring") Matrix::Matrix " +Matrix(omp_lock_t *cell_locks, int num_x=1, int num_y=1, int num_groups=1) + +Constructor initializes Matrix as a list of lists and sets the matrix dimensions. The +matrix object uses a \"lists of lists\" structure (implemented as a map of lists) to allow +for easy setting and incrementing of the values in the object. When the matrix is needed +to perform linear algebra operations, it is converted to compressed row storage (CSR) +form. The matrix is ordered by cell (as opposed to by group) on the outside. Locks are +used to make the matrix thread-safe against concurrent writes the same value. One lock +locks out multiple rows of the matrix at a time reprsenting multiple groups in the same +cell. + +Parameters +---------- +* cell_locks : + Omp locks for atomic cell operations +* num_x : + The number of cells in the x direction. +* num_y : + The number of cells in the y direction. +* num_groups : + The number of energy groups in each cell. +"; + +%feature("docstring") Matrix::getJA " +getJA() -> int * + +Get the JA component of the CSR form of the matrix object. + +Returns +------- +A pointer to the JA component of the CSR form matrix object. +"; + +%feature("docstring") Matrix::transpose " +transpose() + +Transpose the matrix in place. +"; + +%feature("docstring") Matrix::clear " +clear() + +Clear all values in the matrix list of lists. +"; + +%feature("docstring") Matrix::~Matrix " +~Matrix() + +Destructor clears list of lists and deletes the arrays used to represent the matrix in CSR +form. +"; + +%feature("docstring") Matrix::getCellLocks " +getCellLocks() -> omp_lock_t * + +Return the array of cell locks for atomic cell operations. + +Returns +------- +an array of cell locks +"; + +%feature("docstring") Matrix::getNumX " +getNumX() -> int + +Get the number of cells in the x dimension. + +Returns +------- +The number of cells in the x dimension. +"; + +%feature("docstring") Matrix::getNumY " +getNumY() -> int + +Get the number of cells in the y dimension. + +Returns +------- +The number of cells in the y dimension. +"; + +// File: structmultiplyByConstant.xml + + +%feature("docstring") multiplyByConstant " + +A functor to multiply all elements in a Thrust vector by a constant. + +Parameters +---------- +* constant : + the constant to multiply the vector + +Attributes +---------- +* constant : const T +"; + +%feature("docstring") multiplyByConstant::multiplyByConstant " +multiplyByConstant(T constant) + +Constructor for the functor. + +Parameters +---------- +* constant : + to multiply each element in a Thrust vector +"; + +// File: structFixedHashMap_1_1node.xml + +// File: structParallelHashMap_1_1paddedPointer.xml + +// File: classParallelHashMap.xml + + +%feature("docstring") ParallelHashMap " + +A thread-safe hash map supporting insertion and lookup operations. + +The ParallelHashMap class is built on top of the FixedHashMap class, supporting insertion +and lookup operations but not deletion as deletion is not needed in the OpenMOC +application. This hash table uses chaining for collisions, as defined in FixedHashMap. It +offers lock free lookups in O(1) time on average and fine-grained locking for insertions +in O(1) time on average as well. Resizing is conducted periodically during inserts, +although the starting table size can be chosen to limit the number of resizing operations. + +C++ includes: src/ParallelHashMap.h +"; + +%feature("docstring") ParallelHashMap::values " +values() -> V * + +Returns an array of the values in the underlying table. + +All buckets are scanned in order to form a list of all values present in the table and +then the list is returned. Threads announce their presence to ensure table memory is not +freed during access. WARNING: The user is responsible for freeing the allocated memory +once the array is no longer needed. + +Returns +------- +an array of values in the map whose length is the number of key/value pairs in the table. +"; + +%feature("docstring") ParallelHashMap::insert_and_get_count " +insert_and_get_count(K key, V value) -> int + +Insert a given key/value pair into the parallel hash map and return the order number. + +First the underlying table is checked to determine if a resize should be conducted. Then, +the table is checked to see if it already contains the key. If so, the key/value pair is +not inserted and the function returns. Otherwise, the lock of the associated bucket is +acquired and the key/value pair is added to the bucket. + +Parameters +---------- +* key : + key of the key/value pair to be inserted +* value : + value of the key/value pair to be inserted + +Returns +------- +order number in which the key/value pair was inserted, -1 if it already exists +"; + +%feature("docstring") ParallelHashMap::size " +size() -> size_t + +Returns the number of key/value pairs in the underlying table. + +Returns +------- +number of key/value pairs in the map +"; + +%feature("docstring") ParallelHashMap::ParallelHashMap " +ParallelHashMap(size_t M=64, size_t L=64) + +Constructor generates initial underlying table as a fixed-sized hash map and intializes +concurrency structures. +"; + +%feature("docstring") ParallelHashMap::print_buckets " +print_buckets() + +Prints the contents of each bucket to the screen. + +All buckets are scanned and the contents of the buckets are printed, which are pointers to +linked lists. If the pointer is NULL suggesting that the linked list is empty, NULL is +printed to the screen. Threads announce their presence to ensure table memory is not freed +during access. +"; + +%feature("docstring") ParallelHashMap::update " +update(K key, V value) + +Updates the value associated with a key in the parallel hash map. + +The thread first acquires the lock for the bucket associated with the key is acquired, +then the linked list in the bucket is searched for the key. If the key is not found, an +exception is returned. When the key is found, the value is updated and the lock is +released. + +Parameters +---------- +* key : + the key of the key/value pair to be updated +* value : + the new value for the key/value pair +"; + +%feature("docstring") ParallelHashMap::keys " +keys() -> K * + +Returns an array of the keys in the underlying table. + +All buckets are scanned in order to form a list of all keys present in the table and then +the list is returned. Threads announce their presence to ensure table memory is not freed +during access. WARNING: The user is responsible for freeing the allocated memory once the +array is no longer needed. + +Returns +------- +an array of keys in the map whose length is the number of key/value pairs in the table. +"; + +%feature("docstring") ParallelHashMap::insert " +insert(K key, V value) + +Insert a given key/value pair into the parallel hash map. + +First the underlying table is checked to determine if a resize should be conducted. Then, +the table is checked to see if it already contains the key. If so, the key/value pair is +not inserted and the function returns. Otherwise, the lock of the associated bucket is +acquired and the key/value pair is added to the bucket. + +Parameters +---------- +* key : + key of the key/value pair to be inserted +* value : + value of the key/value pair to be inserted +"; + +%feature("docstring") ParallelHashMap::clear " +clear() + +Clears all key/value pairs form the hash table. +"; + +%feature("docstring") ParallelHashMap::~ParallelHashMap " +~ParallelHashMap() + +Destructor frees memory associated with fixed-sized hash map and concurrency structures. +"; + +%feature("docstring") ParallelHashMap::num_locks " +num_locks() -> size_t + +Returns the number of locks in the parallel hash map. + +Returns +------- +number of locks in the map +"; + +%feature("docstring") ParallelHashMap::contains " +contains(K key) -> bool + +Determine whether the parallel hash map contains a given key. + +First the thread accessing the table announces its presence and which table it is reading. +Then the linked list in the bucket associated with the key is searched without setting any +locks to determine whether the key is present. When the thread has finished accessing the +table, the announcement is reset to NULL. The announcement ensures that the data in the +map is not freed during a resize until all threads have finished accessing the map. + +Parameters +---------- +* key : + key to be searched + +Returns +------- +boolean value referring to whether the key is contained in the map +"; + +%feature("docstring") ParallelHashMap::bucket_count " +bucket_count() -> size_t + +Returns the number of buckets in the underlying table. + +Returns +------- +number of buckets in the map +"; + +%feature("docstring") ParallelHashMap::at " +at(K key) -> V + +Determine the value associated with a given key. + +This function follows the same algorithm as except that the value associated +with the searched key is returned. First the thread accessing the table acquires the lock +corresponding with the associated bucket based on the key. Then the linked list in the +bucket is searched for the key. An exception is thrown if the key is not found. When the +thread has finished accessing the table, it releases the lock. + +Parameters +---------- +* key : + key to be searched + +Returns +------- +value associated with the key +"; + +// File: classPlane.xml + + +%feature("docstring") Plane " + +Represents a Plane perpendicular to the xy-plane. + +C++ includes: src/Surface.h +"; + +%feature("docstring") Plane::getMaxZ " +getMaxZ(int halfspace) -> double + +Returns the maximum z value of INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum z value of INFINITY +"; + +%feature("docstring") Plane::getMaxX " +getMaxX(int halfspace) -> double + +Returns the maximum x value of INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum x value of INFINITY +"; + +%feature("docstring") Plane::getMaxY " +getMaxY(int halfspace) -> double + +Returns the maximum y value of INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum y value of INFINITY +"; + +%feature("docstring") Plane::toString " +toString() -> std::string + +Converts this Plane's attributes to a character array. + +The character array returned conatins the type of Plane (ie, PLANE) and the A, B, and C +coefficients in the quadratic Surface equation. + +Returns +------- +a character array of this Plane's attributes +"; + +%feature("docstring") Plane::getA " +getA() -> double + +Returns the A coefficient multiplying x in the surface equation. + +Returns +------- +the value for the A coefficient +"; + +%feature("docstring") Plane::getC " +getC() -> double + +Returns the C coefficient multiplying z in the surface equation. + +Returns +------- +the value for the C coefficient +"; + +%feature("docstring") Plane::getB " +getB() -> double + +Returns the B coefficient multiplying y in the surface equation. + +Returns +------- +the value for the B coefficient +"; + +%feature("docstring") Plane::getD " +getD() -> double + +Returns the D constant coefficient. + +Returns +------- +the value for the D coefficient +"; + +%feature("docstring") Plane::getMinX " +getMinX(int halfspace) -> double + +Returns the minimum x value of -INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum x value of -INFINITY +"; + +%feature("docstring") Plane::getMinY " +getMinY(int halfspace) -> double + +Returns the minimum y value of -INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum y value of -INFINITY +"; + +%feature("docstring") Plane::getMinZ " +getMinZ(int halfspace) -> double + +Returns the minimum z value of -INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum z value of -INFINITY +"; + +%feature("docstring") Plane::Plane " +Plane(const double A, const double B, const double C, const double D, const int id=0, + const char *name=\"\") + +Constructor. + +Parameters +---------- +* A : + the first coefficient in $ A * x + B * y + C * z + D = 0 $ +* B : + the second coefficient in $ A * x + B * y + C * z + D = 0 $ +* C : + the third coefficient in $ A * x + B * y + C * z + D = 0 $ +* D : + the fourth coefficient in $ A * x + B * y + C * z + D = 0 $ +* id : + the optional Surface ID +* name : + the optional name of the Surface +"; + +%feature("docstring") Plane::evaluate " +evaluate(const Point *point) const -> double + +Evaluate a Point using the Plane's quadratic Surface equation. + +Parameters +---------- +* point : + a pointer to the Point of interest + +Returns +------- +the value of Point in the Plane's quadratic equation +"; + +%feature("docstring") Plane::intersection " +intersection(Point *point, double angle, Point *points) -> int + +Finds the intersection Point with this Plane from a given Point and trajectory defined by +an angle. + +Parameters +---------- +* point : + pointer to the Point of interest +* angle : + the angle defining the trajectory in radians +* points : + pointer to a Point to store the intersection Point + +Returns +------- +the number of intersection Points (0 or 1) +"; + +// File: classPoint.xml + + +%feature("docstring") Point " + +Class to represent a 3D point in space. + +C++ includes: src/Point.h +"; + +%feature("docstring") Point::toString " +toString() -> std::string + +Converts this Point to a character representation of its attributes. + +The character array includes the x-coordinate, y-coordinate, and z-coordinate + +Returns +------- +a character array of this Point's attributes +"; + +%feature("docstring") Point::getY " +getY() const -> double + +Returns this Point's y-coordinate. + +Returns +------- +the y-coordinate +"; + +%feature("docstring") Point::getX " +getX() const -> double + +Returns this Point's x-coordinate. + +Returns +------- +the x-coordinate +"; + +%feature("docstring") Point::getZ " +getZ() const -> double + +Returns this Point's z-coordinate. + +Returns +------- +the z-coordinate +"; + +%feature("docstring") Point::Point " +Point() + +Constructor initializes an empty Point. +"; + +%feature("docstring") Point::setX " +setX(const double x) + +Set the Point's x-coordinate. + +Parameters +---------- +* x : + the new x-coordinate +"; + +%feature("docstring") Point::setZ " +setZ(const double z) + +Set the Point's z-coordinate. + +Parameters +---------- +* z : + the new z-coordinate +"; + +%feature("docstring") Point::setY " +setY(const double y) + +Set the Point's y-coordinate. + +Parameters +---------- +* y : + the new y-coordinate +"; + +%feature("docstring") Point::distanceToPoint " +distanceToPoint(const Point *point) -> double + +Compute the distance from this Point to another Point of interest. + +Parameters +---------- +* point : + a pointer to the Point of interest + +Returns +------- +distance to the Point of interest +"; + +%feature("docstring") Point::~Point " +~Point() + +Destructor. +"; + +%feature("docstring") Point::setCoords " +setCoords(const double x, const double y, const double z) + +Initializes a Point with two-dimensional coordinates. + +Parameters +---------- +* x : + x-coordinate +* y : + y-coordinate +"; + +// File: classPolarQuad.xml + + +%feature("docstring") PolarQuad " + +The arbitrary polar quadrature parent class. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") PolarQuad::PolarQuad " +PolarQuad() + +Dummy constructor sets the default number of angles to zero. +"; + +%feature("docstring") PolarQuad::initialize " +initialize() + +Dummy routine to initialize the polar quadrature. + +The parent class routine simply checks that the number of polar angles has been set by the +user and returns; +"; + +%feature("docstring") PolarQuad::getWeights " +getWeights() -> FP_PRECISION * + +Returns a pointer to the PolarQuad's array of polar weights. + +Returns +------- +a pointer to the polar weights array +"; + +%feature("docstring") PolarQuad::setWeights " +setWeights(double *weights, int num_polar) + +Set the PolarQuad's array of weights for each angle. + +This method is a helper function to allow OpenMOC users to assign the PolarQuad's angular +weights in Python. A user must initialize a NumPy array of the correct size (e.g., a +float64 array the length of the number of polar angles) as input to this function. This +function then fills the NumPy array with the data values for the PolarQuad's weights. An +example of how this function might be called in Python is as follows: + + +Parameters +---------- +* weights : + the array of weights for each polar angle +* num_polar : + the number of polar angles +"; + +%feature("docstring") PolarQuad::getQuadratureType " +getQuadratureType() -> quadratureType + +Returns the quadrature type. + +Returns +------- +an enum corresponding to the quadrature type +"; + +%feature("docstring") PolarQuad::setSinThetas " +setSinThetas(double *sin_thetas, int num_polar) + +Set the PolarQuad's array of sines of each polar angle. + +This method is a helper function to allow OpenMOC users to assign the PolarQuad's sin +thetas in Python. A user must initialize a NumPy array of the correct size (e.g., a +float64 array the length of the number of polar angles) as input to this function. This +function then fills the NumPy array with the data values for the PolarQuad's sin thetas. +An example of how this function might be called in Python is as follows: + + +Parameters +---------- +* sin_thetas : + the array of sines of each polar angle +* num_polar : + the number of polar angles +"; + +%feature("docstring") PolarQuad::getMultiples " +getMultiples() -> FP_PRECISION * + +Returns a pointer to the PolarQuad's array of multiples. + +A multiple is the sine of a polar angle multiplied by its weight. + +Returns +------- +a pointer to the multiples array +"; + +%feature("docstring") PolarQuad::getSinTheta " +getSinTheta(const int n) const -> FP_PRECISION + +Returns the $ sin(\\theta)$ value for a particular polar angle. + +Parameters +---------- +* n : + index of the polar angle of interest + +Returns +------- +the value of $ \\sin(\\theta) $ for this polar angle +"; + +%feature("docstring") PolarQuad::getSinThetas " +getSinThetas() -> FP_PRECISION * + +Returns a pointer to the PolarQuad's array of $ sin\\theta_{p} $. + +Returns +------- +a pointer to the array of $ sin\\theta_{p} $ +"; + +%feature("docstring") PolarQuad::getNumPolarAngles " +getNumPolarAngles() const -> int + +Returns the number of polar angles. + +Returns +------- +the number of polar angles +"; + +%feature("docstring") PolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles +"; + +%feature("docstring") PolarQuad::getMultiple " +getMultiple(const int n) const -> FP_PRECISION + +Returns the multiple value for a particular polar angle. + +A multiple is the sine of a polar angle multiplied by its weight. + +Parameters +---------- +* n : + index of the polar angle of interest + +Returns +------- +the value of the sine of the polar angle multiplied with its weight +"; + +%feature("docstring") PolarQuad::toString " +toString() -> std::string + +Converts this Quadrature to a character array of its attributes. + +The character array includes the number of polar angles, the the values of the sine and +weight of each polar angle, and the product of the sine and weight of each polar angle. + +Returns +------- +a character array of the PolarQuad's attributes +"; + +%feature("docstring") PolarQuad::~PolarQuad " +~PolarQuad() + +Destructor deletes arrray of sines of the polar angles, the weights of the polar angles +and the products of the sines and weights. +"; + +%feature("docstring") PolarQuad::getWeight " +getWeight(const int n) const -> FP_PRECISION + +Returns the weight value for a particular polar angle. + +Parameters +---------- +* n : + index of the polar angle of interest + +Returns +------- +the weight for a polar angle +"; + +// File: structsecond__t.xml + + +%feature("docstring") second_t " + +A helper struct for the Universe::findCell() method. + +This is used to insert a Universe's Cells to the back of a vector of neighbor Cells in +Universe::findCell() routine. This works in symbiosis with the pair_second method template +defined below. + +C++ includes: Universe.h +"; + +// File: structsegment.xml + + +%feature("docstring") segment " + +A segment represents a line segment within a single flat source region along a track. + +Attributes +---------- +* _length : FP_PRECISION + The length of the segment (cm) + +* _material : Material * + A pointer to the material in which this segment resides + +* _region_id : int + The ID for flat source region in which this segment resides + +* _cmfd_surface_fwd : int + The ID for the mesh surface crossed by the Track end point + +* _cmfd_surface_bwd : int + The ID for the mesh surface crossed by the Track start point + +C++ includes: Track.h +"; + +%feature("docstring") segment::segment " +segment() + +Constructor initializes CMFD surfaces +"; + +// File: classSolver.xml + + +%feature("docstring") Solver " + +This is an abstract base class which different Solver subclasses implement for different +architectures or source iteration algorithms. + +C++ includes: src/Solver.h +"; + +%feature("docstring") Solver::setConvergenceThreshold " +setConvergenceThreshold(FP_PRECISION threshold) + +Sets the threshold for source/flux convergence. + +The default threshold for convergence is 1E-5. + +Parameters +---------- +* source_thresh : + the threshold for source/flux convergence +"; + +%feature("docstring") Solver::computeFlux " +computeFlux(int max_iters=1000, solverMode mode=FORWARD, bool only_fixed_source=true) + +Computes the scalar flux distribution by performing a series of transport sweeps. + +This is the main method exposed to the user through the Python interface to compute the +scalar flux distribution, e.g., for a fixed source calculation. This routine makes an +initial guess for scalar and boundary fluxes and performs transport sweep until +convergence. + +By default, this method will perform a maximum of 1000 transport sweeps with a 1E-5 +threshold on the average FSR scalar flux. These values may be freely modified by the user +at runtime. + +The only_fixed_source runtime parameter may be used to control the type of source +distribution used in the calculation. By default, this paramter is true and only the fixed +sources specified by the user will be considered. Alternatively, when the parameter is +false, the source will be computed as the scattering and fission sources resulting from a +previously computed flux distribution (e.g., an eigenvalue calculation) in addition to any +user-defined fixed sources. + +This method may be called by the user to compute the scalar flux for a fixed source +distribution from Python as follows: + + + + Alternatively, as described above, this method may be called by + the user in Python to compute the flux from a superposition of + fixed and / or eigenvalue sources as follows: + + +Parameters +---------- +* max_iters : + the maximum number of source iterations to allow +* mode : + the solution type (FORWARD or ADJOINT) +* only_fixed_source : + use only fixed sources (true by default) +"; + +%feature("docstring") Solver::countFissionableFSRs " +countFissionableFSRs() + +Counts the number of fissionable flat source regions. + +This routine is used by the Solver::computeEigenvalue(...) routine which uses the number +of fissionable FSRs to normalize the residual on the fission source distribution. +"; + +%feature("docstring") Solver::setExpPrecision " +setExpPrecision(FP_PRECISION precision) + +Set the precision, or maximum allowable approximation error, of the the exponential +interpolation table. + +By default, the precision is 1E-5 based on the analysis in Yamamoto's 2003 paper. + +Parameters +---------- +* precision : + the precision of the exponential interpolation table, +"; + +%feature("docstring") Solver::getTotalTime " +getTotalTime() -> double + +Returns the total time to converge the source (seconds). + +Returns +------- +the time to converge the source (seconds) +"; + +%feature("docstring") Solver::getTrackGenerator " +getTrackGenerator() -> TrackGenerator * + +Returns a pointer to the TrackGenerator. + +Returns +------- +a pointer to the TrackGenerator +"; + +%feature("docstring") Solver::setFixedSourceByCell " +setFixedSourceByCell(Cell *cell, int group, FP_PRECISION source) + +Assign a fixed source for a Cell and energy group. + +Parameters +---------- +* cell : + the Cell of interest +* group : + the energy group +* source : + the volume-averaged source in this group +"; + +%feature("docstring") Solver::computeFSRFissionSources " +computeFSRFissionSources()=0 + +Computes the total fission source for each FSR and energy group. +"; + +%feature("docstring") Solver::normalizeFluxes " +normalizeFluxes()=0 + +Normalizes all FSR scalar fluxes and Track boundary angular fluxes to the total fission +source (times $ \\nu $). +"; + +%feature("docstring") Solver::getFlux " +getFlux(int fsr_id, int group) -> FP_PRECISION + +Returns the scalar flux for some FSR and energy group. + +Parameters +---------- +* fsr_id : + the ID for the FSR of interest +* group : + the energy group of interest + +Returns +------- +the FSR scalar flux +"; + +%feature("docstring") Solver::Solver " +Solver(TrackGenerator *track_generator=NULL) + +Constructor initializes an empty Solver class with array pointers set to NULL. + +Parameters +---------- +* track_generator : + an optional pointer to a TrackGenerator object +"; + +%feature("docstring") Solver::getPolarQuad " +getPolarQuad() -> PolarQuad * + +Returns a pointer to the PolarQuad. + +Returns +------- +a pointer to the PolarQuad +"; + +%feature("docstring") Solver::getMaxOpticalLength " +getMaxOpticalLength() -> FP_PRECISION + +Get the maximum allowable optical length for a track segment. + +Returns +------- +The max optical length +"; + +%feature("docstring") Solver::computeEigenvalue " +computeEigenvalue(int max_iters=1000, solverMode mode=FORWARD, residualType + res_type=FISSION_SOURCE) + +Computes keff by performing a series of transport sweep and source updates. + +This is the main method exposed to the user through the Python interface to perform an +eigenvalue calculation. The method makes an initial guess for the scalar and boundary +fluxes and performs transport sweeps and source updates until convergence. + +By default, this method will perform a maximum of 1000 transport sweeps with a 1E-5 +threshold on the integrated FSR fission source. These values may be freely modified by the +user at runtime. + +The res_type parameter may be used to control the convergence criterion - SCALAR_FLUX, +TOTAL_SOURCE and FISSION_SOURCE (default) are all supported options in OpenMOC at this +time. + + +Parameters +---------- +* max_iters : + the maximum number of source iterations to allow +* mode : + the solution type (FORWARD or ADJOINT) +* res_type : + the type of residual used for the convergence criterion +"; + +%feature("docstring") Solver::isUsingExponentialInterpolation " +isUsingExponentialInterpolation() -> bool + +Returns whether the Solver uses linear interpolation to compute exponentials. + +Returns +------- +true if using linear interpolation to compute exponentials +"; + +%feature("docstring") Solver::setFluxes " +setFluxes(FP_PRECISION *in_fluxes, int num_fluxes)=0 +"; + +%feature("docstring") Solver::getFluxes " +getFluxes(FP_PRECISION *out_fluxes, int num_fluxes)=0 +"; + +%feature("docstring") Solver::getGeometry " +getGeometry() -> Geometry * + +Returns a pointer to the Geometry. + +Returns +------- +a pointer to the Geometry +"; + +%feature("docstring") Solver::setPolarQuadrature " +setPolarQuadrature(PolarQuad *polar_quad) + +Assign a PolarQuad object to the Solver. + +This routine allows use of a PolarQuad with any polar angle quadrature. Alternatively, +this routine may take in any subclass of the PolarQuad parent class, including TYPolarQuad +(default), LeonardPolarQuad, GLPolarQuad, etc. + +Users may assign a PolarQuad object to the Solver from Python script as follows: + + +Parameters +---------- +* polar_quad : + a pointer to a PolarQuad object +"; + +%feature("docstring") Solver::initializeSourceArrays " +initializeSourceArrays()=0 + +Allocates memory for FSR source arrays. +"; + +%feature("docstring") Solver::getNumPolarAngles " +getNumPolarAngles() -> int + +Returns the number of angles used for the polar quadrature. + +Returns +------- +the number of polar angles +"; + +%feature("docstring") Solver::setFixedSourceByFSR " +setFixedSourceByFSR(int fsr_id, int group, FP_PRECISION source) + +Assign a fixed source for a flat source region and energy group. + +Parameters +---------- +* fsr_id : + the flat source region ID +* group : + the energy group +* source : + the volume-averaged source in this group +"; + +%feature("docstring") Solver::computeSource " +computeSource(int max_iters=1000, solverMode mode=FORWARD, double k_eff=1.0, residualType + res_type=TOTAL_SOURCE) + +Computes the total source distribution by performing a series of transport sweep and +source updates. + +This is the main method exposed to the user through the Python interface to compute the +source distribution, e.g., for a fixed and/or external source calculation. This routine +makes an initial guess for the scalar and boundary fluxes and performs transport sweeps +and source updates until convergence. + +By default, this method will perform a maximum of 1000 transport sweeps with a 1E-5 +threshold on the integrated FSR total source. These values may be freely modified by the +user at runtime. + +The k_eff parameter may be used for fixed source calculations with fissionable material +(e.g., start-up in a reactor from a fixed external source). In this case, the user must +\"guess\" the critical eigenvalue to be be used to scale the fission source. + +The res_type parameter may be used to control the convergence criterion - SCALAR_FLUX, +TOTAL_SOURCE (default) and FISSION_SOURCE are all supported options in OpenMOC at this +time. + +This method may be called by the user from Python as follows: + + +Parameters +---------- +* max_iters : + the maximum number of source iterations to allow +* mode : + the solution type (FORWARD or ADJOINT) +* k_eff : + the sub/super-critical eigenvalue (default 1.0) +* res_type : + the type of residual used for the convergence criterion +"; + +%feature("docstring") Solver::flattenFSRFluxes " +flattenFSRFluxes(FP_PRECISION value)=0 + +Set the scalar flux for each FSR and energy group to some value. + +Parameters +---------- +* value : + the value to assign to each FSR scalar flux +"; + +%feature("docstring") Solver::getFSRVolume " +getFSRVolume(int fsr_id) -> FP_PRECISION + +Returns the calculated volume for a flat source region. + +Parameters +---------- +* fsr_id : + the flat source region ID of interest + +Returns +------- +the flat source region volume +"; + +%feature("docstring") Solver::initializeFixedSources " +initializeFixedSources() + +Assigns fixed sources assigned by Cell, Material to FSRs. + +Fixed sources assigned by Material +"; + +%feature("docstring") Solver::getKeff " +getKeff() -> FP_PRECISION + +Returns the converged eigenvalue $ k_{eff} $. + +Returns +------- +the converged eigenvalue $ k_{eff} $ +"; + +%feature("docstring") Solver::useExponentialIntrinsic " +useExponentialIntrinsic() + +Informs the Solver to use the exponential intrinsic exp(...) function to compute the +exponential in the transport equation. +"; + +%feature("docstring") Solver::computeResidual " +computeResidual(residualType res_type)=0 -> double + +Computes the residual between successive flux/source iterations. + +Parameters +---------- +* res_type : + the type of residual (FLUX, FISSION_SOURCE, TOTAL_SOURCE) + +Returns +------- +the total residual summed over FSRs and energy groups +"; + +%feature("docstring") Solver::transportSweep " +transportSweep()=0 + +This method performs one transport swep. +"; + +%feature("docstring") Solver::initializeMaterials " +initializeMaterials(solverMode mode=FORWARD) + +Initializes the Material fission matrices. + +In an adjoint calculation, this routine will transpose the scattering and fission matrices +in each material. + +Parameters +---------- +* mode : + the solution type (FORWARD or ADJOINT) +"; + +%feature("docstring") Solver::isUsingDoublePrecision " +isUsingDoublePrecision() -> bool + +Returns whether the solver is using double floating point precision. + +Returns +------- +true if using double precision float point arithmetic +"; + +%feature("docstring") Solver::getConvergenceThreshold " +getConvergenceThreshold() -> FP_PRECISION + +Returns the threshold for source/flux convergence. + +Returns +------- +the threshold for source/flux convergence +"; + +%feature("docstring") Solver::printTimerReport " +printTimerReport() + +Prints a report of the timing statistics to the console. +"; + +%feature("docstring") Solver::initializeCmfd " +initializeCmfd() + +Initializes a Cmfd object for acceleratiion prior to source iteration. + +Instantiates a dummy Cmfd object if one was not assigned to the Solver by the user and +initializes FSRs, materials, fluxes and the Mesh object. This method is for internal use +only and should not be called directly by the user. +"; + +%feature("docstring") Solver::setFixedSourceByMaterial " +setFixedSourceByMaterial(Material *material, int group, FP_PRECISION source) + +Assign a fixed source for a Material and energy group. + +Parameters +---------- +* material : + the Material of interest +* group : + the energy group +* source : + the volume-averaged source in this group +"; + +%feature("docstring") Solver::setMaxOpticalLength " +setMaxOpticalLength(FP_PRECISION max_optical_length) + +Set the maximum allowable optical length for a track segment. + +Parameters +---------- +* max_optical_length : + The max optical length +"; + +%feature("docstring") Solver::computeKeff " +computeKeff()=0 + +Compute $ k_{eff} $ from total fission and absorption rates in each FSR and energy group. +"; + +%feature("docstring") Solver::getFSRSource " +getFSRSource(int fsr_id, int group) -> FP_PRECISION + +Returns the source for some energy group for a flat source region. + +This is a helper routine used by the openmoc.process module. + +Parameters +---------- +* fsr_id : + the ID for the FSR of interest +* group : + the energy group of interest + +Returns +------- +the flat source region source +"; + +%feature("docstring") Solver::initializePolarQuadrature " +initializePolarQuadrature() + +Initializes a new PolarQuad object. + +Deletes memory old PolarQuad if one was previously allocated. +"; + +%feature("docstring") Solver::scatterTransportSweep " +scatterTransportSweep() + +This method performs one transport sweep using the scatter source. + +This is a helper routine used for Krylov subspace methods. +"; + +%feature("docstring") Solver::addSourceToScalarFlux " +addSourceToScalarFlux()=0 + +Add the source term contribution in the transport equation to the FSR scalar flux. +"; + +%feature("docstring") Solver::initializeFSRs " +initializeFSRs() + +Initializes the FSR volumes and Materials array. + +This method assigns each FSR a unique, monotonically increasing ID, sets the Material for +each FSR, and assigns a volume based on the cumulative length of all of the segments +inside the FSR. +"; + +%feature("docstring") Solver::setTrackGenerator " +setTrackGenerator(TrackGenerator *track_generator) + +Sets the Solver's TrackGenerator with characteristic Tracks. + +The TrackGenerator must already have generated Tracks and have used ray tracing to +segmentize them across the Geometry. This should be initated in Python prior to assigning +the TrackGenerator to the Solver: + + +Parameters +---------- +* track_generator : + a pointer to a TrackGenerator object +"; + +%feature("docstring") Solver::getNumIterations " +getNumIterations() -> int + +Returns the number of source iterations to converge the source. + +Returns +------- +the number of iterations +"; + +%feature("docstring") Solver::storeFSRFluxes " +storeFSRFluxes()=0 + +Stores the current scalar fluxes in the old scalar flux array. +"; + +%feature("docstring") Solver::zeroTrackFluxes " +zeroTrackFluxes()=0 + +Zero each Track's boundary fluxes for each energy group and polar angle in the \"forward\" +and \"reverse\" directions. +"; + +%feature("docstring") Solver::fissionTransportSweep " +fissionTransportSweep() + +This method performs one transport sweep using the fission source. + +This is a helper routine used for Krylov subspace methods. +"; + +%feature("docstring") Solver::~Solver " +~Solver() + +Destructor deletes arrays of boundary angular fluxes, scalar fluxes and sources for each +FSR and energy group. + +Deallocates memory for all arrays allocated for the Solver, including fluxes, sources, +quadrature weights, and exponential linear interpolation table. +"; + +%feature("docstring") Solver::computeFSRSources " +computeFSRSources()=0 + +Computes the total source (fission, scattering, fixed) for each FSR and energy group. +"; + +%feature("docstring") Solver::setGeometry " +setGeometry(Geometry *geometry) + +Sets the Geometry for the Solver. + +This is a private setter method for the Solver and is not intended to be called by the +user. + +Parameters +---------- +* geometry : + a pointer to a Geometry object +"; + +%feature("docstring") Solver::resetMaterials " +resetMaterials(solverMode mode=FORWARD) + +Returns the Material data to its original state. + +In an adjoint calculation, the scattering and fission matrices in each material are +transposed during initialization. This routine returns both matrices to their original +(FORWARD) state at the end of a calculation. + +Parameters +---------- +* mode : + the solution type (FORWARD or ADJOINT) +"; + +%feature("docstring") Solver::useExponentialInterpolation " +useExponentialInterpolation() + +Informs the Solver to use linear interpolation to compute the exponential in the transport +equation. +"; + +%feature("docstring") Solver::initializeExpEvaluator " +initializeExpEvaluator() + +Initializes new ExpEvaluator object to compute exponentials. +"; + +%feature("docstring") Solver::initializeFluxArrays " +initializeFluxArrays()=0 + +Initializes Track boundary angular and FSR scalar flux arrays. +"; + +%feature("docstring") Solver::computeFSRScatterSources " +computeFSRScatterSources()=0 + +Computes the total scattering source for each FSR and energy group. +"; + +%feature("docstring") Solver::computeFSRFissionRates " +computeFSRFissionRates(double *fission_rates, int num_FSRs)=0 + +Computes the volume-weighted, energy integrated fission rate in each FSR and stores them +in an array indexed by FSR ID. + +This is a helper method for SWIG to allow users to retrieve FSR fission rates as a NumPy +array. An example of how this method can be called from Python is as follows: + + +Parameters +---------- +* fission_rates : + an array to store the fission rates (implicitly passed in as a NumPy array from + Python) +* num_FSRs : + the number of FSRs passed in from Python +"; + +// File: structstrided__range_1_1stride__functor.xml + + +%feature("docstring") strided_range::stride_functor " + +Attributes +---------- +* stride : difference_type +"; + +%feature("docstring") strided_range::stride_functor::stride_functor " +stride_functor(difference_type stride) +"; + +// File: classstrided__range.xml + + +%feature("docstring") strided_range " +"; + +%feature("docstring") strided_range::end " +end(void) const -> iterator + +Get the last element in the iterator. + +Returns +------- +the last element in the iterator +"; + +%feature("docstring") strided_range::strided_range " +strided_range(Iterator first, Iterator last, difference_type stride) + +The strided iterator constructor. +"; + +%feature("docstring") strided_range::begin " +begin(void) const -> iterator + +Get the first element in the iterator. + +Returns +------- +the first element in the iterator +"; + +// File: classSurface.xml + + +%feature("docstring") Surface " + +Represents a general Surface in 3D. + +The Surface class and its subclasses are used to define the geometry for an OpenMOC +simulation using a constructive solid geometry (CSG) formalism. Surfaces are used during +ray tracing of charateristic tracks across the geometry. + +C++ includes: src/Surface.h +"; + +%feature("docstring") Surface::getUid " +getUid() const -> int + +Return the Surface's unique ID. + +Returns +------- +the Surface's unique ID +"; + +%feature("docstring") Surface::~Surface " +~Surface() + +Destructor. +"; + +%feature("docstring") Surface::getMaxY " +getMaxY(int halfspace)=0 -> double + +Returns the maximum y value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum y value +"; + +%feature("docstring") Surface::getMaxX " +getMaxX(int halfspace)=0 -> double + +Returns the maximum x value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum x value +"; + +%feature("docstring") Surface::Surface " +Surface(const int id=0, const char *name=\"\") + +Constructor assigns unique ID and user-defined ID for a Surface. + +Assigns a default boundary condition for this Surface to BOUNDARY_NONE. + +Parameters +---------- +* id : + an optional user-defined Surface ID +* name : + an optional user-defined Surface name +"; + +%feature("docstring") Surface::getMaxZ " +getMaxZ(int halfspace)=0 -> double + +Returns the maximum z value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the maximum z value +"; + +%feature("docstring") Surface::getMinZ " +getMinZ(int halfspace)=0 -> double + +Returns the minimum z value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum z value +"; + +%feature("docstring") Surface::getMinY " +getMinY(int halfspace)=0 -> double + +Returns the minimum y value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum y value +"; + +%feature("docstring") Surface::getMinX " +getMinX(int halfspace)=0 -> double + +Returns the minimum x value for one of this Surface's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the Surface to consider + +Returns +------- +the minimum x value +"; + +%feature("docstring") Surface::evaluate " +evaluate(const Point *point) const =0 -> double + +Evaluate a Point using the Surface's potential equation. + +This method returns the values $ f(x,y) $ for the potential function $f$ representing this +Surface. + +Parameters +---------- +* point : + a pointer to the Soint of interest + +Returns +------- +the value of Point in the Plane's potential equation. +"; + +%feature("docstring") Surface::getId " +getId() const -> int + +Return the Surface's user-defined ID. + +Returns +------- +the Surface's user-defined ID +"; + +%feature("docstring") Surface::getBoundaryType " +getBoundaryType() -> boundaryType + +Returns the type of boundary conditions for this Surface (REFLECTIVE, VACUUM or +BOUNDARY_NONE) + +Returns +------- +the type of boundary condition type for this Surface +"; + +%feature("docstring") Surface::addNeighborCell " +addNeighborCell(int halfspace, Cell *cell) + +Adds a neighbor Cell to this Surface's collection of neighbors. + +Parameters +---------- +* halfspace : + the +/-1 halfspace for the neighboring Cell +* cell : + a pointer to the neighboring Cell +"; + +%feature("docstring") Surface::isPointOnSurface " +isPointOnSurface(Point *point) -> bool + +Return true or false if a Point is on or off of a Surface. + +Parameters +---------- +* point : + pointer to the Point of interest + +Returns +------- +on (true) or off (false) the Surface +"; + +%feature("docstring") Surface::getMinDistance " +getMinDistance(LocalCoords *coords) -> double + +Finds the minimum distance to a Surface. + +Finds the miniumum distance to a Surface from a LocalCoords with a trajectory defined by +an angle to this Surface. If the trajectory will not intersect the Surface, returns +INFINITY. + +Parameters +---------- +* coords : + a pointer to a localcoords object + +Returns +------- +the minimum distance to the Surface +"; + +%feature("docstring") Surface::setBoundaryType " +setBoundaryType(const boundaryType boundary_type) + +Sets the boundary condition type (ie, VACUUM or REFLECTIVE) for this Surface. + +Parameters +---------- +* boundary_type : + the boundary condition type for this Surface +"; + +%feature("docstring") Surface::getSurfaceType " +getSurfaceType() -> surfaceType + +Return the type of Surface (ie, XPLANE, ZCYLINDER, etc). + +Returns +------- +the Surface type +"; + +%feature("docstring") Surface::getName " +getName() const -> char * + +Return the user-defined name of the Surface. + +Returns +------- +the Surface name +"; + +%feature("docstring") Surface::isCoordOnSurface " +isCoordOnSurface(LocalCoords *coord) -> bool + +Return true or false if a LocalCoord is on or off of a Surface. + +Parameters +---------- +* coord : + pointer to the LocalCoord of interest + +Returns +------- +on (true) or off (false) the Surface +"; + +%feature("docstring") Surface::toString " +toString()=0 -> std::string + +Converts this Surface's attributes to a character array. + +The character array returned conatins the type of Surface (ie, PLANE) and the coefficients +in the potential equation. + +Returns +------- +a character array of this Surface's attributes +"; + +%feature("docstring") Surface::printString " +printString() + +Prints a string representation of all of the Surface's objects to the console. +"; + +%feature("docstring") Surface::setName " +setName(const char *name) + +Sets the name of the Surface. + +Parameters +---------- +* name : + the Surface name string +"; + +%feature("docstring") Surface::intersection " +intersection(Point *point, double angle, Point *points)=0 -> int + +Finds the intersection Point with this Surface from a given Point and trajectory defined +by an angle. + +Parameters +---------- +* point : + pointer to the Point of interest +* angle : + the angle defining the trajectory in radians +* points : + pointer to a Point to store the intersection Point + +Returns +------- +the number of intersection Points (0 or 1) +"; + +// File: structsurface__halfspace.xml + + +%feature("docstring") surface_halfspace " + +A surface_halfspace represents a surface pointer with associated halfspace. + +Attributes +---------- +* _surface : Surface * + A pointer to the Surface object + +* _halfspace : int + The halfspace associated with this surface + +C++ includes: Cell.h +"; + +// File: classThis.xml + + +%feature("docstring") This " + +templated interface for a strided iterator over a Thrust device_vector on a GPU. + +This code is taken from the Thrust examples site on 1/20/2015: +https://github.com/thrust/thrust/blob/master/examples/strided_range.cu +"; + +// File: classTimer.xml + + +%feature("docstring") Timer " + +The Timer class is for timing and profiling regions of code. + +C++ includes: src/Timer.cpp +"; + +%feature("docstring") Timer::getTime " +getTime() -> double + +Returns the time elapsed from startTimer() to stopTimer(). + +Returns +------- +the elapsed time in seconds +"; + +%feature("docstring") Timer::recordSplit " +recordSplit(const char *msg) + +Records a message corresponding to a time for the current split. + +When this method is called it assumes that the Timer has been stopped and has the current +time for the process corresponding to the message. + +Parameters +---------- +* msg : + a msg corresponding to this time split +"; + +%feature("docstring") Timer::~Timer " +~Timer() + +Destructor. +"; + +%feature("docstring") Timer::Get " +Get() -> Timer * + +Returns a static instance of the Timer class. + +Returns +------- +a pointer to the static Timer class +"; + +%feature("docstring") Timer::printSplits " +printSplits() + +Prints the times and messages for each split to the console. + +This method will loop through all of the Timer's splits and print a formatted message +string (80 characters in length) to the console with the message and the time +corresponding to that message. +"; + +%feature("docstring") Timer::Timer " +Timer() + +Constructor sets the current split elapsed time to zero. +"; + +%feature("docstring") Timer::getSplit " +getSplit(const char *msg) -> double + +Returns the time associated with a particular split. + +If the split does not exist, returns 0. + +Parameters +---------- +* msg : + the message tag for the split + +Returns +------- +the time recorded for the split (seconds) +"; + +%feature("docstring") Timer::startTimer " +startTimer() + +Starts the Timer. + +This method is similar to starting a stopwatch. +"; + +%feature("docstring") Timer::stopTimer " +stopTimer() + +Stops the Timer. + +This method is similar to stopping a stopwatch. +"; + +%feature("docstring") Timer::clearSplit " +clearSplit(const char *msg) + +Clears the time split for this message and deletes the message's entry in the Timer's +splits log. + +Parameters +---------- +* msg : + the message tag for the split +"; + +%feature("docstring") Timer::clearSplits " +clearSplits() + +Clears all times split messages from the Timer. +"; + +// File: classTrack.xml + + +%feature("docstring") Track " + +A Track represents a characteristic line across the geometry. + +A Track has particular starting and ending points on the boundaries of the geometry and an +azimuthal angle. + +C++ includes: src/Track.h +"; + +%feature("docstring") Track::toString " +toString() -> std::string + +Convert this Track's attributes to a character array. + +The character array returned includes the Track's starting and ending coordinates, the +azimuthal angle and azimuthal weight. + +Returns +------- +a character array of this Track's attributes +"; + +%feature("docstring") Track::setAzimAngleIndex " +setAzimAngleIndex(const int index) + +Set the index for the Track's azimuthal angle index. + +The azimuthal angle index corresponds to a an array of all azimuthal angles for $ \\theta +\\in [0, \\pi] $ owned by the TrackGenerator class. + +Parameters +---------- +* index : + the azimuthal angle index +"; + +%feature("docstring") Track::clearSegments " +clearSegments() + +Deletes each of this Track's segments. +"; + +%feature("docstring") Track::getAzimAngleIndex " +getAzimAngleIndex() const -> int + +Return the index for the Track's azimuthal angle (with respect to the x-axis). + +Returns +------- +th azimuthal angle index +"; + +%feature("docstring") Track::setPeriodicTrackIndex " +setPeriodicTrackIndex(const int index) + +Set the index of a track in a periodic cycle. + +Tracks form periodic track cycles as they traverse the geometry. Tracks can be arbitrarily +decomposed into periodic track cycles and this index indicates the index in a particular +cycle. + +Parameters +---------- +* index : + of the track in a periodic cycle +"; + +%feature("docstring") Track::setUid " +setUid(int uid) + +Initializes a Track's unique ID. + +This is set by the trackgenerator to correspond to the Track's location in a 2D ragged +array of all tracks. + +Parameters +---------- +* uid : + the Track's unique ID +"; + +%feature("docstring") Track::getSegment " +getSegment(int s) -> segment * + +Returns a pointer to a segment with a given index. + +Returns a pointer to the segment or ends program if Track does not have the requested +segment. + +Parameters +---------- +* segment : + index into the Track's segments container + +Returns +------- +a pointer to the requested segment +"; + +%feature("docstring") Track::isNextOut " +isNextOut() const -> bool + +Returns whether to give the outgoing flux to the \"forward\" (false) or \"reverse\" (true) +direction of the next Track when traveling along this Track's \"reverse\" direction. + +Returns +------- +\"forward\" (false) \"reverse\" (true) direction of outgoing Track +"; + +%feature("docstring") Track::setPhi " +setPhi(const double phi) + +Set the Track's azimuthal angle. + +Parameters +---------- +* phi : + the azimuthal angle +"; + +%feature("docstring") Track::Track " +Track() +"; + +%feature("docstring") Track::getPeriodicTrackIndex " +getPeriodicTrackIndex() const -> int + +Get the index of a track in a periodic cycle. + +Returns +------- +index of the track in a periodic cycle +"; + +%feature("docstring") Track::setTrackOut " +setTrackOut(Track *track_out) + +Sets the track going out along this Track's \"reverse\" direction. + +Parameters +---------- +* track_out : + pointer to the Track going out in the \"reverse\" direction +"; + +%feature("docstring") Track::getTransferFluxOut " +getTransferFluxOut() const -> bool + +Returns a boolean to indicate whether the outgoing flux along this Track's \"reverse\" +direction should be transferred to the incoming Track. + +The bool with be false for vacuum BCs and true for all other BCs. + +Returns +------- +bool indicating whether the flux should be passed when tracking in the \"reverse\" +direction. +"; + +%feature("docstring") Track::setNextOut " +setNextOut(const bool next_out) + +Sets the direction in which the flux leaving this Track along its \"reverse\" direction is +passed. + +Sets whether or not to pass the outgoing flux from this Track along its \"reverse\" +direction to the \"forward\" direction (false) or \"reverse\" direction (true) of the next +Track after intersection with the geometry boundary. + +Parameters +---------- +* next_out : + the \"forward\" (false) or \"reverse (true) direction +"; + +%feature("docstring") Track::getStart " +getStart() -> Point * + +Returns a pointer to the Track's start Point. + +Returns +------- +a pointer to the Track's start Point +"; + +%feature("docstring") Track::getTransferFluxIn " +getTransferFluxIn() const -> bool + +Returns a boolean to indicate whether the outgoing flux along this Track's \"forward\" +direction should be transferred to the outgoing Track. + +The bool with be false for vacuum BCs and true for all other BCs. + +Returns +------- +bool indicating whether the flux should be passed when tracking in the \"forward\" +direction. +"; + +%feature("docstring") Track::setBCOut " +setBCOut(const boundaryType bc_out) + +Sets the boundary condition for the incoming flux along the Track's \"reverse\" direction. + +The boundaryType represents vacuum (0), reflective (1), or periodic (2) boundary +conditions. + +Parameters +---------- +* bc_out : + boundary condition for the incoming flux in the \"reverse\" direction +"; + +%feature("docstring") Track::getUid " +getUid() -> int + +Return the Track's unique ID. + +Returns +------- +the Track's unique ID +"; + +%feature("docstring") Track::removeSegment " +removeSegment(int index) + +Removes a segment from this Track's list of segments. + +Parameters +---------- +* index : + the index of the segment to remove +"; + +%feature("docstring") Track::getSegments " +getSegments() -> segment * + +Returns a vector of pointers to the Track's segments. + +Returns +------- +vector of segment pointers +"; + +%feature("docstring") Track::getTrackIn " +getTrackIn() const -> Track * + +Returns the incoming Track. + +Returns +------- +a pointer to the incoming Track +"; + +%feature("docstring") Track::isNextIn " +isNextIn() const -> bool + +Returns whether to give the outgoing flux to the \"forward\" (false) or \"reverse\" (true) +direction of the next Track when traveling along this Tracks's \"forward\" direction. + +Returns +------- +\"forward\" (false) \"reverse\" (true) direction of outgoing Track +"; + +%feature("docstring") Track::setNextIn " +setNextIn(const bool next_in) + +Sets the direction in which the flux leaving this Track along its \"forward\" direction is +passed. + +Sets whether or not to pass the outgoing flux from this Track along its \"forward\" +direction to the \"forward\" direction (false) or \"reverse\" direction (true) of the next +Track after intersection with the geometry boundary. + +Parameters +---------- +* next_in : + the \"forward\" (false) or \"reverse (true) direction +"; + +%feature("docstring") Track::getBCOut " +getBCOut() const -> boundaryType + +Returns the boundary condition for the flux along the Track's \"reverse\" direction. + +Returns +------- +vacuum (0), reflective (1), or periodic (2) reflective boundary conditions +"; + +%feature("docstring") Track::getReflectiveTrackIndex " +getReflectiveTrackIndex() const -> int + +Get the index of a track in a reflective cycle. + +Returns +------- +index of the track in a reflective cycle +"; + +%feature("docstring") Track::getEnd " +getEnd() -> Point * + +Returns a pointer to the Track's end Point. + +Returns +------- +a pointer to the Track's end Point +"; + +%feature("docstring") Track::addSegment " +addSegment(segment *to_add) + +Adds a segment pointer to this Track's list of segments. + +This method assumes that segments are added in order of their starting location from the +Track's start point. + +Parameters +---------- +* to_add : + a pointer to the segment to add +"; + +%feature("docstring") Track::setValues " +setValues(const double start_x, const double start_y, const double start_z, const double + end_x, const double end_y, const double end_z, const double phi) + +Set the values for the Track's start and end point and angle. + +Parameters +---------- +* start_x : + the x-coordinate at the starting point +* start_y : + the y-coordinate at the starting point +* start_z : + the z-coordinate at the starting point +* end_x : + the x-coordinate at the ending point +* end_y : + the y-coordinate at the ending point +* end_z : + the z-coordinate at the ending point +* phi : + the track's azimuthal angle ( $ \\theta \\in [0, \\pi] $) +"; + +%feature("docstring") Track::insertSegment " +insertSegment(int index, segment *segment) + +Inserts a segment pointer into this Track's list of segments. + +This method appends the new segment directly behind another segment in the Track. This is +a helper method for the TrackGenerator::splitTracks(...) routine. + +Parameters +---------- +* index : + the index of the segment to insert behind in the list +* segment : + a pointer to the segment to insert +"; + +%feature("docstring") Track::getPhi " +getPhi() const -> double + +Return the Track's azimuthal angle (with respect to the x-axis). + +Returns +------- +the azimuthal angle $ \\theta \\in [0, \\pi] $ +"; + +%feature("docstring") Track::getNumSegments " +getNumSegments() -> int + +Return the number of segments along this Track. + +Returns +------- +the number of segments +"; + +%feature("docstring") Track::setReflectiveTrackIndex " +setReflectiveTrackIndex(const int index) + +Set the index of a track in a reflective cycle. + +Tracks form reflective track cycles as they traverse the geometry. Tracks can be +arbitrarily decomposed into reflective track cycles and this index indicates the index in +a particular cycle. + +Parameters +---------- +* index : + of the track in a reflective cycle +"; + +%feature("docstring") Track::~Track " +~Track() + +Destructor clears the Track segments container. +"; + +%feature("docstring") Track::getTrackOut " +getTrackOut() const -> Track * + +Returns the outgoing Track. + +Returns +------- +a pointer to the outgoing Track +"; + +%feature("docstring") Track::setTrackIn " +setTrackIn(Track *track_in) + +Sets the track going out along this Track's \"forward\" direction. + +Parameters +---------- +* track_in : + pointer to the Track going out in the \"forward\" direction +"; + +%feature("docstring") Track::setBCIn " +setBCIn(const boundaryType bc_in) + +Sets the boundary condition for the incoming flux along the Track's \"forward\" direction. + +The boundaryType represents vacuum (0), reflective (1), or periodic (2) boundary +conditions. + +Parameters +---------- +* bc_in : + boundary condition for the incoming flux in the \"forward\" direction +"; + +%feature("docstring") Track::getBCIn " +getBCIn() const -> boundaryType + +Returns the boundary condition for the flux along the Track's \"forward\" direction. + +Returns +------- +vacuum (0), reflective (1), or periodic (2) reflective boundary conditions +"; + +// File: classTrackGenerator.xml + + +%feature("docstring") TrackGenerator " + +The TrackGenerator is dedicated to generating and storing Tracks which cyclically wrap +across the Geometry. + +The TrackGenerator creates Track and initializes boundary conditions (vacuum or +reflective) for each Track. + +C++ includes: src/TrackGenerator.h +"; + +%feature("docstring") TrackGenerator::retrieveTrackCoords " +retrieveTrackCoords(double *coords, int num_tracks) + +Fills an array with the x,y,z coordinates for each Track. + +This class method is intended to be called by the OpenMOC Python \"plotter\" module as a +utility to assist in plotting tracks. Although this method appears to require two +arguments, in reality it only requires on due to SWIG and would be called from within +Python as follows: + + +Parameters +---------- +* coords : + an array of coords of length NUM_VALUES_PER_RETRIEVED_TRACK times the number of Tracks +* length_coords : + the total number of Tracks times NUM_VALUES_PER_RETRIEVED_TRACK +"; + +%feature("docstring") TrackGenerator::setNumAzim " +setNumAzim(int num_azim) + +Set the number of azimuthal angles in $ [0, 2\\pi] $. + +Parameters +---------- +* num_azim : + the number of azimuthal angles in $ 2\\pi $ +"; + +%feature("docstring") TrackGenerator::getZCoord " +getZCoord() -> double + +Returns the z-coord where the 2D Tracks should be created. + +Returns +------- +the z-coord where the 2D Tracks should be created. +"; + +%feature("docstring") TrackGenerator::getTracks " +getTracks() -> Track ** + +Returns a 2D jagged array of the Tracks. + +The first index into the array is the azimuthal angle and the second index is the Track +number for a given azimuthal angle. + +Returns +------- +the 2D jagged array of Tracks +"; + +%feature("docstring") TrackGenerator::initializeSegments " +initializeSegments() + +Initialize track segments with pointers to FSR Materials. + +This is called by the Solver at simulation time. This initialization is necessary since +Materials in each FSR may be interchanged by the user in between different simulations. +This method links each segment and fsr_data struct with the current Material found in each +FSR. +"; + +%feature("docstring") TrackGenerator::getFSRLocks " +getFSRLocks() -> omp_lock_t * + +Return the array of FSR locks for atomic FSR operations. + +Returns +------- +an array of FSR locks +"; + +%feature("docstring") TrackGenerator::setZCoord " +setZCoord(double z_coord) + +Sets the z-coord where the 2D Tracks should be created. + +Parameters +---------- +* z_coord : + the z-coord where the 2D Tracks should be created. +"; + +%feature("docstring") TrackGenerator::generateFSRCentroids " +generateFSRCentroids() + +Generates the numerical centroids of the FSRs. + +This routine generates the numerical centroids of the FSRs by weighting the average x and +y values of each segment in the FSR by the segment's length and azimuthal weight. The +numerical centroid fomula can be found in R. Ferrer et. al. \"Linear Source + Approximation in CASMO 5\", PHYSOR 2012. +"; + +%feature("docstring") TrackGenerator::getFSRVolume " +getFSRVolume(int fsr_id) -> FP_PRECISION + +Computes and returns the volume of an FSR. + +Parameters +---------- +* fsr_id : + the ID for the FSR of interest + +Returns +------- +the FSR volume +"; + +%feature("docstring") TrackGenerator::retrieveSegmentCoords " +retrieveSegmentCoords(double *coords, int num_segments) + +Fills an array with the x,y,z coordinates for each Track segment. + +This class method is intended to be called by the OpenMOC Python \"plotter\" module as a +utility to assist in plotting segments. Although this method appears to require two +arguments, in reality it only requires one due to SWIG and would be called from within +Python as follows: + + +Parameters +---------- +* coords : + an array of coords of length NUM_VALUES_PER_RETRIEVED_SEGMENT times the number of + segments +* length_coords : + the total number of Track segments times NUM_VALUES_PER_RETRIEVED_SEGMENT +"; + +%feature("docstring") TrackGenerator::correctFSRVolume " +correctFSRVolume(int fsr_id, FP_PRECISION fsr_volume) + +Assign a correct volume for some FSR. + +This routine adjusts the length of each track segment crossing a FSR such that the +integrated volume is identical to the true volume assigned by the user. + +Parameters +---------- +* fsr_id : + the ID of the FSR of interest +* fsr_volume : + the correct FSR volume to use +"; + +%feature("docstring") TrackGenerator::setTrackSpacing " +setTrackSpacing(double spacing) + +Set the suggested track spacing (cm). + +Parameters +---------- +* spacing : + the suggested track spacing +"; + +%feature("docstring") TrackGenerator::getNumTracksByParallelGroup " +getNumTracksByParallelGroup(int group) -> int + +Return the number of tracks in a given parallel track group. + +Returns +------- +the number of tracks in a given parallel track group. +"; + +%feature("docstring") TrackGenerator::getFSRVolumes " +getFSRVolumes() -> FP_PRECISION * + +Computes and returns an array of volumes indexed by FSR. + +Note: It is the function caller's responsibility to deallocate the memory reserved for the +FSR volume array. + +Returns +------- +a pointer to the array of FSR volumes +"; + +%feature("docstring") TrackGenerator::getPhi " +getPhi(int azim) -> double + +Returns the azimuthal angle for a given azimuthal angle index. + +Parameters +---------- +* the : + azimuthal angle index. + +Returns +------- +the desired azimuthal angle. +"; + +%feature("docstring") TrackGenerator::splitSegments " +splitSegments(FP_PRECISION max_optical_length) + +Splits Track segments into sub-segments for a user-defined maximum optical length for the +problem. + +This routine is needed so that all segment lengths fit within the exponential +interpolation table used in the MOC transport sweep. + +Parameters +---------- +* max_optical_length : + the maximum optical length +"; + +%feature("docstring") TrackGenerator::getNumY " +getNumY(int azim) -> int + +Return the number of tracks on the y-axis for a given azimuthal angle. + +Parameters +---------- +* azim : + An azimuthal angle index + +Returns +------- +The number of Tracks on the y-axis +"; + +%feature("docstring") TrackGenerator::getNumX " +getNumX(int azim) -> int + +Return the number of tracks on the x-axis for a given azimuthal angle. + +Parameters +---------- +* azim : + An azimuthal angle index + +Returns +------- +The number of Tracks on the x-axis +"; + +%feature("docstring") TrackGenerator::getTracksByParallelGroup " +getTracksByParallelGroup() -> Track ** + +Returns a 1D array of Track pointers. + +The tracks in the _tracks_by_parallel_group array are organized by parallel track group. +The index into the array is also the corresponding Track's UID. + +Returns +------- +The 1D array of Track pointers +"; + +%feature("docstring") TrackGenerator::setGeometry " +setGeometry(Geometry *geometry) + +Set a pointer to the Geometry to use for track generation. + +Parameters +---------- +* geometry : + a pointer to the Geometry +"; + +%feature("docstring") TrackGenerator::getMaxOpticalLength " +getMaxOpticalLength() -> FP_PRECISION + +Finds and returns the maximum optical length amongst all segments. + +Returns +------- +the maximum optical path length +"; + +%feature("docstring") TrackGenerator::~TrackGenerator " +~TrackGenerator() + +Destructor frees memory for all Tracks. +"; + +%feature("docstring") TrackGenerator::generateTracks " +generateTracks(bool neighbor_cells=false) + +Generates tracks for some number of azimuthal angles and track spacing. + +Computes the effective angles and track spacing. Computes the number of Tracks for each +azimuthal angle, allocates memory for all Tracks at each angle and sets each Track's +starting and ending Points, azimuthal angle, and azimuthal angle quadrature weight. +neighbor_cells whether to use neighbor cell optimizations +"; + +%feature("docstring") TrackGenerator::getAzimWeights " +getAzimWeights() -> FP_PRECISION * + +Return a pointer to the array of azimuthal angle quadrature weights. + +Returns +------- +the array of azimuthal angle quadrature weights +"; + +%feature("docstring") TrackGenerator::getNumSegments " +getNumSegments() -> int + +Return the total number of Track segments across the Geometry. + +Returns +------- +the total number of Track segments +"; + +%feature("docstring") TrackGenerator::getNumThreads " +getNumThreads() -> int + +Returns the number of shared memory OpenMP threads in use. + +Returns +------- +the number of threads +"; + +%feature("docstring") TrackGenerator::getNumAzim " +getNumAzim() -> int + +Return the number of azimuthal angles in $ [0, 2\\pi] $. + +Returns +------- +the number of azimuthal angles in $ 2\\pi $ +"; + +%feature("docstring") TrackGenerator::setNumThreads " +setNumThreads(int num_threads) + +Sets the number of shared memory OpenMP threads to use (>0). + +Parameters +---------- +* num_threads : + the number of threads +"; + +%feature("docstring") TrackGenerator::getGeometry " +getGeometry() -> Geometry * + +Return the Geometry for this TrackGenerator if one has been set. + +Returns +------- +a pointer to the Geometry +"; + +%feature("docstring") TrackGenerator::getTrackSpacing " +getTrackSpacing() -> double + +Return the track spacing (cm). + +This will return the user-specified track spacing and NOT the effective track spacing +which is computed and used to generate cyclic tracks. + +Returns +------- +the track spacing (cm) +"; + +%feature("docstring") TrackGenerator::getNumParallelTrackGroups " +getNumParallelTrackGroups() -> int + +Return the number of parallel track groups. + +Returns +------- +The number of parallel track groups +"; + +%feature("docstring") TrackGenerator::TrackGenerator " +TrackGenerator(Geometry *geometry, int num_azim, double spacing) + +Constructor for the TrackGenerator assigns default values. + +Parameters +---------- +* geometry : + a pointer to a Geometry object +* num_azim : + number of azimuthal angles in $ [0, 2\\pi] $ +* spacing : + track spacing (cm) +"; + +%feature("docstring") TrackGenerator::getNumTracks " +getNumTracks() -> int + +Return the total number of Tracks generated. + +Returns +------- +The number of Tracks generated +"; + +%feature("docstring") TrackGenerator::containsTracks " +containsTracks() -> bool + +Returns whether or not the TrackGenerator contains Track that are for its current number +of azimuthal angles, track spacing and geometry. + +Returns +------- +true if the TrackGenerator conatains Tracks; false otherwise +"; + +// File: classTYPolarQuad.xml + + +%feature("docstring") TYPolarQuad " + +Tabuchi-Yamamoto's polar quadrature. + +C++ includes: src/PolarQuad.h +"; + +%feature("docstring") TYPolarQuad::setNumPolarAngles " +setNumPolarAngles(const int num_polar) + +Set the number of polar angles to initialize. + +Parameters +---------- +* num_polar : + the number of polar angles (maximum 3) +"; + +%feature("docstring") TYPolarQuad::TYPolarQuad " +TYPolarQuad() + +Dummy constructor calls the parent constructor. +"; + +%feature("docstring") TYPolarQuad::initialize " +initialize() + +Routine to initialize the polar quadrature. + +This routine uses the tabulated values for the Tabuchi-Yamamoto polar angle quadrature, +including the sine thetas and weights. +"; + +// File: classUniverse.xml + + +%feature("docstring") Universe " + +A Universe represents an unbounded space in the 3D. + +A Universe contains cell which are bounded subspaces in 3D which together form the +Universe. Universes allow for complex, repeating (i.e. lattices) geometries to be simply +represented with as few data structures as possible. + +C++ includes: src/Universe.h +"; + +%feature("docstring") Universe::getNumCells " +getNumCells() const -> int + +Return the number of Cells in this Universe. + +Returns +------- +the number of Cells +"; + +%feature("docstring") Universe::setType " +setType(universeType type) + +Sets the Universe type to SIMPLE or LATTICE. + +Parameters +---------- +* type : + the Universe type +"; + +%feature("docstring") Universe::getMinZ " +getMinZ() -> double + +Returns the minimum reachable z-coordinate in the Universe. + +Returns +------- +the minimum reachable z-coordinate +"; + +%feature("docstring") Universe::getType " +getType() -> universeType + +Return the Universe type (SIMPLE or LATTICE). + +Returns +------- +the Universe type +"; + +%feature("docstring") Universe::getMinX " +getMinX() -> double + +Aggregates a list (vector) of the IDs of all Materials within the MATERIAL type Cells +filling this Universe. + +Note that this method only searches the first level of Cells below this Universe within +the nested Universe coordinate system. + +Returns +------- +a vector of Material IDs +"; + +%feature("docstring") Universe::getMinY " +getMinY() -> double + +Returns the minimum reachable y-coordinate in the Universe. + +Returns +------- +the minimum reachable y-coordinate +"; + +%feature("docstring") Universe::getMaxX " +getMaxX() -> double + +Returns the maximum reachable x-coordinate in the Universe. + +Returns +------- +the maximum reachable x-coordinate +"; + +%feature("docstring") Universe::getMaxY " +getMaxY() -> double + +Returns the maximum reachable y-coordinate in the Universe. + +Returns +------- +the maximum reachable y-coordinate +"; + +%feature("docstring") Universe::getMaxZ " +getMaxZ() -> double + +Returns the maximum reachable z-coordinate in the Universe. + +Returns +------- +the maximum reachable z-coordinate +"; + +%feature("docstring") Universe::printString " +printString() + +Prints a string representation of the Universe's attributes to the console. +"; + +%feature("docstring") Universe::getMinYBoundaryType " +getMinYBoundaryType() -> boundaryType + +Returns the boundary conditions (VACUUM or REFLECTIVE) at the minimum reachable +y-coordinate in the Universe. + +Returns +------- +the boundary conditions at the minimum reachable y-coordinate +"; + +%feature("docstring") Universe::buildNeighbors " +buildNeighbors() + +Builds collections of neighboring Cells for all Cells in this Universe for optimized ray +tracing. +"; + +%feature("docstring") Universe::getAllCells " +getAllCells() -> std::map< int, Cell * > + +Returns the std::map of Cell IDs and Cell pointers in this Universe at all nested Universe +levels. + +Returns +------- +std::map of Cell IDs and pointers +"; + +%feature("docstring") Universe::toString " +toString() -> std::string + +Convert the member attributes of this Universe to a character array. + +Returns +------- +a character array representing the Universe's attributes +"; + +%feature("docstring") Universe::subdivideCells " +subdivideCells(double max_radius=INFINITY) + +Subdivides all of the Material-filled Cells within this Universe into rings and angular +sectors aligned with the z-axis. + +Parameters +---------- +* max_radius : + the maximum allowable radius used in the subdivisions +"; + +%feature("docstring") Universe::getMaxYBoundaryType " +getMaxYBoundaryType() -> boundaryType + +Returns the boundary conditions (VACUUM or REFLECTIVE) at the maximum reachable +y-coordinate in the Universe. + +Returns +------- +the boundary conditions at the maximum reachable y-coordinate +"; + +%feature("docstring") Universe::Universe " +Universe(const int id=-1, const char *name=\"\") + +Constructor assigns a unique and user-specified ID for the Universe. + +Parameters +---------- +* id : + the user-specified optional Universe ID +* name : + the user-specified optional Universe ID +"; + +%feature("docstring") Universe::removeCell " +removeCell(Cell *cell) + +Removes a Cell from this Universe's container of Cells. + +Parameters +---------- +* cell : + a pointer to the Cell to remove +"; + +%feature("docstring") Universe::getId " +getId() const -> int + +Return the user-specified ID for this Universe. + +Returns +------- +the user-specified Universe ID +"; + +%feature("docstring") Universe::getMaxXBoundaryType " +getMaxXBoundaryType() -> boundaryType + +Returns the boundary conditions (VACUUM or REFLECTIVE) at the maximum reachable +x-coordinate in the Universe. + +Returns +------- +the boundary conditions at the maximum reachable x-coordinate +"; + +%feature("docstring") Universe::getName " +getName() const -> char * + +Return the user-defined name of the Universe. + +Returns +------- +the Universe name +"; + +%feature("docstring") Universe::~Universe " +~Universe() + +Destructor clears the Cell pointers container. +"; + +%feature("docstring") Universe::getUid " +getUid() const -> int + +Returns the Universe's unique ID. + +Returns +------- +the Universe's unique ID. +"; + +%feature("docstring") Universe::getMinXBoundaryType " +getMinXBoundaryType() -> boundaryType + +Returns the boundary conditions (VACUUM or REFLECTIVE) at the minimum reachable +x-coordinate in the Universe. + +Returns +------- +the boundary conditions at the minimum reachable x-coordinate +"; + +%feature("docstring") Universe::getCells " +getCells() const -> std::map< int, Cell * > + +Return the container of Cell IDs and Cell pointers in this Universe. + +Returns +------- +std::map of Cell IDs +"; + +%feature("docstring") Universe::isFissionable " +isFissionable() -> bool + +Returns true if the Universe contains a Cell filled by a fissionable Material and false +otherwise. + +This method should not be called prior to the calling of the +Geometry::computeFissionability() method. + +Returns +------- +true if contains a fissionable Material +"; + +%feature("docstring") Universe::getAllMaterials " +getAllMaterials() -> std::map< int, Material * > + +Returns the std::map of all IDs and Material pointers filling this Universe. + +Returns +------- +std::map of Material IDs and pointers +"; + +%feature("docstring") Universe::addCell " +addCell(Cell *cell) + +Adds a Cell to this Universe. + +Stores the user-specified Cell ID and Cell pointer in a std::map along with all of other +Cells added to this Universe. + +Parameters +---------- +* cell : + the Cell pointer +"; + +%feature("docstring") Universe::setFissionability " +setFissionability(bool fissionable) + +Sets whether or not this Universe contains a fissionable Material with a non-zero fission +cross-section. + +This method is called by the Geometry::computeFissionability() class method. + +Parameters +---------- +* fissionable : + true if the Universe contains a fissionable Material; false otherwise +"; + +%feature("docstring") Universe::findCell " +findCell(LocalCoords *coords) -> Cell * + +Finds the Cell for which a LocalCoords object resides. + +Finds the Cell that a LocalCoords object is located inside by checking each of this +Universe's Cells. Returns NULL if the LocalCoords is not in any of the Cells. + +Parameters +---------- +* coords : + a pointer to the LocalCoords of interest + +Returns +------- +a pointer the Cell where the LocalCoords is located +"; + +%feature("docstring") Universe::getCell " +getCell(int cell_id) -> Cell * + +Returns a Cell in this universe. + +Parameters +---------- +* cell_id : + the integer the cell_id + +Returns +------- +Returns the cell pointer. +"; + +%feature("docstring") Universe::clone " +clone() -> Universe * + +Clones this Universe and copy cells map. + +Returns +------- +a pointer to the Universe clone +"; + +%feature("docstring") Universe::getAllUniverses " +getAllUniverses() -> std::map< int, Universe * > + +Returns the std::map of all nested Universe IDs and Universe pointers filling this +Universe. + +Returns +------- +std::map of Universe IDs and pointers +"; + +%feature("docstring") Universe::setName " +setName(const char *name) + +Sets the name of the Universe. + +Parameters +---------- +* name : + the Universe name string +"; + +// File: classVector.xml + + +%feature("docstring") Vector " +"; + +%feature("docstring") Vector::getNumX " +getNumX() -> int + +Get the number of cells in the x dimension. + +Returns +------- +The number of cells in the x dimension. +"; + +%feature("docstring") Vector::getNumY " +getNumY() -> int + +Get the number of cells in the y dimension. + +Returns +------- +The number of cells in the y dimension. +"; + +%feature("docstring") Vector::getSum " +getSum() -> FP_PRECISION + +Get the sum of all the values in the vector. + +Returns +------- +The sum of all the values in the vector. +"; + +%feature("docstring") Vector::getNumRows " +getNumRows() -> int + +Get the number of rows in the vector. + +Returns +------- +The number of rows in the vector. +"; + +%feature("docstring") Vector::setValues " +setValues(int cell, int group_start, int group_end, FP_PRECISION *vals) + +Set values in the vector. This method takes a cell, first group, last group, and floating +point value. The cell and groups are used to compute the rows in the vector. If a values +exist for the rows, the values are overwritten. + +Parameters +---------- +* cell : + The cell location. +* group_first : + The first group location to set. +* group_last : + The last group location to set. +* vals : + The values used to set the row locations. +"; + +%feature("docstring") Vector::incrementValue " +incrementValue(int cell, int group, FP_PRECISION val) + +Increment a value in the vector. This method takes a cell and group and floating point +value. The cell and group are used to compute the row and column in the vector. If a value +exists for the row, the value is incremented by val; otherwise, it is set to val. + +Parameters +---------- +* cell : + The cell location. +* group : + The group location. +* val : + The value used to increment the row location. +"; + +%feature("docstring") Vector::Vector " +Vector(omp_lock_t *cell_locks, int num_x=1, int num_y=1, int num_groups=1) + +Constructor initializes Vector object as a floating point array and sets the vector +dimensions. The vector is ordered by cell (as opposed to by group) on the outside to be +consistent with the Matrix object. Locks are used to make the vector object thread-safe +against concurrent writes the same value. One lock locks out multiple rows of the vector +at a time representing multiple groups in the same cell. + +Parameters +---------- +* cell_locks : + OpenMP locks for atomic cell operations. +* num_x : + The number of cells in the x direction. +* num_y : + The number of cells in the y direction. +* num_groups : + The number of energy groups in each cell. +"; + +%feature("docstring") Vector::getCellLocks " +getCellLocks() -> omp_lock_t * + +Return the array of cell locks for atomic cell operations. + +Returns +------- +an array of cell locks +"; + +%feature("docstring") Vector::clear " +clear() + +Clear all values in the vector. +"; + +%feature("docstring") Vector::printString " +printString() + +Print the vector object to the log file. +"; + +%feature("docstring") Vector::copyTo " +copyTo(Vector *vector) + +Copy the values from the current vector to an input vector. + +Parameters +---------- +* vector : + The vector to copy values to. +"; + +%feature("docstring") Vector::getValue " +getValue(int cell, int group) -> FP_PRECISION + +Get a value at location described by a given cell and group index. + +Parameters +---------- +* cell : + The cell location index. +* group : + The group location index. +"; + +%feature("docstring") Vector::scaleByValue " +scaleByValue(FP_PRECISION val) + +Scales the vector by a given value. + +Parameters +---------- +* val : + The value to scale the vector by. +"; + +%feature("docstring") Vector::getArray " +getArray() -> FP_PRECISION * + +Get the array describing the vector. + +Returns +------- +The array describing the vector. +"; + +%feature("docstring") Vector::getNumGroups " +getNumGroups() -> int + +Get the number of groups in each cell. + +Returns +------- +The number of groups in each cell. +"; + +%feature("docstring") Vector::setAll " +setAll(FP_PRECISION val) +"; + +%feature("docstring") Vector::incrementValues " +incrementValues(int cell, int group_start, int group_end, FP_PRECISION *vals) + +Increment values in the vector. This method takes a cell, first group, last group, and +floating point value. The cell and groups are used to compute the rows in the vector. If +values exist for the rows, the values are incremented by vals; otherwise, they are set. + +Parameters +---------- +* cell : + The cell location. +* group_first : + The first group location to increment. +* group_last : + The last group location to increment. +* vals : + The values used to increment the row locations. +"; + +%feature("docstring") Vector::setValue " +setValue(int cell, int group, FP_PRECISION val) + +Set a value in the vector. This method takes a cell and group and floating point value. +The cell and group are used to compute the row and column in the vector. The location of +the corresponding row is set to val. + +Parameters +---------- +* cell : + The cell location. +* group : + The group location. +* val : + The value used to set the row location. +"; + +%feature("docstring") Vector::~Vector " +~Vector() + +Destructor deletes the arrays used to represent the vector. +"; + +// File: classVectorizedSolver.xml + + +%feature("docstring") VectorizedSolver " + +This is a subclass of the CPUSolver class which uses memory-aligned data structures and +Intel's auto-vectorization. + +note: This class is only compiled if the Intel compiler is used when building OpenMOC. If + building OpenMOC with the \"--with-icpc\" flag, then this class will be available in + the \"openmoc.intel.single\" or \"openmoc.intel.double\" Python module. + +C++ includes: src/VectorizedSolver.h +"; + +%feature("docstring") VectorizedSolver::initializeSourceArrays " +initializeSourceArrays() + +Allocates memory for FSR source arrays. + +Deletes memory for old source arrays if they were allocated for a previous simulation. +"; + +%feature("docstring") VectorizedSolver::getNumVectorWidths " +getNumVectorWidths() -> int + +Returns the number of vector lengths required to fit the number of energy groups. + +If the number of energy groups is 35 and the vector width is 4, this method will return 9 +since 9*4 = 36 is the nearest integer greater than or equal to 35. + +Returns +------- +The number of vector widths +"; + +%feature("docstring") VectorizedSolver::initializeFluxArrays " +initializeFluxArrays() + +Allocates memory for Track boundary angular and FSR scalar fluxes. + +Deletes memory for old flux arrays if they were allocated for a previous simulation. +"; + +%feature("docstring") VectorizedSolver::VectorizedSolver " +VectorizedSolver(TrackGenerator *track_generator=NULL) + +Constructor initializes NULL arrays for source, flux, etc. + +Parameters +---------- +* track_generator : + an optional pointer to a TrackGenerator object +"; + +%feature("docstring") VectorizedSolver::initializeExpEvaluator " +initializeExpEvaluator() + +Allocates memory for the exponential linear interpolation table. +"; + +%feature("docstring") VectorizedSolver::initializeMaterials " +initializeMaterials(solverMode mode=ADJOINT) + +Aligns all Material cross-section data for SIMD vector instructions. + +Parameters +---------- +* mode : + the solution type (FORWARD or ADJOINT) +"; + +%feature("docstring") VectorizedSolver::~VectorizedSolver " +~VectorizedSolver() + +Destructor deletes Track boundary angular flux and and FSR scalar flux and source arrays. +"; + +%feature("docstring") VectorizedSolver::initializeFixedSources " +initializeFixedSources() + +Populates array of fixed sources assigned by FSR. +"; + +%feature("docstring") VectorizedSolver::setGeometry " +setGeometry(Geometry *geometry) + +Sets the Geometry for the Solver. + +Parameters +---------- +* geometry : + a pointer to the Geometry +"; + +%feature("docstring") VectorizedSolver::initializeFSRs " +initializeFSRs() + +Initializes the FSR volumes and Materials array. +"; + +%feature("docstring") VectorizedSolver::computeKeff " +computeKeff() + +Compute $ k_{eff} $ from successive fission sources. +"; + +%feature("docstring") VectorizedSolver::normalizeFluxes " +normalizeFluxes() + +Normalizes all FSR scalar fluxes and Track boundary angular fluxes to the total fission +source (times $ \\nu $). +"; + +%feature("docstring") VectorizedSolver::addSourceToScalarFlux " +addSourceToScalarFlux() + +Add the source term contribution in the transport equation to the FSR scalar flux. +"; + +%feature("docstring") VectorizedSolver::computeFSRSources " +computeFSRSources() + +Computes the total source (fission, scattering, fixed) in each FSR. + +This method computes the total source in each FSR based on this iteration's current +approximation to the scalar flux. +"; + +// File: classXPlane.xml + + +%feature("docstring") XPlane " + +Represents a Plane perpendicular to the x-axis. + +C++ includes: src/Surface.h +"; + +%feature("docstring") XPlane::XPlane " +XPlane(const double x, const int id=0, const char *name=\"\") + +Constructor for a Plane perpendicular to the x-axis. + +Parameters +---------- +* x : + the location of the Plane along the x-axis +* id : + the optional Surface id +* name : + the optional name of the XPlane +"; + +%feature("docstring") XPlane::setX " +setX(const double x) + +Set the location of this XPlane on the x-axis. + +Parameters +---------- +* x : + the location of the XPlane on the x-axis +"; + +%feature("docstring") XPlane::toString " +toString() -> std::string + +Converts this XPlane's attributes to a character array. + +The character array returned conatins the type of Plane (ie, XPLANE) and the A, B, C, and +D coefficients in the quadratic Surface equation and the location of the Plane on the +x-axis. + +Returns +------- +a character array of this XPlane's attributes +"; + +%feature("docstring") XPlane::getMinX " +getMinX(int halfspace) -> double + +Returns the minimum x value for one of this XPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the XPlane to consider + +Returns +------- +the minimum x value +"; + +%feature("docstring") XPlane::getMaxX " +getMaxX(int halfspace) -> double + +Returns the maximum x value for one of this XPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the XPlane to consider + +Returns +------- +the maximum x value +"; + +%feature("docstring") XPlane::getX " +getX() -> double + +Returns the location of the XPlane on the x-axis. + +Returns +------- +the location of the XPlane on the x-axis +"; + +// File: classYPlane.xml + + +%feature("docstring") YPlane " + +Represents a Plane perpendicular to the y-axis. + +C++ includes: src/Surface.h +"; + +%feature("docstring") YPlane::setY " +setY(const double y) + +Set the location of this YPlane on the y-axis. + +Parameters +---------- +* y : + the location of the YPlane on the y-axis +"; + +%feature("docstring") YPlane::toString " +toString() -> std::string + +Converts this yplane's attributes to a character array. + +The character array returned conatins the type of Plane (ie, YPLANE) and the A, B, C, and +D coefficients in the quadratic Surface equation and the location of the Plane on the +y-axis. + +Returns +------- +a character array of this YPlane's attributes +"; + +%feature("docstring") YPlane::getY " +getY() -> double + +Returns the location of the YPlane on the y-axis. + +Returns +------- +the location of the YPlane on the y-axis +"; + +%feature("docstring") YPlane::YPlane " +YPlane(const double y, const int id=0, const char *name=\"\") + +Constructor for a Plane perpendicular to the y-axis. + +Parameters +---------- +* y : + the location of the Plane along the y-axis +* id : + the optional Surface id +* name : + the optional Surface name +"; + +%feature("docstring") YPlane::getMaxY " +getMaxY(int halfspace) -> double + +Returns the maximum y value for one of this YPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the YPlane to consider + +Returns +------- +the maximum y value +"; + +%feature("docstring") YPlane::getMinY " +getMinY(int halfspace) -> double + +Returns the minimum y value for one of this YPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the YPlane to consider + +Returns +------- +the minimum y value +"; + +// File: classZCylinder.xml + + +%feature("docstring") ZCylinder " + +Represents a Cylinder with axis parallel to the z-axis. + +C++ includes: src/Surface.h +"; + +%feature("docstring") ZCylinder::getMinZ " +getMinZ(int halfspace) -> double + +Returns the minimum z value of -INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the minimum z value of -INFINITY +"; + +%feature("docstring") ZCylinder::getRadius " +getRadius() -> double + +Return the radius of the ZCylinder. + +Returns +------- +the radius of the ZCylinder +"; + +%feature("docstring") ZCylinder::getMinX " +getMinX(int halfspace) -> double + +Returns the minimum x value for one of this ZCylinder's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the minimum x value +"; + +%feature("docstring") ZCylinder::getMinY " +getMinY(int halfspace) -> double + +Returns the minimum y value for one of this ZCylinder's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the minimum y value +"; + +%feature("docstring") ZCylinder::getX0 " +getX0() -> double + +Return the x-coordinate of the ZCylinder's center Point. + +Returns +------- +the x-coordinate of the ZCylinder center +"; + +%feature("docstring") ZCylinder::getY0 " +getY0() -> double + +Return the y-coordinate of the ZCylinder's center Point. + +Returns +------- +the y-coordinate of the ZCylinder center +"; + +%feature("docstring") ZCylinder::evaluate " +evaluate(const Point *point) const -> double + +Evaluate a Point using the ZCylinder's quadratic Surface equation. + +Parameters +---------- +* point : + a pointer to the Point of interest + +Returns +------- +the value of Point in the equation +"; + +%feature("docstring") ZCylinder::toString " +toString() -> std::string + +Converts this ZCylinder's attributes to a character array. + +The character array returned conatins the type of Plane (ie, ZCYLINDER) and the A, B, C, D +and E coefficients in the quadratic Surface equation. + +Returns +------- +a character array of this ZCylinder's attributes +"; + +%feature("docstring") ZCylinder::getMaxX " +getMaxX(int halfspace) -> double + +Returns the maximum x value for one of this ZCylinder's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the maximum x value +"; + +%feature("docstring") ZCylinder::getMaxY " +getMaxY(int halfspace) -> double + +Returns the maximum y value for one of this ZCylinder's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the maximum y value +"; + +%feature("docstring") ZCylinder::getMaxZ " +getMaxZ(int halfspace) -> double + +Returns the maximum z value of INFINITY. + +Parameters +---------- +* halfspace : + the halfspace of the ZCylinder to consider + +Returns +------- +the maximum z value of INFINITY +"; + +%feature("docstring") ZCylinder::ZCylinder " +ZCylinder(const double x, const double y, const double radius, const int id=0, const char + *name=\"\") + +constructor. + +Parameters +---------- +* x : + the x-coordinte of the ZCylinder center +* y : + the y-coordinate of the ZCylinder center +* radius : + the radius of the ZCylinder +* id : + the optional Surface ID +* name : + the optional Surface name +"; + +%feature("docstring") ZCylinder::intersection " +intersection(Point *point, double angle, Point *points) -> int + +Finds the intersection Point with this zcylinder from a given Point and trajectory defined +by an angle (0, 1, or 2 points). + +Parameters +---------- +* point : + pointer to the Point of interest +* angle : + the angle defining the trajectory in radians +* points : + pointer to a an array of Points to store intersection Points +* polar : + the polar angle defining the trajectory in radians + +Returns +------- +the number of intersection Points (0 or 1) +"; + +// File: classZPlane.xml + + +%feature("docstring") ZPlane " + +Represents a Plane perpendicular to the z-axis. + +C++ includes: src/Surface.h +"; + +%feature("docstring") ZPlane::getMinZ " +getMinZ(int halfspace) -> double + +Returns the minimum z value for one of this ZPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZPlane to consider + +Returns +------- +the minimum z value +"; + +%feature("docstring") ZPlane::ZPlane " +ZPlane(const double z, const int id=0, const char *name=\"\") + +Constructor for a Plane perpendicular to the z-axis. + +Parameters +---------- +* z : + the location of the Plane along the z-axis +* id : + the optional Surface ID +* name : + the optional Surface name +"; + +%feature("docstring") ZPlane::getMaxZ " +getMaxZ(int halfspace) -> double + +Returns the maximum z value for one of this ZPlane's halfspaces. + +Parameters +---------- +* halfspace : + the halfspace of the ZPlane to consider + +Returns +------- +the maximum z value +"; + +%feature("docstring") ZPlane::toString " +toString() -> std::string + +Converts this ZPlane's attributes to a character array. + +The character array returned conatins the type of Plane (ie, ZPLANE) and the A, B, C, and +D coefficients in the quadratic Surface equation and the location of the Plane along the +z-axis. + +Returns +------- +a character array of this ZPlane's attributes +"; + +%feature("docstring") ZPlane::setZ " +setZ(const double z) + +Set the location of this ZPlane on the z-axis. + +Parameters +---------- +* z : + the location of the ZPlane on the z-axis +"; + +%feature("docstring") ZPlane::getZ " +getZ() -> double + +Returns the location of the ZPlane on the z-axis. + +Returns +------- +the location of the ZPlane on the z-axis +"; + +// File: clone_8cu.xml + +%feature("docstring") clone_track " +clone_track(Track *track_h, dev_track *track_d, std::map< int, int > + &material_IDs_to_indices) + +Given a pointer to a Track on the host, a dev_track on the GPU, and the map of material +IDs to indices in the _materials array, copy all of the class attributes and segments from +the Track object on the host to the GPU. + +This routine is called by the GPUSolver::initializeTracks() private class method and is +not intended to be called directly. + +Parameters +---------- +* track_h : + pointer to a Track on the host +* track_d : + pointer to a dev_track on the GPU +* material_IDs_to_indices : + map of material IDs to indices in the _materials array. +"; + +%feature("docstring") clone_material " +clone_material(Material *material_h, dev_material *material_d) + +Given a pointer to a Material on the host and a dev_material on the GPU, copy all of the +properties from the Material object on the host struct to the GPU. + +This routine is called by the GPUSolver::initializeMaterials() private class method and is +not intended to be called directly. + +Parameters +---------- +* material_h : + pointer to a Material on the host +* material_d : + pointer to a dev_material on the GPU +"; + +// File: clone_8h.xml + +%feature("docstring") clone_track " +clone_track(Track *track_h, dev_track *track_d, std::map< int, int > + &material_IDs_to_indices) + +Given a pointer to a Track on the host, a dev_track on the GPU, and the map of material +IDs to indices in the _materials array, copy all of the class attributes and segments from +the Track object on the host to the GPU. + +This routine is called by the GPUSolver::initializeTracks() private class method and is +not intended to be called directly. + +Parameters +---------- +* track_h : + pointer to a Track on the host +* track_d : + pointer to a dev_track on the GPU +* material_IDs_to_indices : + map of material IDs to indices in the _materials array. +"; + +%feature("docstring") clone_material " +clone_material(Material *material_h, dev_material *material_d) + +Given a pointer to a Material on the host and a dev_material on the GPU, copy all of the +properties from the Material object on the host struct to the GPU. + +This routine is called by the GPUSolver::initializeMaterials() private class method and is +not intended to be called directly. + +Parameters +---------- +* material_h : + pointer to a Material on the host +* material_d : + pointer to a dev_material on the GPU +"; + +// File: GPUExpEvaluator_8cu.xml + +%feature("docstring") clone_exp_evaluator " +clone_exp_evaluator(ExpEvaluator *evaluator_h, GPUExpEvaluator *evaluator_d) + +Given a pointer to an ExpEvaluator on the host and a GPUExpEvaluator on the GPU, copy all +of the properties from the ExpEvaluator object on the host to the GPU. + +This routine is called by the GPUSolver::initializeExpEvaluator() private class method and +is not intended to be called directly. + +Parameters +---------- +* eavluator_h : + pointer to a ExpEvaluator on the host +* evaluator_d : + pointer to a GPUExpEvaluator on the GPU +"; + +// File: GPUExpEvaluator_8h.xml + +%feature("docstring") clone_exp_evaluator " +clone_exp_evaluator(ExpEvaluator *evaluator_h, GPUExpEvaluator *evaluator_d) + +Given a pointer to an ExpEvaluator on the host and a GPUExpEvaluator on the GPU, copy all +of the properties from the ExpEvaluator object on the host to the GPU. + +This routine is called by the GPUSolver::initializeExpEvaluator() private class method and +is not intended to be called directly. + +Parameters +---------- +* eavluator_h : + pointer to a ExpEvaluator on the host +* evaluator_d : + pointer to a GPUExpEvaluator on the GPU +"; + +// File: GPUQuery_8cu.xml + +%feature("docstring") get_num_threads_per_warp " +get_num_threads_per_warp() -> int + +Returns the number of threads in a CUDA warp for the attached GPU. +"; + +%feature("docstring") machine_contains_gpu " +machine_contains_gpu() -> bool + +Queries a node to determine whether it contains one or more GPUs. + +Returns +------- +True if the node contains a GPU, false otherwise. +"; + +%feature("docstring") print_basic_gpu_info " +print_basic_gpu_info() + +Prints the basic device info for the CUDA-enabled device in use. + +Prints the name, compute capability, # multiprocessors and the clock rate of the device. +"; + +%feature("docstring") print_detailed_gpu_info " +print_detailed_gpu_info() + +Prints the detailed device info for the CUDA-enabled device in use. + +Prints the total global and constant memory, shared memory and registers per +multiprocessor, # threads per warp, maximum # threads per multiprocessor, maximum # +threads per block, maximum threadblock dimensions, and maximum grid dimensions. +"; + +%feature("docstring") attach_gpu " +attach_gpu(int id) + +Sets the primary CUDA-enabled device to be the GPU with a given ID. + +Parameters +---------- +* id : + the ID for the GPU to attache +"; + +// File: GPUQuery_8h.xml + +%feature("docstring") get_num_threads_per_warp " +get_num_threads_per_warp() -> int + +Returns the number of threads in a CUDA warp for the attached GPU. +"; + +%feature("docstring") machine_contains_gpu " +machine_contains_gpu() -> bool + +Queries a node to determine whether it contains one or more GPUs. + +Returns +------- +True if the node contains a GPU, false otherwise. +"; + +%feature("docstring") print_basic_gpu_info " +print_basic_gpu_info() + +Prints the basic device info for the CUDA-enabled device in use. + +Prints the name, compute capability, # multiprocessors and the clock rate of the device. +"; + +%feature("docstring") print_detailed_gpu_info " +print_detailed_gpu_info() + +Prints the detailed device info for the CUDA-enabled device in use. + +Prints the total global and constant memory, shared memory and registers per +multiprocessor, # threads per warp, maximum # threads per multiprocessor, maximum # +threads per block, maximum threadblock dimensions, and maximum grid dimensions. +"; + +%feature("docstring") attach_gpu " +attach_gpu(int id=0) + +Sets the primary CUDA-enabled device to be the GPU with a given ID. + +Parameters +---------- +* id : + the ID for the GPU to attache +"; + +// File: GPUSolver_8cu.xml + +%feature("docstring") addSourceToScalarFluxOnDevice " +addSourceToScalarFluxOnDevice(FP_PRECISION *scalar_flux, FP_PRECISION *reduced_sources, + FP_PRECISION *FSR_volumes, int *FSR_materials, dev_material *materials) -> __global__ + void + +Add the source term contribution in the transport equation to the FSR scalar flux on the +GPU. + +Parameters +---------- +* scalar_flux : + an array of FSR scalar fluxes +* reduced_sources : + an array of FSR sources / total xs +* FSR_volumes : + an array of FSR volumes +* FSR_materials : + an array of FSR material indices +* materials : + an array of dev_material pointers +"; + +%feature("docstring") computeFSRFissionRatesOnDevice " +computeFSRFissionRatesOnDevice(FP_PRECISION *FSR_volumes, int *FSR_materials, dev_material + *materials, FP_PRECISION *scalar_flux, FP_PRECISION *fission) -> __global__ void + +Compute the total volume-intergrated fission source from all FSRs and energy groups. + +Parameters +---------- +* FSR_volumes : + an array of the FSR volumes +* FSR_materials : + an array of the FSR Material indices +* materials : + an array of the dev_material pointers +* scalar_flux : + an array of FSR scalar fluxes +* fission : + an array of FSR nu-fission rates +"; + +%feature("docstring") transferBoundaryFlux " +transferBoundaryFlux(dev_track *curr_track, int azim_index, FP_PRECISION *track_flux, + FP_PRECISION *boundary_flux, FP_PRECISION *polar_weights, int energy_angle_index, bool + direction) -> __device__ void + +Updates the boundary flux for a Track given boundary conditions. + +For reflective and periodic boundary conditions, the outgoing boundary flux for the Track +is given to the corresponding reflecting or periodic Track. For vacuum boundary +conditions, the outgoing flux is tallied as leakage. Note: Only one energy group is +transferred by this routine. + +Parameters +---------- +* curr_track : + a pointer to the Track of interest +* azim_index : + a pointer to the azimuthal angle index for this segment +* track_flux : + an array of the outgoing Track flux +* boundary_flux : + an array of all angular fluxes +* polar_weights : + an array of polar Quadrature weights +* energy_angle_index : + the energy group index +* direction : + the Track direction (forward - true, reverse - false) +"; + +%feature("docstring") computeFSRFissionSourcesOnDevice " +computeFSRFissionSourcesOnDevice(int *FSR_materials, dev_material *materials, bool + divide_sigma_t, FP_PRECISION *scalar_flux, FP_PRECISION *reduced_sources) -> + __global__ void + +Computes the total fission source in each FSR in each energy group. + +This method is a helper routine for the openmoc.krylov submodule. This routine computes +the total fission source in each FSR. If the divide_sigma_t parameter is true then the +fission source will be divided by the total cross-section in each FSR. + +Parameters +---------- +* FSR_materials : + an array of FSR Material indices +* materials : + an array of dev_material pointers +* divide_sigma_t : + a boolean indicating whether to divide by the total xs +* scalar_flux : + an array of FSR scalar fluxes +* reduced_sources : + an array of FSR fission sources +"; + +%feature("docstring") atomicAdd " +atomicAdd(double *address, double val) -> __device__ double + +Perform an atomic addition in double precision to an array address. + +This method is straight out of CUDA C Developers Guide (cc 2013). + +Parameters +---------- +* address : + the array memory address +* val : + the value to add to the array + +Returns +------- +the atomically added array value and input value +"; + +%feature("docstring") computeFissionSourcesOnDevice " +computeFissionSourcesOnDevice(FP_PRECISION *FSR_volumes, int *FSR_materials, dev_material + *materials, FP_PRECISION *scalar_flux, FP_PRECISION *fission_sources) -> __global__ + void + +Compute the total fission source from all FSRs. + +Parameters +---------- +* FSR_volumes : + an array of FSR volumes +* FSR_materials : + an array of FSR Material indices +* materials : + an array of dev_materials on the device +* scalar_flux : + the scalar flux in each FSR and energy group +* fission_sources : + array of fission sources in each FSR and energy group +"; + +%feature("docstring") tallyScalarFlux " +tallyScalarFlux(dev_segment *curr_segment, int azim_index, int energy_group, dev_material + *materials, FP_PRECISION *track_flux, FP_PRECISION *reduced_sources, FP_PRECISION + *polar_weights, FP_PRECISION *scalar_flux) -> __device__ void + +Computes the contribution to the FSR scalar flux from a Track segment in a single energy +group. + +This method integrates the angular flux for a Track segment across energy groups and polar +angles, and tallies it into the FSR scalar flux, and updates the Track's angular flux. + +Parameters +---------- +* curr_segment : + a pointer to the Track segment of interest +* azim_index : + a pointer to the azimuthal angle index for this segment +* energy_group : + the energy group of interest +* materials : + the array of dev_material pointers +* track_flux : + a pointer to the Track's angular flux +* reduced_sources : + the array of FSR sources / total xs +* polar_weights : + the array of polar Quadrature weights +* scalar_flux : + the array of FSR scalar fluxes +"; + +%feature("docstring") computeFSRScatterSourcesOnDevice " +computeFSRScatterSourcesOnDevice(int *FSR_materials, dev_material *materials, bool + divide_sigma_t, FP_PRECISION *scalar_flux, FP_PRECISION *reduced_sources) -> + __global__ void + +Computes the total scattering source in each FSR and energy group. + +This method is a helper routine for the openmoc.krylov submodule. This routine computes +the total scatter source in each FSR. If the divide_sigma_t parameter is true then the +scatter source will be divided by the total cross-section in each FSR. + +Parameters +---------- +* FSR_materials : + an array of FSR Material indices +* materials : + an array of dev_material pointers +* divide_sigma_t : + a boolean indicating whether to divide by the total xs +* scalar_flux : + an array of FSR scalar fluxes +* reduced_sources : + an array of FSR scatter sources +"; + +%feature("docstring") transportSweepOnDevice " +transportSweepOnDevice(FP_PRECISION *scalar_flux, FP_PRECISION *boundary_flux, + FP_PRECISION *reduced_sources, dev_material *materials, dev_track *tracks, int + tid_offset, int tid_max) -> __global__ void + +This method performs one transport sweep of one halfspace of all azimuthal angles, tracks, +segments, polar angles and energy groups. + +The method integrates the flux along each track and updates the boundary fluxes for the +corresponding output Track, while updating the scalar flux in each FSR. + +Parameters +---------- +* scalar_flux : + an array of FSR scalar fluxes +* boundary_flux : + an array of Track boundary fluxes +* reduced_sources : + an array of FSR sources / total xs +* materials : + an array of dev_material pointers +* tracks : + an array of Tracks +* tid_offset : + the Track offset for azimuthal angle halfspace +* tid_max : + the upper bound on the Track IDs for this azimuthal angle halfspace +"; + +%feature("docstring") computeFSRSourcesOnDevice " +computeFSRSourcesOnDevice(int *FSR_materials, dev_material *materials, FP_PRECISION + *scalar_flux, FP_PRECISION *fixed_sources, FP_PRECISION *reduced_sources, FP_PRECISION + inverse_k_eff) -> __global__ void + +Computes the total source (fission, scattering, fixed) in each FSR. + +This method computes the total source in each region based on this iteration's current +approximation to the scalar flux. + +Parameters +---------- +* FSR_materials : + an array of FSR Material indices +* materials : + an array of dev_material pointers +* scalar_flux : + an array of FSR scalar fluxes +* fixed_sources : + an array of fixed (user-defined) sources +* reduced_sources : + an array of FSR sources / total xs +* inverse_k_eff : + the inverse of keff +"; + +// File: GPUSolver_8h.xml + +// File: DeviceMaterial_8h.xml + +// File: DeviceTrack_8h.xml + +// File: boundary__type_8h.xml + +// File: Cell_8cpp.xml + +%feature("docstring") maximize_cell_id " +maximize_cell_id(int cell_id) + +Maximize the auto-generated unique Cell ID counter. + +This method updates the auto-generated unique Cell ID counter if the input parameter is +greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Cell IDs do not collide with those created in OpenCG. + +Parameters +---------- +* cell_id : + the id assigned to the auto-generated counter +"; + +%feature("docstring") reset_cell_id " +reset_cell_id() + +Resets the auto-generated unique Cell ID counter to 10000. +"; + +%feature("docstring") cell_id " +cell_id() -> int + +Returns an auto-generated unique Cell ID. + +This method is intended as a utility method for users writing OpenMOC input files. The +method makes use of a static Cell ID which is incremented each time the method is called +to enable unique generation of monotonically increasing IDs. The method's first ID begins +at 10000. Hence, user-defined Cell IDs greater than or equal to 10000 are prohibited. +"; + +// File: Cell_8h.xml + +%feature("docstring") maximize_cell_id " +maximize_cell_id(int cell_id) + +Maximize the auto-generated unique Cell ID counter. + +This method updates the auto-generated unique Cell ID counter if the input parameter is +greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Cell IDs do not collide with those created in OpenCG. + +Parameters +---------- +* cell_id : + the id assigned to the auto-generated counter +"; + +%feature("docstring") reset_cell_id " +reset_cell_id() + +Resets the auto-generated unique Cell ID counter to 10000. +"; + +%feature("docstring") cell_id " +cell_id() -> int + +Returns an auto-generated unique Cell ID. + +This method is intended as a utility method for users writing OpenMOC input files. The +method makes use of a static Cell ID which is incremented each time the method is called +to enable unique generation of monotonically increasing IDs. The method's first ID begins +at 10000. Hence, user-defined Cell IDs greater than or equal to 10000 are prohibited. +"; + +// File: Cmfd_8cpp.xml + +// File: Cmfd_8h.xml + +%feature("docstring") stencilCompare " +stencilCompare(const std::pair< int, FP_PRECISION > &firstElem, const std::pair< int, + FP_PRECISION > &secondElem) -> bool + +Comparitor for sorting k-nearest stencil std::pair objects +"; + +// File: constants_8h.xml + +// File: CPUSolver_8cpp.xml + +// File: CPUSolver_8h.xml + +// File: ExpEvaluator_8cpp.xml + +// File: ExpEvaluator_8h.xml + +// File: Geometry_8cpp.xml + +%feature("docstring") reset_auto_ids " +reset_auto_ids() + +Resets the auto-generated unique IDs for Materials, Surfaces, Cells and Universes/Lattices +to 10000. +"; + +// File: Geometry_8h.xml + +%feature("docstring") reset_auto_ids " +reset_auto_ids() + +Resets the auto-generated unique IDs for Materials, Surfaces, Cells and Universes/Lattices +to 10000. +"; + +// File: linalg_8cpp.xml + +%feature("docstring") matrixMultiplication " +matrixMultiplication(Matrix *A, Vector *X, Vector *B) + +Performs a matrix vector multiplication. + +This function takes in a Matrix (A), a variable Vector (X), and a solution Vector (B) and +computes the matrix vector product. The solution Vector is modified in place. + +Parameters +---------- +* A : + a Matrix object +* X : + the variable Vector object +* B : + the solution Vector object +"; + +%feature("docstring") eigenvalueSolve " +eigenvalueSolve(Matrix *A, Matrix *M, Vector *X, FP_PRECISION tol, FP_PRECISION + SOR_factor) -> FP_PRECISION + +Solves a generalized eigenvalue problem using the Power method. + +This function takes in a loss + streaming Matrix (A), a fission gain Matrix (M), a flux +Vector (X), a tolerance used for both the power method and linear solve convergence (tol), +and a successive over-relaxation factor (SOR_factor) and computes the dominant eigenvalue +and eigenvector using the Power method. The eigenvalue is returned and the input X Vector +is modified in place to be the corresponding eigenvector. + +Parameters +---------- +* A : + the loss + streaming Matrix object +* M : + the fission gain Matrix object +* X : + the flux Vector object +* tol : + the power method and linear solve source convergence threshold +* SOR_factor : + the successive over-relaxation factor + +Returns +------- +k_eff the dominant eigenvalue +"; + +%feature("docstring") computeRMSE " +computeRMSE(Vector *X, Vector *Y, bool integrated) -> FP_PRECISION + +Computes the Root Mean Square Error of two Vectors. + +This function takes in two vectors (X and Y) and computes the Root Mean Square Error of +the Vector Y with respect to Vector X. The boolean integrated must also be given to +indicate whether the operation on the vector should be group-wise integrated before +performing the RMSE operation. + +Parameters +---------- +* X : + a Vector object +* Y : + a second Vector object +* integrated : + a boolean indicating whether to group-wise integrate. +"; + +%feature("docstring") linearSolve " +linearSolve(Matrix *A, Matrix *M, Vector *X, Vector *B, FP_PRECISION tol, FP_PRECISION + SOR_factor) + +Solves a linear system using Red-Black Gauss Seidel with successive over-relaxation. + +This function takes in a loss + streaming Matrix (A), a fission gain Matrix (M), a flux +Vector (X), a source Vector (B), a source convergence tolerance (tol) and a successive +over-relaxation factor (SOR_factor) and computes the solution to the linear system. The +input X Vector is modified in place to be the solution vector. + +Parameters +---------- +* A : + the loss + streaming Matrix object +* M : + the fission gain Matrix object +* X : + the flux Vector object +* B : + the source Vector object +* tol : + the power method and linear solve source convergence threshold +* SOR_factor : + the successive over-relaxation factor +"; + +// File: linalg_8h.xml + +%feature("docstring") matrix_transpose " +matrix_transpose(T *matrix, int dim1, int dim2) + +Transpose a 2D matrix. + +Parameters +---------- +* matrix : + array to transpose +* dim1 : + first dimension length +* dim2 : + second dimension length +"; + +%feature("docstring") matrixMultiplication " +matrixMultiplication(Matrix *A, Vector *X, Vector *B) + +Performs a matrix vector multiplication. + +This function takes in a Matrix (A), a variable Vector (X), and a solution Vector (B) and +computes the matrix vector product. The solution Vector is modified in place. + +Parameters +---------- +* A : + a Matrix object +* X : + the variable Vector object +* B : + the solution Vector object +"; + +%feature("docstring") eigenvalueSolve " +eigenvalueSolve(Matrix *A, Matrix *M, Vector *X, FP_PRECISION tol, FP_PRECISION + SOR_factor=1.5) -> FP_PRECISION + +Solves a generalized eigenvalue problem using the Power method. + +This function takes in a loss + streaming Matrix (A), a fission gain Matrix (M), a flux +Vector (X), a tolerance used for both the power method and linear solve convergence (tol), +and a successive over-relaxation factor (SOR_factor) and computes the dominant eigenvalue +and eigenvector using the Power method. The eigenvalue is returned and the input X Vector +is modified in place to be the corresponding eigenvector. + +Parameters +---------- +* A : + the loss + streaming Matrix object +* M : + the fission gain Matrix object +* X : + the flux Vector object +* tol : + the power method and linear solve source convergence threshold +* SOR_factor : + the successive over-relaxation factor + +Returns +------- +k_eff the dominant eigenvalue +"; + +%feature("docstring") computeRMSE " +computeRMSE(Vector *x, Vector *y, bool integrated) -> FP_PRECISION + +Computes the Root Mean Square Error of two Vectors. + +This function takes in two vectors (X and Y) and computes the Root Mean Square Error of +the Vector Y with respect to Vector X. The boolean integrated must also be given to +indicate whether the operation on the vector should be group-wise integrated before +performing the RMSE operation. + +Parameters +---------- +* X : + a Vector object +* Y : + a second Vector object +* integrated : + a boolean indicating whether to group-wise integrate. +"; + +%feature("docstring") linearSolve " +linearSolve(Matrix *A, Matrix *M, Vector *X, Vector *B, FP_PRECISION tol, FP_PRECISION + SOR_factor=1.5) + +Solves a linear system using Red-Black Gauss Seidel with successive over-relaxation. + +This function takes in a loss + streaming Matrix (A), a fission gain Matrix (M), a flux +Vector (X), a source Vector (B), a source convergence tolerance (tol) and a successive +over-relaxation factor (SOR_factor) and computes the solution to the linear system. The +input X Vector is modified in place to be the solution vector. + +Parameters +---------- +* A : + the loss + streaming Matrix object +* M : + the fission gain Matrix object +* X : + the flux Vector object +* B : + the source Vector object +* tol : + the power method and linear solve source convergence threshold +* SOR_factor : + the successive over-relaxation factor +"; + +// File: LocalCoords_8cpp.xml + +// File: LocalCoords_8h.xml + +// File: log_8cpp.xml + +%feature("docstring") initialize_logger " +initialize_logger() + +Initializes the logger for use. + +This should be immediately called when the logger is imported into Python and before any +of its other routines are called. The routine initializes an OpenMP mutual exclusion lock +which is used to preclude race conditions from occurring when an ERROR message is reported +and program execution is terminated. +"; + +%feature("docstring") get_header_character " +get_header_character() -> char + +Returns the character used to format HEADER type log messages. + +Returns +------- +the character used for HEADER type log messages +"; + +%feature("docstring") set_line_length " +set_line_length(int length) + +Sets the maximum line length for log messages. + +Messages longer than this amount will be broken up into multiline messages. + +Parameters +---------- +* length : + the maximum log message line length in characters +"; + +%feature("docstring") get_log_filename " +get_log_filename() -> const char * + +Returns the log filename. + +Returns +------- +a character array for the log filename +"; + +%feature("docstring") set_separator_character " +set_separator_character(char c) + +Sets the character to be used when printing SEPARATOR log messages. + +Parameters +---------- +* c : + the character for SEPARATOR log messages +"; + +%feature("docstring") set_log_level " +set_log_level(const char *new_level) + +Sets the minimum log message level which will be printed to the console and to the log +file. + +Parameters +---------- +* new_level : + the minimum logging level as a character array +"; + +%feature("docstring") get_separator_character " +get_separator_character() -> char + +Returns the character used to format SEPARATOR log messages. + +Returns +------- +the character used for SEPARATOR log messages +"; + +%feature("docstring") log_printf " +log_printf(logLevel level, const char *format,...) + +Print a formatted message to the console. + +If the logging level is ERROR, this function will throw a runtime exception + +Parameters +---------- +* level : + the logging level for this message +* format : + variable list of C++ formatted arguments +"; + +%feature("docstring") get_output_directory " +get_output_directory() -> const char * + +Returns the output directory for log files. + +Returns +------- +a character array for the log file directory +"; + +%feature("docstring") set_log_filename " +set_log_filename(char *filename) + +Sets the name for the log file. + +Parameters +---------- +* filename : + a character array for log filename +"; + +%feature("docstring") get_log_level " +get_log_level() -> const char * + +Return the minimum level for log messages printed to the screen. + +Returns +------- +the minimum level for log messages +"; + +%feature("docstring") set_output_directory " +set_output_directory(char *directory) + +Sets the output directory for log files. + +If the directory does not exist, it creates it for the user. + +Parameters +---------- +* directory : + a character array for the log file directory +"; + +%feature("docstring") set_header_character " +set_header_character(char c) + +Sets the character to be used when printing HEADER log messages. + +Parameters +---------- +* c : + the character for HEADER log messages +"; + +%feature("docstring") set_title_character " +set_title_character(char c) + +Sets the character to be used when printing TITLE log messages. + +Parameters +---------- +* c : + the character for TITLE log messages +"; + +%feature("docstring") get_title_character " +get_title_character() -> char + +Returns the character used to format TITLE log messages. + +Returns +------- +the character used for TITLE log messages +"; + +%feature("docstring") create_multiline_msg " +create_multiline_msg(std::string level, std::string message) -> std::string + +Breaks up a message which is too long for a single line into a multiline message. + +This is an internal function which is called by log_printf and should not be called +directly by the user. + +Parameters +---------- +* level : + a string containing log level prefix +* message : + a string containing the log message + +Returns +------- +a string with a formatted multiline message +"; + +// File: log_8h.xml + +%feature("docstring") initialize_logger " +initialize_logger() + +Initializes the logger for use. + +This should be immediately called when the logger is imported into Python and before any +of its other routines are called. The routine initializes an OpenMP mutual exclusion lock +which is used to preclude race conditions from occurring when an ERROR message is reported +and program execution is terminated. +"; + +%feature("docstring") get_header_character " +get_header_character() -> char + +Returns the character used to format HEADER type log messages. + +Returns +------- +the character used for HEADER type log messages +"; + +%feature("docstring") set_line_length " +set_line_length(int length) + +Sets the maximum line length for log messages. + +Messages longer than this amount will be broken up into multiline messages. + +Parameters +---------- +* length : + the maximum log message line length in characters +"; + +%feature("docstring") get_log_filename " +get_log_filename() -> const char * + +Returns the log filename. + +Returns +------- +a character array for the log filename +"; + +%feature("docstring") set_separator_character " +set_separator_character(char c) + +Sets the character to be used when printing SEPARATOR log messages. + +Parameters +---------- +* c : + the character for SEPARATOR log messages +"; + +%feature("docstring") set_log_level " +set_log_level(const char *new_level) + +Sets the minimum log message level which will be printed to the console and to the log +file. + +Parameters +---------- +* new_level : + the minimum logging level as a character array +"; + +%feature("docstring") get_separator_character " +get_separator_character() -> char + +Returns the character used to format SEPARATOR log messages. + +Returns +------- +the character used for SEPARATOR log messages +"; + +%feature("docstring") log_printf " +log_printf(logLevel level, const char *format,...) + +Print a formatted message to the console. + +If the logging level is ERROR, this function will throw a runtime exception + +Parameters +---------- +* level : + the logging level for this message +* format : + variable list of C++ formatted arguments +"; + +%feature("docstring") get_output_directory " +get_output_directory() -> const char * + +Returns the output directory for log files. + +Returns +------- +a character array for the log file directory +"; + +%feature("docstring") set_log_filename " +set_log_filename(char *filename) + +Sets the name for the log file. + +Parameters +---------- +* filename : + a character array for log filename +"; + +%feature("docstring") get_log_level " +get_log_level() -> const char * + +Return the minimum level for log messages printed to the screen. + +Returns +------- +the minimum level for log messages +"; + +%feature("docstring") set_output_directory " +set_output_directory(char *directory) + +Sets the output directory for log files. + +If the directory does not exist, it creates it for the user. + +Parameters +---------- +* directory : + a character array for the log file directory +"; + +%feature("docstring") set_header_character " +set_header_character(char c) + +Sets the character to be used when printing HEADER log messages. + +Parameters +---------- +* c : + the character for HEADER log messages +"; + +%feature("docstring") set_err " +set_err(const char *msg) + +A function stub used to convert C++ exceptions into Python exceptions through SWIG. + +This method is not defined in the C++ source. It is defined in the SWIG inteface files +(i.e., openmoc/openmoc.i) + +Parameters +---------- +* msg : + a character array for the exception message +"; + +%feature("docstring") set_title_character " +set_title_character(char c) + +Sets the character to be used when printing TITLE log messages. + +Parameters +---------- +* c : + the character for TITLE log messages +"; + +%feature("docstring") get_title_character " +get_title_character() -> char + +Returns the character used to format TITLE log messages. + +Returns +------- +the character used for TITLE log messages +"; + +%feature("docstring") create_multiline_msg " +create_multiline_msg(std::string level, std::string message) -> std::string + +Breaks up a message which is too long for a single line into a multiline message. + +This is an internal function which is called by log_printf and should not be called +directly by the user. + +Parameters +---------- +* level : + a string containing log level prefix +* message : + a string containing the log message + +Returns +------- +a string with a formatted multiline message +"; + +// File: Material_8cpp.xml + +%feature("docstring") reset_material_id " +reset_material_id() + +Resets the auto-generated unique Material ID counter to 10000. +"; + +%feature("docstring") maximize_material_id " +maximize_material_id(int material_id) + +Maximize the auto-generated unique Material ID counter. + +This method updates the auto-generated unique Material ID counter if the input parameter +is greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Material IDs do not collide with those created in OpenCG. + +Parameters +---------- +* material_id : + the id assigned to the auto-generated counter +"; + +%feature("docstring") material_id " +material_id() -> int + +Returns an auto-generated unique Material ID. + +This method is intended as a utility method for user's writing OpenMOC input files. The +method makes use of a static Material ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined material IDs greater than or equal to 10000 is +prohibited. +"; + +// File: Material_8h.xml + +%feature("docstring") reset_material_id " +reset_material_id() + +Resets the auto-generated unique Material ID counter to 10000. +"; + +%feature("docstring") maximize_material_id " +maximize_material_id(int material_id) + +Maximize the auto-generated unique Material ID counter. + +This method updates the auto-generated unique Material ID counter if the input parameter +is greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Material IDs do not collide with those created in OpenCG. + +Parameters +---------- +* material_id : + the id assigned to the auto-generated counter +"; + +%feature("docstring") material_id " +material_id() -> int + +Returns an auto-generated unique Material ID. + +This method is intended as a utility method for user's writing OpenMOC input files. The +method makes use of a static Material ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined material IDs greater than or equal to 10000 is +prohibited. +"; + +// File: Matrix_8cpp.xml + +// File: Matrix_8h.xml + +// File: pairwise__sum_8h.xml + +%feature("docstring") pairwise_sum " +pairwise_sum(T *vector, int length) -> T + +Performs a pairwise sum of an array of numbers. + +This type of summation uses a divide-and-conquer algorithm which is necessary to bound the +error for summations of large sequences of numbers. + +Parameters +---------- +* vector : + an array of numbers +* length : + the length of the array + +Returns +------- +the sum of all numbers in the array +"; + +// File: ParallelHashMap_8h.xml + +// File: Point_8cpp.xml + +// File: Point_8h.xml + +// File: PolarQuad_8cpp.xml + +// File: PolarQuad_8h.xml + +// File: Solver_8cpp.xml + +// File: Solver_8h.xml + +// File: Surface_8cpp.xml + +%feature("docstring") surface_id " +surface_id() -> int + +Returns an auto-generated unique surface ID. + +This method is intended as a utility mehtod for user's writing OpenMOC input files. The +method makes use of a static surface ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined surface IDs greater than or equal to 10000 are +prohibited. +"; + +%feature("docstring") reset_surface_id " +reset_surface_id() + +Resets the auto-generated unique Surface ID counter to 10000. +"; + +%feature("docstring") maximize_surface_id " +maximize_surface_id(int surface_id) + +Maximize the auto-generated unique Surface ID counter. + +This method updates the auto-generated unique Surface ID counter if the input parameter is +greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Surface IDs do not collide with those created in OpenCG. + +Parameters +---------- +* surface_id : + the id assigned to the auto-generated counter +"; + +// File: Surface_8h.xml + +%feature("docstring") surface_id " +surface_id() -> int + +Returns an auto-generated unique surface ID. + +This method is intended as a utility mehtod for user's writing OpenMOC input files. The +method makes use of a static surface ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined surface IDs greater than or equal to 10000 are +prohibited. +"; + +%feature("docstring") reset_surface_id " +reset_surface_id() + +Resets the auto-generated unique Surface ID counter to 10000. +"; + +%feature("docstring") maximize_surface_id " +maximize_surface_id(int surface_id) + +Maximize the auto-generated unique Surface ID counter. + +This method updates the auto-generated unique Surface ID counter if the input parameter is +greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Surface IDs do not collide with those created in OpenCG. + +Parameters +---------- +* surface_id : + the id assigned to the auto-generated counter +"; + +// File: Timer_8cpp.xml + +// File: Timer_8h.xml + +// File: Track_8cpp.xml + +// File: Track_8h.xml + +// File: TrackGenerator_8cpp.xml + +// File: TrackGenerator_8h.xml + +// File: Universe_8cpp.xml + +%feature("docstring") universe_id " +universe_id() -> int + +Returns an auto-generated unique Universe ID. + +This method is intended as a utility method for user's writing OpenMOC input files. The +method makes use of a static Universe ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined Universe IDs greater than or equal to 10000 is +prohibited. +"; + +%feature("docstring") reset_universe_id " +reset_universe_id() + +Resets the auto-generated unique Universe ID counter to 10000. +"; + +%feature("docstring") maximize_universe_id " +maximize_universe_id(int universe_id) + +Maximize the auto-generated unique Universe ID counter. + +This method updates the auto-generated unique Universe ID counter if the input parameter +is greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Universe IDs do not collide with those created in OpenCG. + +Parameters +---------- +* universe_id : + the id assigned to the auto-generated counter +"; + +// File: Universe_8h.xml + +%feature("docstring") universe_id " +universe_id() -> int + +Returns an auto-generated unique Universe ID. + +This method is intended as a utility method for user's writing OpenMOC input files. The +method makes use of a static Universe ID which is incremented each time the method is +called to enable unique generation of monotonically increasing IDs. The method's first ID +begins at 10000. Hence, user-defined Universe IDs greater than or equal to 10000 is +prohibited. +"; + +%feature("docstring") pair_second " +pair_second(const tMap &map) -> second_t< typename tMap::value_type > + +A helper routine for the Universe::findCell() method. + +This is used to insert a Universe's Cells to the back of a vector of neighbor Cells in +Universe::findCell() routine. This works in symbiosis with the second_t struct template +defined above. + +Parameters +---------- +* map : + a std::map iterator + +Returns +------- +the second element in the iterator (e.g., map value) +"; + +%feature("docstring") reset_universe_id " +reset_universe_id() + +Resets the auto-generated unique Universe ID counter to 10000. +"; + +%feature("docstring") maximize_universe_id " +maximize_universe_id(int universe_id) + +Maximize the auto-generated unique Universe ID counter. + +This method updates the auto-generated unique Universe ID counter if the input parameter +is greater than the present value. This is useful for the OpenCG compatibility module to +ensure that the auto-generated Universe IDs do not collide with those created in OpenCG. + +Parameters +---------- +* universe_id : + the id assigned to the auto-generated counter +"; + +// File: Vector_8cpp.xml + +// File: Vector_8h.xml + +// File: VectorizedSolver_8cpp.xml + +// File: VectorizedSolver_8h.xml + +// File: dir_1ea949864ab1faf245facc269e7b2721.xml + +// File: dir_e42498f83ad2e028b83ea18abff69fa1.xml + +// File: dir_68267d1309a1af8e8297ef4c3efbcdba.xml + diff --git a/openmoc/gnu/__init__.py b/openmoc/gnu/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openmoc/gnu/double/__init__.py b/openmoc/gnu/double/__init__.py deleted file mode 100644 index fb10c05d8..000000000 --- a/openmoc/gnu/double/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import signal, sys - -import _openmoc_gnu_double - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_gnu_double import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.gnu.double.openmoc_gnu_double import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -set_log_level(str(openmoc.get_log_level())) -set_output_directory(openmoc.get_output_directory()) -set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/gnu/double/openmoc_gnu_double.i b/openmoc/gnu/double/openmoc_gnu_double.i deleted file mode 100644 index c031cf53f..000000000 --- a/openmoc/gnu/double/openmoc_gnu_double.i +++ /dev/null @@ -1,268 +0,0 @@ -%module openmoc_gnu_double - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/Solver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } - -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for Lattice::setLatticeCells(int num_x, int num_y, int* universes) - * method - allows users to pass in Python lists of Universe IDs for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, int* universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (int*) malloc(($1 * $2) * sizeof(int)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PySequence_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for Lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem(outer_list,j); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $3[i*$1 + j] = (int) PyInt_AS_LONG(o); - } - else { - free($3); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers as " - "Universe IDs when constructing Lattice cells\n"); - return NULL; - } - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef double FP_PRECISION; - diff --git a/openmoc/gnu/single/__init__.py b/openmoc/gnu/single/__init__.py deleted file mode 100644 index 9dfa06b57..000000000 --- a/openmoc/gnu/single/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -import signal, sys - -import _openmoc_gnu_single - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_gnu_single import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.gnu.single.openmoc_gnu_single import * - - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -openmoc.set_log_level(str(openmoc.get_log_level())) -openmoc.set_output_directory(openmoc.get_output_directory()) -openmoc.set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/gnu/single/openmoc_gnu_single.i b/openmoc/gnu/single/openmoc_gnu_single.i deleted file mode 100644 index 3afb25fe0..000000000 --- a/openmoc/gnu/single/openmoc_gnu_single.i +++ /dev/null @@ -1,268 +0,0 @@ -%module openmoc_gnu_single - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/Solver.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for Lattice::setLatticeCells(int num_x, int num_y, int* universes) - * method - allows users to pass in Python lists of Universe IDs for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, int* universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (int*) malloc(($1 * $2) * sizeof(int)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PySequence_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for Lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem(outer_list,j); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $3[i*$1 + j] = (int) PyInt_AS_LONG(o); - } - else { - free($3); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers as" - "Universe IDs when constructing Lattice cells\n"); - return NULL; - } - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef float FP_PRECISION; - diff --git a/openmoc/intel/__init__.py b/openmoc/intel/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openmoc/intel/double/__init__.py b/openmoc/intel/double/__init__.py deleted file mode 100644 index 18943c2e1..000000000 --- a/openmoc/intel/double/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import signal, sys - -import _openmoc_intel_double - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_intel_double import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.intel.double.openmoc_intel_double import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -set_log_level(str(openmoc.get_log_level())) -set_output_directory(openmoc.get_output_directory()) -set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/intel/double/openmoc_intel_double.i b/openmoc/intel/double/openmoc_intel_double.i deleted file mode 100644 index 04b02dc55..000000000 --- a/openmoc/intel/double/openmoc_intel_double.i +++ /dev/null @@ -1,268 +0,0 @@ -%module openmoc_intel_double - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/Solver.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/VectorizedSolver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 1024); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for Lattice::setLatticeCells(int num_x, int num_y, int* universes) - * method - allows users to pass in Python lists of Universe IDs for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, int* universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (int*) malloc(($1 * $2) * sizeof(int)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PySequence_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for Lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem(outer_list,j); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $3[i*$1 + j] = (int) PyInt_AS_LONG(o); - } - else { - free($3); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers as " - "Universe IDs when constructing Lattice cells\n"); - return NULL; - } - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/VectorizedSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef double FP_PRECISION; - diff --git a/openmoc/intel/single/__init__.py b/openmoc/intel/single/__init__.py deleted file mode 100644 index 9ff057fdd..000000000 --- a/openmoc/intel/single/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import signal, sys - -import _openmoc_intel_single - -# For Python 2.X.X -if (sys.version_info[0] == 2): - import openmoc - from openmoc_intel_single import * -# For Python 3.X.X -else: - import openmoc.openmoc as openmoc - from openmoc.intel.single.openmoc_intel_single import * - -# Tell Python to recognize CTRL+C and stop the C++ extension module -# when this is passed in from the keyboard -signal.signal(signal.SIGINT, signal.SIG_DFL) - -set_log_level(str(openmoc.get_log_level())) -set_output_directory(openmoc.get_output_directory()) -set_log_filename(openmoc.get_log_filename()) - -Timer = openmoc.Timer diff --git a/openmoc/intel/single/openmoc_intel_single.i b/openmoc/intel/single/openmoc_intel_single.i deleted file mode 100644 index 0f260304b..000000000 --- a/openmoc/intel/single/openmoc_intel_single.i +++ /dev/null @@ -1,268 +0,0 @@ -%module openmoc_intel_single - -%{ - #define SWIG_FILE_WITH_INIT - #include "../../../src/Cell.h" - #include "../../../src/Geometry.h" - #include "../../../src/LocalCoords.h" - #include "../../../src/log.h" - #include "../../../src/Material.h" - #include "../../../src/Point.h" - #include "../../../src/Quadrature.h" - #include "../../../src/Solver.h" - #include "../../../src/CPUSolver.h" - #include "../../../src/VectorizedSolver.h" - #include "../../../src/Surface.h" - #include "../../../src/Timer.h" - #include "../../../src/Track.h" - #include "../../../src/TrackGenerator.h" - #include "../../../src/Universe.h" - #include "../../../src/Cmfd.h" - - /* Exception helpers */ - static int swig_c_error_num = 0; - static char swig_c_err_msg[1024]; - - const char* err_occurred(void) { - if (swig_c_error_num) { - swig_c_error_num = 0; - return (const char*)swig_c_err_msg; - } - return NULL; - } - - void set_err(const char *msg) { - swig_c_error_num = 1; - strncpy(swig_c_err_msg, msg, 512); - } -%} - -%warnfilter(506) log_printf(logLevel level, const char *format, ...); -%warnfilter(511) swig::SwigPyIterator; - -%exception { - try { - $function - } catch (const std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -/* C++ casting helper method for openmoc.process computePinPowers routine */ -%inline %{ - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - -%include typemaps.i - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for Lattice::setLatticeCells(int num_x, int num_y, int* universes) - * method - allows users to pass in Python lists of Universe IDs for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, int* universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (int*) malloc(($1 * $2) * sizeof(int)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PySequence_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for Lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem(outer_list,j); - - /* If the value is a number, cast it as an int and set the - * input array value */ - if (PyNumber_Check(o)) { - $3[i*$1 + j] = (int) PyInt_AS_LONG(o); - } - else { - free($3); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers as " - "Universe IDs when constructing Lattice cells\n"); - return NULL; - } - } - } -} - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "../../numpy.i" - - -%init %{ - import_array(); -%} - -/* The typemape used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemape used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - -#endif - - -%include -%include ../../../src/Cell.h -%include ../../../src/Geometry.h -%include ../../../src/LocalCoords.h -%include ../../../src/log.h -%include ../../../src/Material.h -%include ../../../src/Point.h -%include ../../../src/Quadrature.h -%include ../../../src/Solver.h -%include ../../../src/CPUSolver.h -%include ../../../src/VectorizedSolver.h -%include ../../../src/Surface.h -%include ../../../src/Timer.h -%include ../../../src/Track.h -%include ../../../src/TrackGenerator.h -%include ../../../src/Universe.h -%include ../../../src/Cmfd.h - -typedef float FP_PRECISION; - diff --git a/openmoc/krylov.py b/openmoc/krylov.py new file mode 100644 index 000000000..f63af1cea --- /dev/null +++ b/openmoc/krylov.py @@ -0,0 +1,269 @@ +import sys + +import numpy as np + +import openmoc + +# For Python 2.X.X +if sys.version_info[0] == 2: + from log import py_printf + import checkvalue as cv +# For Python 3.X.X +else: + from openmoc.log import py_printf + import openmoc.checkvalue as cv + + +class IRAMSolver(object): + """A Solver which uses a Krylov subspace-based method to solve for an + arbitrary number of eigenmodes in a criticality problem. + + This class uses the Implicitly Restared Arnoldi Method (IRAM) to compute the + n highest order eigenvalues/vectors for a k-eigenvalue criticality problem. + This functionality is based on original work by Colin Josey (cjosey@mit.edu). + + NOTE: This functionality only works for vacuum boundary conditions. + + """ + + def __init__(self, moc_solver): + """Initialize an IRAMSolver. + + Parameters + ---------- + moc_solver : openmoc.Solver + The OpenMOC solver to use in the eigenmode calculation + + """ + + cv.check_type('moc_solver', moc_solver, openmoc.Solver) + + self._moc_solver = moc_solver + + # Determine the floating point precision for Solver + if self._moc_solver.isUsingDoublePrecision(): + self._precision = np.float64 + else: + self._precision = np.float32 + + # Determine if the user passed in a CUDA-enabled GPUSolver + if 'GPUSolver' in type(moc_solver).__name__: + self._with_cuda = True + else: + self._with_cuda = False + + # Compute the size of the LinearOperators used in the eigenvalue problem + geometry = self._moc_solver.getGeometry() + num_FSRs = geometry.getNumFSRs() + num_groups = geometry.getNumEnergyGroups() + self._op_size = num_FSRs * num_groups + + # Initialize solution-dependent class attributes to None + self._num_modes = None + self._interval = None + self._outer_tol = None + self._inner_tol = None + self._A_op = None + self._M_op = None + self._F_op = None + self._a_count = None + self._m_count = None + self._eigenvalues = None + self._eigenvectors = None + + def computeEigenmodes(self, solver_mode=openmoc.FORWARD, num_modes=5, + inner_method='gmres', outer_tol=1e-5, + inner_tol=1e-6, interval=10): + """Compute all eigenmodes in the problem using the scipy.linalg package. + + Parameters + ---------- + solver_mode : {openmoc.FORWARD, openmoc.ADJOINT} + The type of eigenmodes to compute (default is openmoc.FORWARD) + num_modes : Integral + The number of eigenmodes to compute (default is 5) + inner_method : {'gmres', 'lgmres', 'bicgstab', 'cgs'} + Krylov subspace method used for the Ax=b solve (default is 'gmres') + outer_tol : Real + The tolerance on the outer eigenvalue solve (default is 1E-5) + inner_tol : Real + The tolerance on the inner Ax=b solve (default is 1E-5) + interval : Integral + The inner iteration interval for logging messages (default is 10) + """ + + # Ensure that vacuum boundary conditions are used + geometry = self._moc_solver.getGeometry() + if (geometry.getMinXBoundaryType() != openmoc.VACUUM or + geometry.getMaxXBoundaryType() != openmoc.VACUUM or + geometry.getMinYBoundaryType() != openmoc.VACUUM or + geometry.getMaxYBoundaryType() != openmoc.VACUUM): + py_printf('ERROR', 'All boundary conditions must be ' + \ + 'VACUUM for the IRAMSolver') + + import scipy.sparse.linalg as linalg + + # Set solution-dependent class attributes based on parameters + # These are accessed and used by the LinearOperators + self._num_modes = num_modes + self._inner_method = inner_method + self._outer_tol = outer_tol + self._inner_tol = inner_tol + self._interval = interval + + # Initialize inner/outer iteration counters to zero + self._m_count = 0 + self._a_count = 0 + + # Initialize MOC solver + self._moc_solver.initializePolarQuadrature() + self._moc_solver.initializeExpEvaluator() + self._moc_solver.initializeMaterials(solver_mode) + self._moc_solver.initializeFluxArrays() + self._moc_solver.initializeSourceArrays() + self._moc_solver.initializeFSRs() + self._moc_solver.countFissionableFSRs() + self._moc_solver.zeroTrackFluxes() + + # Initialize SciPy operators + op_shape = (self._op_size, self._op_size) + self._A_op = linalg.LinearOperator(op_shape, self._A, + dtype=self._precision) + self._M_op = linalg.LinearOperator(op_shape, self._M, + dtype=self._precision) + self._F_op = linalg.LinearOperator(op_shape, self._F, + dtype=self._precision) + + # Solve the eigenvalue problem + timer = openmoc.Timer() + timer.startTimer() + vals, vecs = linalg.eigs(self._F_op, k=self._num_modes, + tol=self._outer_tol) + timer.stopTimer() + + # Print a timer report + tot_time = timer.getTime() + time_per_mode = tot_time / self._num_modes + tot_time = '{0:.4e} sec'.format(tot_time) + time_per_mode = '{0:.4e} sec'.format(time_per_mode) + py_printf('RESULT', 'Total time to solution'.ljust(53, '.') + tot_time) + py_printf('RESULT', 'Solution time per mode'.ljust(53, '.') + time_per_mode) + + # Store the eigenvalues and eigenvectors + self._eigenvalues = vals + self._eigenvectors = vecs + + # Restore the material data + self._moc_solver.resetMaterials(solver_mode) + + def _A(self, flux): + """Private routine for inner Ax=b solves with the scattering source. + + Solves a fixed source problem using the scatter source for a given flux + distribution. This corresponds to the left hand side of the generalized + kAX = MX eigenvalue problem. + + Parameters + ---------- + flux : numpy.ndarray + The flux used to compute the scattering source + + Returns + ------- + residual : numpy.ndarray + The residual array between input and computed fluxes + + """ + + # Remove imaginary components from NumPy array + flux = np.real(flux).astype(self._precision) + flux_old = np.copy(flux) + + # Apply operator to flux + self._a_count += 1 + self._moc_solver.setFluxes(flux) + self._moc_solver.scatterTransportSweep() + flux = self._moc_solver.getFluxes(self._op_size) + + # Print report to screen to update user on progress + if self._a_count % self._interval == 0: + py_printf('NORMAL', "Performed A operator sweep number %d", self._a_count) + else: + py_printf('INFO', "Performed A operator sweep number %d", self._a_count) + + # Return flux residual + return flux_old - flux + + def _M(self, flux): + """Private routine for inner Ax=b solves with the fission source. + + Solves a fixed source problem using the fission source for a given flux + distribution. This corresponds to the right hand side of the generalized + kAX = MX eigenvalue problem. + + Parameters + ---------- + flux : numpy.ndarray + The flux used to compute the fission source + + Returns + ------- + residual : numpy.ndarray + The residual array between input and computed fluxes + + """ + + # Remove imaginary components from NumPy array + flux = np.real(flux).astype(self._precision) + + # Apply operator to flux + self._m_count += 1 + self._moc_solver.setFluxes(flux) + self._moc_solver.fissionTransportSweep() + flux = self._moc_solver.getFluxes(self._op_size) + + py_printf('NORMAL', "Performed M operator sweep number %d", self._m_count) + + # Return new flux + return flux + + def _F(self, flux): + """Private routine for outer eigenvalue solver method. + + Uses a Krylov subspace method (e.g., GMRES, BICGSTAB) from the + scipy.linalg package to solve the AX=B fixed scatter source problem. + + Parameters + ---------- + flux : numpy.ndarray + The flux array returned from the scipy.linalg.eigs routine + + Returns + ------- + flux : numpy.ndarray + The flux computed from the fission/scatter fixed source calculations + + """ + + import scipy.sparse.linalg as linalg + + # Apply operator to flux - get updated flux from fission source + flux = self._M_op * flux + + # Solve AX=B fixed scatter source problem using Krylov subspace method + if self._inner_method == 'gmres': + flux, x = linalg.gmres(self._A_op, flux, tol=self._inner_tol) + elif self._inner_method == 'lgmres': + flux, x = linalg.lgmres(self._A_op, flux, tol=self._inner_tol) + elif self._inner_method == 'bicgstab': + flux, x = linalg.bicgstab(self._A_op, flux, tol=self._inner_tol) + elif self._inner_method == 'cgs': + flux, x = linalg.cgs(self._A_op, flux, tol=self._inner_tol) + else: + py_printf('ERROR', 'Unable to use %s to solve Ax=b', self._inner_method) + + # Check that solve completed without error before returning new flux + if x != 0: + py_printf('ERROR', 'Unable to solve Ax=b with %s', self._inner_method) + else: + return flux \ No newline at end of file diff --git a/openmoc/log.py b/openmoc/log.py index 8e0c69bb1..a393e89ce 100644 --- a/openmoc/log.py +++ b/openmoc/log.py @@ -1,120 +1,95 @@ -## -# @file log.py -# @package openmoc.log -# @brief Utility functions for writing log messages to the screen. -# -# @details This module includes a set of wrapper functions for the logging -# routines provided by OpenMOC's C++ source code. These Python methods -# provide an interface for creating formatted log messages using -# level-based logging and to print them to the screen and a log file. -# @author Samuel Shaner -# @date March 15, 2013 - -import sys - -## @var openmoc -# @brief The openmoc module in use in the Python script using the -# openmoc.log module. -openmoc = '' - -# Determine which OpenMOC module is being used -if 'openmoc.gnu.double' in sys.modules: - openmoc = sys.modules['openmoc.gnu.double'] -elif 'openmoc.gnu.single' in sys.modules: - openmoc = sys.modules['openmoc.gnu.single'] -elif 'openmoc.intel.double' in sys.modules: - openmoc = sys.modules['openmoc.intel.double'] -elif 'openmoc.intel.single' in sys.modules: - openmoc = sys.modules['openmoc.intel.single'] -elif 'openmoc.bgq.double' in sys.modules: - openmoc = sys.modules['openmoc.bgq.double'] -elif 'openmoc.bgq.single' in sys.modules: - openmoc = sys.modules['openmoc.bgq.single'] -else: - import openmoc - - -## -# @brief Function to print a log message to the screen -# @details This method is a wrapper to the log_printf C++ routine. It -# allows for formatted messages to be printed to the screen -# in a similar fashion to the C/C++ printf method, but with -# additional formatting provided by the OpenMOC logging utilities. -# An example of how this might be used in a OpenMOC Python script -# is as follows: -# -# @code -# value1 = 25 -# value2 = 26.0 -# log.py_printf('NORMAL', 'My name is Will and I am %d going on' \ -# ' %f years of age', value1, value2) -# @endcode -# -# @param level the logging level for this message -# @param my_str the string to print to the screen -# @param *args a variable length list of values for the message string +import openmoc + + def py_printf(level, my_str, *args): + """Print a log message to the screen and the log file. + + This method is a wrapper to the log_printf C++ routine. It allows for + formatted messages to be printed to the screen in a similar fashion to the + C/C++ printf method, but with additional formatting provided by the OpenMOC + logging utilities. + + Parameters + ---------- + level : str + The logging level for this message (i.e., 'NORMAL') + my_str : str + The string to print to the screen + *args : list + A variable length list of values for the message string + + Examples + -------- + An example of how this may be used in a OpenMOC Python script is as follows: + + >>> value1 = 25 + >>> value2 = 26.0 + >>> log.py_printf('NORMAL', 'My name is Will and I am %d going on ' \ + '%f years of age', value1, value2) + + """ + + if level == 'DEBUG': + openmoc.log_printf(openmoc.DEBUG, my_str % args) + elif level == 'INFO': + openmoc.log_printf(openmoc.INFO, my_str % args) + elif level == 'NORMAL': + openmoc.log_printf(openmoc.NORMAL, my_str % args) + elif level == 'SEPARATOR': + openmoc.log_printf(openmoc.SEPARATOR, my_str % args) + elif level == 'HEADER': + openmoc.log_printf(openmoc.HEADER, my_str % args) + elif level == 'TITLE': + openmoc.log_printf(openmoc.TITLE, my_str % args) + elif level == 'WARNING': + openmoc.log_printf(openmoc.WARNING, my_str % args) + elif level == 'CRITICAL': + openmoc.log_printf(openmoc.CRITICAL, my_str % args) + elif level == 'RESULT': + openmoc.log_printf(openmoc.RESULT, my_str % args) + elif level == 'ERROR': + openmoc.log_printf(openmoc.ERROR, my_str % args) + - if level == 'DEBUG': - openmoc.log_printf(openmoc.DEBUG, my_str % args) - elif level == 'INFO': - openmoc.log_printf(openmoc.INFO, my_str % args) - elif level == 'NORMAL': - openmoc.log_printf(openmoc.NORMAL, my_str % args) - elif level == 'SEPARATOR': - openmoc.log_printf(openmoc.SEPARATOR, my_str % args) - elif level == 'HEADER': - openmoc.log_printf(openmoc.HEADER, my_str % args) - elif level == 'TITLE': - openmoc.log_printf(openmoc.TITLE, my_str % args) - elif level == 'WARNING': - openmoc.log_printf(openmoc.WARNING, my_str % args) - elif level == 'CRITICAL': - openmoc.log_printf(openmoc.CRITICAL, my_str % args) - elif level == 'RESULT': - openmoc.log_printf(openmoc.RESULT, my_str % args) - elif level == 'UNITTEST': - openmoc.log_printf(openmoc.UNITTEST, my_str % args) - elif level == 'ERROR': - openmoc.log_printf(openmoc.ERROR, my_str % args) - - -## -# @brief Assigns the lowest level logging message. -# @details Sets the lowest level logging message to print to the screen. -# This controls the lowest level for both logging messages in the -# C++ source code as well as the user's OpenMOC Python input file. -# This function would be called at the beginning of the input file -# as follows: -# -# @code -# log.set_log_level('INFO') -# @endcode -# -# @param level the minimum logging level ('DEBUG', 'INFO', etc) def set_log_level(level): + """Assign the lowest level logging message to be reported. + + Sets the lowest level logging message to print to the screen. This controls + the lowest level for both logging messages in the C++ source code as well as + the user's OpenMOC Python input file. + + Parameters + ---------- + level : str + The minimum logging level (i.e., 'DEBUG', 'INFO') + + Examples + -------- + This routine may be called in an OpenMOC Python script as follows: + + >>> log.set_log_level('INFO') + + """ - if level == 'DEBUG': - openmoc.set_log_level('DEBUG') - elif level == 'INFO': - openmoc.set_log_level('INFO') - elif level == 'NORMAL': - openmoc.set_log_level('NORMAL') - elif level == 'SEPARATOR': - openmoc.set_log_level('SEPARATOR') - elif level == 'HEADER': - openmoc.set_log_level('HEADER') - elif level == 'TITLE': - openmoc.set_log_level('TITLE') - elif level == 'WARNING': - openmoc.set_log_level('WARNING') - elif level == 'CRITICAL': - openmoc.set_log_level('CRITICAL') - elif level == 'RESULT': - openmoc.set_log_level('RESULT') - elif level == 'UNITTEST': - openmoc.set_log_level('UNITTEST') - elif level == 'ERROR': - openmoc.set_log_level('ERROR') - else: - py_printf('Cannot set log level to unsupported log level %s', str(level)) + if level == 'DEBUG': + openmoc.set_log_level('DEBUG') + elif level == 'INFO': + openmoc.set_log_level('INFO') + elif level == 'NORMAL': + openmoc.set_log_level('NORMAL') + elif level == 'SEPARATOR': + openmoc.set_log_level('SEPARATOR') + elif level == 'HEADER': + openmoc.set_log_level('HEADER') + elif level == 'TITLE': + openmoc.set_log_level('TITLE') + elif level == 'WARNING': + openmoc.set_log_level('WARNING') + elif level == 'CRITICAL': + openmoc.set_log_level('CRITICAL') + elif level == 'RESULT': + openmoc.set_log_level('RESULT') + elif level == 'ERROR': + openmoc.set_log_level('ERROR') + else: + py_printf('Cannot set log level to unsupported level %s', str(level)) \ No newline at end of file diff --git a/openmoc/map_to_dict.i b/openmoc/map_to_dict.i new file mode 100644 index 000000000..47cead62d --- /dev/null +++ b/openmoc/map_to_dict.i @@ -0,0 +1,173 @@ +/** Routines and typemaps to convert C++ std::map return types to Python dict */ + +%module map_to_dict + +/* Typemap for all methods which return a std::map. This includes + * the Geometry::getAllCells(), Universe::getAllCells(), etc. These methods + * are particularly useful for OpenCG compatibility. */ +%include +%clear std::map; +%typemap(out) std::map { + + $result = PyDict_New(); + int size = $1.size(); + + std::map::iterator iter; + Cell* cell; + int cell_id; + + for (iter = $1.begin(); iter != $1.end(); ++iter) { + cell_id = iter->first; + cell = iter->second; + PyObject* value = + SWIG_NewPointerObj(SWIG_as_voidptr(cell), $descriptor(Cell*), 0); + PyDict_SetItem($result, PyInt_FromLong(cell_id), value); + } +} + + +/* Typemap for all methods which return a std::map. This + * includes the Geometry::getAllSurfaces() method, which is useful for + * OpenCG compatibility. */ +%clear std::map; +%typemap(out) std::map { + + $result = PyDict_New(); + int size = $1.size(); + + std::map::iterator iter; + Surface* surf; + int surf_id; + + for (iter = $1.begin(); iter != $1.end(); ++iter) { + surf_id = iter->first; + surf = iter->second; + PyObject* value = + SWIG_NewPointerObj(SWIG_as_voidptr(surf), + $descriptor(Surface*), 0); + PyDict_SetItem($result, PyInt_FromLong(surf_id), value); + } +} + + +/* Typemap for all methods which return a std::map. + * This includes the Cell::getSurfaces() method, which is useful for OpenCG + * compatibility. */ +%clear std::map; +%typemap(out) std::map { + + $result = PyDict_New(); + int size = $1.size(); + + std::map::iterator iter; + surface_halfspace* surf; + int surf_id; + + for (iter = $1.begin(); iter != $1.end(); ++iter) { + surf_id = iter->first; + surf = iter->second; + PyObject* value = + SWIG_NewPointerObj(SWIG_as_voidptr(surf), + $descriptor(surface_halfspace*), 0); + PyDict_SetItem($result, PyInt_FromLong(surf_id), value); + } +} + + +/* Typemap for all methods which return a std::map. + * This includes the Geometry::getAllMaterials() method, which is useful + * for OpenCG compatibility. */ +%clear std::map; +%typemap(out) std::map { + + $result = PyDict_New(); + int size = $1.size(); + + std::map::iterator iter; + Material* mat; + int mat_id; + + for (iter = $1.begin(); iter != $1.end(); ++iter) { + mat_id = iter->first; + mat = iter->second; + PyObject* value = + SWIG_NewPointerObj(SWIG_as_voidptr(mat), $descriptor(Material*), 0); + PyDict_SetItem($result, PyInt_FromLong(mat_id), value); + } +} + + +/* Typemap for all methods which return a std::map. + * This includes the Lattice::getUniqueUniverses() method which is ueseful for + * OpenCG compatibility. */ +%clear std::map; +%typemap(out) std::map { + + $result = PyDict_New(); + int size = $1.size(); + + std::map::iterator iter; + Universe* univ; + int univ_id; + + for (iter = $1.begin(); iter != $1.end(); ++iter) { + univ_id = iter->first; + univ = iter->second; + PyObject* value = + SWIG_NewPointerObj(SWIG_as_voidptr(univ), $descriptor(Universe*), 0); + PyDict_SetItem($result, PyInt_FromLong(univ_id), value); + } +} + + +/* Typemap for Lattice::setUniverses(int num_z, int num_y, int num_x, + * Universe** universes) + * method - allows users to pass in Python lists of Universes for each + * lattice cell */ +%typemap(in) (int num_z, int num_y, int num_x, Universe** universes) { + + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " + "for the Lattice cells"); + return NULL; + } + + $1 = PySequence_Length($input); // num_z + $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y + $3 = PySequence_Length(PyList_GetItem(PyList_GetItem($input,0), 0)); // num_x + $4 = (Universe**) malloc(($1 * $2 * $3) * sizeof(Universe*)); // universes + + /* Loop over the xy-planes */ + for (int k = 0; k < $1; k++) { + + /* Get the 2D list of universes in the k-th xy-plane */ + PyObject* outer_outer_list = PyList_GetItem($input,k); + + /* Loop over y */ + for (int j = 0; j < $2; j++) { + + /* Get the list of universes in the j-th row of the k-th xy-plane */ + PyObject* outer_list = PyList_GetItem(outer_outer_list, j); + + /* Check that the number of universes in the j-th row of the k-th xy-plane + * is the same as the number of universes in the 1st row of the 1st + * xy-plane */ + if (PySequence_Length(outer_list) != $3) { + PyErr_SetString(PyExc_ValueError, "Size mismatch in dimensions of 3D " + "list of Universes in input to Lattice:setUniverses" + " method"); + return NULL; + } + + /* Loop over universes in j-th row of the k-th xy-plane */ + for (int i =0; i < $3; i++) { + /* Extract the value from the list at this location and convert + * SWIG wrapper to pointer to underlying C++ class instance */ + PyObject* o = PyList_GetItem(outer_list, i); + void *p1 = 0; + SWIG_ConvertPtr(o, &p1, SWIGTYPE_p_Universe, 0 | 0); + $4[k*($2*$3) + j*$3 + i] = (Universe*) p1; + } + } + } +} diff --git a/openmoc/materialize.py b/openmoc/materialize.py index 589b21c07..ae3ad615f 100644 --- a/openmoc/materialize.py +++ b/openmoc/materialize.py @@ -1,217 +1,794 @@ -## -# @file materialize.py -# @package openmoc.materialize -# @brief The materialize module provides utility functions to read and write -# multi-group materials cross-section data from HDF5 binary file format. -# @author William Boyd (wboyd@mit.edu) -# @date April 23, 2013 - -# Determine which OpenMOC module is being used. This is important for -# the materialize module since it must instantiate Material objects -# with the same floating point precision as that compiled into the -# openmoc module used in the main Python input script to OpenMOC. - - import sys +import os +import copy +import collections +import hashlib -## @var openmoc -# @brief The openmoc module in use in the Python script using the -# openmoc.materialize module. -openmoc = '' - -if 'openmoc.gnu.double' in sys.modules: - openmoc = sys.modules['openmoc.gnu.double'] -elif 'openmoc.gnu.single' in sys.modules: - openmoc = sys.modules['openmoc.gnu.single'] -elif 'openmoc.intel.double' in sys.modules: - openmoc = sys.modules['openmoc.intel.double'] -elif 'openmoc.intel.single' in sys.modules: - openmoc = sys.modules['openmoc.intel.single'] -elif 'openmoc.bgq.double' in sys.modules: - openmoc = sys.modules['openmoc.bgq.double'] -elif 'openmoc.bgq.single' in sys.modules: - openmoc = sys.modules['openmoc.bgq.single'] -else: - import openmoc +import numpy as np + +import openmoc # For Python 2.X.X -if (sys.version_info[0] == 2): - from log import * - from process import * +if sys.version_info[0] == 2: + from log import py_printf + import checkvalue as cv # For Python 3.X.X else: - from openmoc.log import * - from openmoc.process import * - - - - -## -# @brief This routine takes in an input file of Material nuclear data and -# instantiates Material objects with that data, and returns a list of -# handles to each Material object to the user. -# @param filename the file of nuclear cross-sections for each Material -# @return a list of Material object handles for OpenMOC -def materialize(filename): - - xs_types = ['Total XS', 'Absorption XS', 'Scattering XS', \ - 'Fission XS', 'Nu Fission XS', 'Chi', 'Diffusion Coefficient'] - materials = {} - - # Check that the filename is a string - if not isinstance(filename, str): - py_printf('ERROR', 'Unable to materialize using filename %s ' + \ - 'since it is not a string', str(filename)) - - - ############################################################################## - # HDF5 DATA FILES - ############################################################################## - - if filename.endswith('.h5') or filename.endswith('.hdf5'): - - import h5py - import numpy as np + from openmoc.log import py_printf + import openmoc.checkvalue as cv + +if sys.version_info[0] >= 3: + basestring = str + + +def _get_domain(domains, domain_spec): + """A helper routine to find materials/cells for load_from_hdf5(...)""" + + # If domain_spec is an integer, it must be a domain ID + if isinstance(domain_spec, int) and domain_spec in domains: + return domains[domain_spec] + + # If domain_spec is a string, it must be a domain name + elif isinstance(domain_spec, basestring): + for domain_id, domain in domains.items(): + if domain_spec == domain.getName(): + return domain + + # If domain could not be found + return None + + +def _get_numpy_array(hdf5_group, key, suffix): + """A helper routine to ensure that MGXS data is a proper NumPy array""" + + sigma = np.array(hdf5_group['{}/'.format(key) + suffix][...]) + sigma = np.atleast_1d(sigma) + sigma = sigma.flatten() + return sigma + + +def load_from_hdf5(filename='mgxs.h5', directory='mgxs', + geometry=None, domain_type='material', suffix=''): + """This routine loads an HDF5 file of multi-group cross section data. + + The routine instantiates material with multi-group cross section data and + returns a dictionary of each Material object keyed by its ID. An OpenMOC + geometry may optionally be given and the routine will directly insert the + multi-group cross sections into each material in the geometry. If a geometry + is passed in, materials from the geometry will be used in place of those + instantiated by this routine. + + Parameters + ---------- + filename : str + Filename for cross sections HDF5 file (default is 'mgxs.h5') + directory : str + Directory for cross sections HDF5 file (default is 'mgxs') + geometry : openmoc.Geometry, optional + An optional geometry populated with materials, cells, etc. + domain_type : str + The domain type ('material' or 'cell') upon which the cross sections + are defined (default is 'material') + suffix : str, optional + An optional string suffix to index the HDF5 file beyond the assumed + domain_type/domain_id/mgxs_type group sequence (default is '') + + Returns + ------- + materials : dict + A dictionary of Materials keyed by ID + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + cv.check_value('domain_type', domain_type, ('material', 'cell')) + cv.check_type('suffix', suffix, basestring) + if geometry: + cv.check_type('geometry', geometry, openmoc.Geometry) # Create a h5py file handle for the file - try: - f = h5py.File(filename,'r') - except: - py_printf('ERROR', 'Unable to materialize file %s because it ' + \ - 'cannot be opened. Check the file path.',filename) + import h5py + filename = os.path.join(directory, filename) + f = h5py.File(filename, 'r') # Check that the file has an 'energy groups' attribute - if not 'Energy Groups' in f.attrs: - py_printf('ERROR', 'Unable to materialize file %s since it does ' + \ - 'not contain an \'Energy Groups\' attribute', filename) - - num_groups = f.attrs['Energy Groups'] - - - - # Check that the number of energy groups is an integer - if not is_integer(num_groups): - py_printf('ERROR', 'Unable to materialize file %s since the number of' + \ - 'energy groups %s could not be converted to an integer', \ - filename, str(num_groups)) - - material_names = list(f) - - # Loop over each material and - for name in material_names: - - py_printf('INFO', 'Importing material %s', str(name)) - - new_material = openmoc.Material() - new_material.setNumEnergyGroups(int(num_groups)) - - # Retrieve and load the cross-section data into the material object - - if 'Total XS' in f[name]: - new_material.setSigmaT(f[name]['Total XS'][...]) - - if 'Scattering XS' in f[name]: - new_material.setSigmaS(f[name]['Scattering XS'][...]) - - if 'Fission XS' in f[name]: - new_material.setSigmaF(f[name]['Fission XS'][...]) - - if 'Nu Fission XS' in f[name]: - new_material.setNuSigmaF(f[name]['Nu Fission XS'][...]) - - if 'Chi' in f[name]: - new_material.setChi(f[name]['Chi'][...]) - - if 'Diffusion Coefficient' in f[name]: - new_material.setDifCoef(f[name]['Diffusion Coefficient'][...]) - - if 'Buckling' in f[name]: - new_material.setBuckling(f[name]['Buckling'][...]) - - if 'Absorption XS' in f[name]: - new_material.setSigmaA(f[name]['Absorption XS'][...]) - - # Make sure this Material's cross-sections add up to - # its total cross-section - new_material.checkSigmaT() - - # Add this material to the list - materials[name] = new_material - - - ############################################################################## - # PYTHON DICTIONARY DATA FILES - ############################################################################## - elif filename.endswith('.py'): - - import imp - + if '# groups' not in f.attrs: + py_printf('ERROR', 'Unable to load HDF5 file "%s" since it does ' + 'not contain an \'# groups\' attribute', filename) + + if domain_type not in f.keys(): + py_printf('ERROR', 'Unable to load HDF5 file "%s" since it does ' + 'not contain domain type "%s"', filename, domain_type) + + # Instantiate dictionary to hold Materials to return to user + materials = {} + old_materials = {} + num_groups = int(f.attrs['# groups']) + + # If a Geometry was passed in, extract all cells or materials from it + if geometry: + if domain_type == 'material': + domains = geometry.getAllMaterials() + elif domain_type == 'cell': + domains = geometry.getAllMaterialCells() + else: + py_printf('ERROR', 'Domain type "%s" is not supported', domain_type) + + # Iterate over all domains (e.g., materials or cells) in the HDF5 file + for domain_spec in sorted(f[domain_type]): + + py_printf('INFO', 'Importing cross sections for %s "%s"', + domain_type, str(domain_spec)) + + # Create shortcut to HDF5 group for this domain + domain_group = f[domain_type][domain_spec] + + # If domain_spec is an integer, it is an ID; otherwise a string name + if domain_spec.isdigit(): + domain_spec = int(domain_spec) + else: + domain_spec = str(domain_spec) + + # If using an OpenMOC Geometry, extract a Material from it + if geometry: + + if domain_type == 'material': + material = _get_domain(domains, domain_spec) + + elif domain_type == 'cell': + cell = _get_domain(domains, domain_spec) + material = cell.getFillMaterial() + + # If the user filled multiple Cells with the same Material, + # the Material must be cloned for each unique Cell + if material != None: + if len(domains) > geometry.getNumMaterials(): + old_materials[material.getId()] = material + material = material.clone() + + # If the Cell does not contain a Material, create one for it + else: + if isinstance(domain_spec, int): + material = openmoc.Material(id=domain_spec) + else: + # Reproducibly hash the domain name into an integer ID + domain_id =hashlib.md5(domain_spec.encode('utf-8')) + domain_id = int(domain_id.hexdigest()[:4], 16) + material = \ + openmoc.Material(id=domain_id, name=domain_spec) + + # Fill the Cell with the new Material + cell.setFill(material) + + # If not Geometry, instantiate a new Material with the ID/name + else: + if isinstance(domain_spec, int): + material = openmoc.Material(id=domain_spec) + else: + # Reproducibly hash the domain name into an integer ID + domain_id =hashlib.md5(domain_spec.encode('utf-8')) + domain_id = int(domain_id.hexdigest()[:4], 16) + material = openmoc.Material(id=domain_id, name=domain_spec) + + # Add material to the collection + materials[domain_spec] = material + material.setNumEnergyGroups(num_groups) + + # Search for the total/transport cross section + if 'transport' in domain_group: + sigma = _get_numpy_array(domain_group, 'transport', suffix) + material.setSigmaT(sigma) + py_printf('INFO', 'Loaded "transport" MGXS for "%s %s"', + domain_type, str(domain_spec)) + elif 'total' in domain_group: + sigma = _get_numpy_array(domain_group, 'total', suffix) + material.setSigmaT(sigma) + py_printf('INFO', 'Loaded "total" MGXS for "%s %s"', + domain_type, str(domain_spec)) + else: + py_printf('WARNING', 'No "total" or "transport" MGXS found for' + '"%s %s"', domain_type, str(domain_spec)) + + # Search for the fission production cross section + if 'nu-fission' in domain_group: + sigma = _get_numpy_array(domain_group, 'nu-fission', suffix) + material.setNuSigmaF(sigma) + py_printf('INFO', 'Loaded "nu-fission" MGXS for "%s %s"', + domain_type, str(domain_spec)) + else: + py_printf('WARNING', 'No "nu-fission" MGXS found for' + '"%s %s"', domain_type, str(domain_spec)) + + # Search for the scattering matrix cross section + if 'nu-scatter matrix' in domain_group: + sigma = _get_numpy_array(domain_group, 'nu-scatter matrix', suffix) + material.setSigmaS(sigma) + py_printf('INFO', 'Loaded "nu-scatter matrix" MGXS for "%s %s"', + domain_type, str(domain_spec)) + elif 'scatter matrix' in domain_group: + sigma = _get_numpy_array(domain_group, 'scatter matrix', suffix) + material.setSigmaS(sigma) + py_printf('INFO', 'Loaded "scatter matrix" MGXS for "%s %s"', + domain_type, str(domain_spec)) + else: + py_printf('WARNING', 'No "scatter matrix" found for "%s %s"', + domain_type, str(domain_spec)) + + # Search for chi (fission spectrum) + if 'chi' in domain_group: + chi = _get_numpy_array(domain_group, 'chi', suffix) + material.setChi(chi) + py_printf('INFO', 'Loaded "chi" MGXS for "%s %s"', + domain_type, str(domain_spec)) + else: + py_printf('WARNING', 'No "chi" MGXS found for "%s %s"', + domain_type, str(domain_spec)) + + # Search for optional cross sections + if 'fission' in domain_group: + sigma = _get_numpy_array(domain_group, 'fission', suffix) + material.setSigmaF(sigma) + py_printf('INFO', 'Loaded "fission" MGXS for "%s %s"', + domain_type, str(domain_spec)) + + # Inform SWIG to garbage collect any old Materials from the Geometry + for material_id in old_materials: + old_materials[material_id].thisown = False + + # Return collection of materials + return materials + + +def load_openmc_mgxs_lib(mgxs_lib, geometry=None): + """This routine loads an OpenMC Library of multi-group cross section data. + + The routine instantiates materials with multi-group cross section data and + returns a dictionary of each material keyed by its ID. An OpenMOC geometry + may optionally be given and the routine will directly insert the multi-group + cross sections into each material in the geometry. If a geometry is passed + in, materials from the geometry will be used in place of those instantiated + by this routine. + + Parameters + ---------- + mgxs_lib : openmc.mgxs.Library + An OpenMC multi-group cross section library library + geometry : openmoc.Geometry, optional + An optional geometry populated with materials, cells, etc. + + Returns + ------- + materials : dict + A dictionary of Materials keyed by ID + + """ + + # Attempt to import openmc try: - data = imp.load_source(filename, filename).dataset - except IOError: - py_printf('ERROR', 'Unable to materialize file %s because it ' + \ - 'cannot be opened. Check the file path.',filename) - - # Check that the file has an 'energy groups' attribute - if not 'Energy Groups' in data.keys(): - py_printf('ERROR', 'Unable to materialize file %s since it does not ' + \ - 'contain an \'Energy Groups\' attribute', filename) - - num_groups = data['Energy Groups'] - - # Check that the number of energy groups is an integer - if not is_integer(num_groups): - py_printf('ERROR', 'Unable to materialize file %s since the number of' + \ - 'energy groups %s is not an integer', filename, str(num_groups)) - - data = data['Materials'] - material_names = data.keys() - - # Loop over each material and - for name in material_names: - - py_printf('INFO', 'Importing material %s', str(name)) - - new_material = openmoc.Material() - new_material.setNumEnergyGroups(int(num_groups)) - - if 'Total XS' in data[name].keys(): - new_material.setSigmaT(data[name]['Total XS']) - - if 'Scattering XS' in data[name].keys(): - new_material.setSigmaS(data[name]['Scattering XS']) - - if 'Fission XS' in data[name].keys(): - new_material.setSigmaF(data[name]['Fission XS']) - - if 'Nu Fission XS' in data[name].keys(): - new_material.setNuSigmaF(data[name]['Nu Fission XS']) - - if 'Chi' in data[name].keys(): - new_material.setChi(data[name]['Chi']) - - if 'Diffusion Coefficient' in data[name].keys(): - new_material.setDifCoef(data[name]['Diffusion Coefficient']) - - if 'Buckling' in data[name].keys(): - new_material.setBuckling(data[name]['Buckling']) - - if 'Absorption XS' in data[name].keys(): - new_material.setSigmaA(data[name]['Absorption XS']) - - # Add this material to the list - materials[name] = new_material - - - ############################################################################## - # UNSUPPORTED DATA FILE TYPES - ############################################################################## - else: - py_printf('ERROR', 'Unable to materialize using filename %s ' + \ - 'since it has an unkown extension. Supported ' + \ - 'extension types are .hdf5 and .py', filename) + import openmc + except ImportError: + py_printf('ERROR', 'The OpenMC code must be installed on your system') + + cv.check_type('mgxs_lib', mgxs_lib, openmc.mgxs.Library) + if geometry: + cv.check_type('geometry', geometry, openmoc.Geometry) + + # Instantiate dictionary to hold Materials to return to user + materials = {} + old_materials = {} + num_groups = mgxs_lib.num_groups + domain_type = mgxs_lib.domain_type + + # If a Geometry was passed in, extract all cells or materials from it + if geometry: + if domain_type == 'material': + domains = geometry.getAllMaterials() + elif domain_type == 'cell': + domains = geometry.getAllMaterialCells() + else: + py_printf('ERROR', 'Unable to load a cross sections library with ' + 'domain type %s', mgxs_lib.domain_type) + + # Iterate over all domains (e.g., materials or cells) in the HDF5 file + for domain in mgxs_lib.domains: + + py_printf('INFO', 'Importing cross sections for %s "%d"', + domain_type, domain.id) + + # If using an OpenMOC Geometry, extract a Material from it + if geometry: + + if domain_type == 'material': + material = _get_domain(domains, domain.id) + + # Ignore materials which cannot be found in the OpenMOC Geometry + if material is None: + continue + + elif domain_type == 'cell': + cell = _get_domain(domains, domain.id) + + # Ignore cells which cannot be found in the OpenMOC Geometry + if cell is None: + continue + else: + material = cell.getFillMaterial() + + # If the user filled multiple Cells with the same Material, + # the Material must be cloned for each unique Cell + if material != None: + if len(domains) > geometry.getNumMaterials(): + old_materials[material.getId()] = material + material = material.clone() + + # If the Cell does not contain a Material, create one for it + else: + material = openmoc.Material(id=domain.id) + + # Fill the Cell with the new Material + cell.setFill(material) + + # If not Geometry, instantiate a new Material with the ID/name + else: + material = openmoc.Material(id=domain.id) + + # Add material to the collection + materials[domain.id] = material + material.setNumEnergyGroups(num_groups) + + # Search for the total/transport cross section + if 'transport' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'transport') + sigma = mgxs.get_xs(nuclides='sum') + material.setSigmaT(sigma) + py_printf('INFO', 'Loaded "transport" MGXS for "%s %d"', + domain_type, domain.id) + elif 'total' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'total') + sigma = mgxs.get_xs(nuclides='sum') + material.setSigmaT(sigma) + py_printf('INFO', 'Loaded "total" MGXS for "%s %d"', + domain_type, domain.id) + else: + py_printf('WARNING', 'No "total" or "transport" MGXS found for' + '"%s %d"', domain_type, domain.id) + + # Search for the fission production cross section + if 'nu-fission' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'nu-fission') + sigma = mgxs.get_xs(nuclides='sum') + material.setNuSigmaF(sigma) + py_printf('INFO', 'Loaded "nu-fission" MGXS for "%s %d"', + domain_type, domain.id) + else: + py_printf('WARNING', 'No "nu-fission" MGXS found for' + '"%s %d"', domain_type, domain.id) + + # Search for the scattering matrix cross section + if 'nu-scatter matrix' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'nu-scatter matrix') + sigma = mgxs.get_xs(nuclides='sum').flatten() + material.setSigmaS(sigma) + py_printf('INFO', 'Loaded "nu-scatter matrix" MGXS for "%s %d"', + domain_type, domain.id) + elif 'scatter matrix' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'scatter matrix') + sigma = mgxs.get_xs(nuclides='sum').flatten() + material.setSigmaS(sigma) + py_printf('INFO', 'Loaded "scatter matrix" MGXS for "%s %d"', + domain_type, domain.id) + else: + py_printf('WARNING', 'No "scatter matrix" or "nu-scatter matrix" ' + 'found for "%s %d"', domain_type, domain.id) + + # Search for chi (fission spectrum) + if 'chi' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'chi') + chi = mgxs.get_xs(nuclides='sum') + material.setChi(chi) + py_printf('INFO', 'Loaded "chi" MGXS for "%s %d"', + domain_type, domain.id) + else: + py_printf('WARNING', 'No "chi" MGXS found for "%s %d"', + domain_type, domain.id) + + # Search for optional cross sections + if 'fission' in mgxs_lib.mgxs_types: + mgxs = mgxs_lib.get_mgxs(domain, 'fission') + sigma = mgxs.get_xs(nuclides='sum') + material.setSigmaF(sigma) + py_printf('INFO', 'Loaded "fission" MGXS for "%s %d"', + domain_type, domain.id) + + # Inform SWIG to garbage collect any old Materials from the Geometry + for material_id in old_materials: + old_materials[material_id].thisown = False + + # Return collection of materials + return materials + + +def compute_sph_factors(mgxs_lib, max_sph_iters=30, sph_tol=1E-5, + fix_src_tol=1E-5, num_azim=4, track_spacing=0.1, + zcoord=0.0, num_threads=1, throttle_output=True): + """Compute SPH factors for an OpenMC multi-group cross section library. + + This routine coputes SuPerHomogenisation (SPH) factors for an OpenMC MGXS + library. The SPH scheme is outlined by Alain Hebert in the following paper: + + Hebert, A., "A Consistent Technique for the Pin-by-Pin + Homogenization of a Pressurized Water Reactor Assembly." + Nuclear Science and Engineering, 113 (3), pp. 227-233, 1993. + + The SPH factors are needed to preserve reaction rates in heterogeneous + geometries. The energy condensation process leads to a bias between + ultrafine and coarse energy group calculations. This bias is a result of the + use of scalar flux-weighting to compute MGXS without properly accounting for + angular-dependence of the flux. + + Parameters + ---------- + mgxs_lib : openmc.mgxs.Library + An OpenMC multi-group cross section library + max_sph_iters : Integral + The maximum number of SPH iterations (default is 30) + sph_tol : Real + The tolerance on the SPH factor convergence (default is 1E-5) + fix_src_tol : Real + The tolerance on the MOC fixed source calculations (default is 1E-5_ + num_azim : Integral + The number of azimuthal angles (default is 4) + track_spacing : Real + The track spacing (default is 0.1 centimeters) + zcoord : Real + The coordinate on the z-axis (default is 0.) + num_threads : Real + The number of OpenMP threads (default is 1) + throttle_output : bool + Whether to suppress output from fixed source calculations (default is True) + + Returns + ------- + fsrs_to_sph : numpy.ndarray of Real + A NumPy array of SPH factors indexed by FSR and energy group + sph_mgxs_lib : openmc.mgxs.Library + A OpenMC MGXS library with the SPH factors applied to each MGXS + sph_to_fsrs_indices : numpy.ndarray of Integral + A NumPy array of all fissionable FSRs to which SPH factors were applied + + """ + + import openmc.mgxs + + cv.check_type('mgxs_lib', mgxs_lib, openmc.mgxs.Library) + + # For Python 2.X.X + if sys.version_info[0] == 2: + from opencg_compatible import get_openmoc_geometry + from process import get_scalar_fluxes + # For Python 3.X.X + else: + from openmoc.opencg_compatible import get_openmoc_geometry + from openmoc.process import get_scalar_fluxes + + py_printf('NORMAL', 'Computing SPH factors...') + + # Create an OpenMOC Geometry from the OpenCG Geometry + geometry = get_openmoc_geometry(mgxs_lib.opencg_geometry) + + # Load the MGXS library data into the OpenMOC geometry + load_openmc_mgxs_lib(mgxs_lib, geometry) + + # Initialize an OpenMOC TrackGenerator + track_generator = openmoc.TrackGenerator(geometry, num_azim, track_spacing) + track_generator.setZCoord(zcoord) + track_generator.generateTracks() + + # Initialize an OpenMOC Solver + solver = openmoc.CPUSolver(track_generator) + solver.setConvergenceThreshold(fix_src_tol) + solver.setNumThreads(num_threads) + openmc_fluxes = _load_openmc_src(mgxs_lib, solver) + + # Initialize SPH factors + num_groups = geometry.getNumEnergyGroups() + num_fsrs = geometry.getNumFSRs() + + # Map FSRs to domains (and vice versa) to compute domain-averaged fluxes + fsrs_to_domains = np.zeros(num_fsrs) + domains_to_fsrs = collections.defaultdict(list) + sph_to_fsr_indices = [] + + for fsr in range(num_fsrs): + cell = geometry.findCellContainingFSR(fsr) + + if mgxs_lib.domain_type == 'material': + domain = cell.getFillMaterial() + else: + domain = cell + + fsrs_to_domains[fsr] = domain.getId() + domains_to_fsrs[domain.getId()].append(fsr) + + if domain.isFissionable(): + sph_to_fsr_indices.append(fsr) + + # Get all OpenMOC domains + if mgxs_lib.domain_type == 'material': + openmoc_domains = geometry.getAllMaterials() + elif mgxs_lib.domain_type == 'cell': + openmoc_domains = geometry.getAllMaterialCells() + else: + py_printf('ERROR', 'SPH factors cannot be applied for an OpenMC MGXS ' + 'library of domain type %s', mgxs_lib.domain_type) + + # Build a list of indices into the SPH array for fissionable domains + sph_to_domain_indices = [] + for i, openmc_domain in enumerate(mgxs_lib.domains): + if openmc_domain.id in openmoc_domains: + openmoc_domain = openmoc_domains[openmc_domain.id] + if openmoc_domain.isFissionable(): + sph_to_domain_indices.append(i) + + py_printf('NORMAL', 'Computing SPH factors for %d "%s" domains', + len(sph_to_domain_indices), mgxs_lib.domain_type) + + # Initialize array of domain-averaged fluxes and SPH factors + num_domains = len(mgxs_lib.domains) + openmoc_fluxes = np.zeros((num_domains, num_groups)) + sph = np.ones((num_domains, num_groups)) + + # Store starting verbosity log level + log_level = openmoc.get_log_level() + + # SPH iteration loop + for i in range(max_sph_iters): + + # Run fixed source calculation with suppressed output + if throttle_output: + openmoc.set_log_level('WARNING') + + # Fixed source calculation + solver.computeFlux() + + # Restore log output level + if throttle_output: + openmoc.set_log_level(log_level) + + # Extract the FSR scalar fluxes + fsr_fluxes = get_scalar_fluxes(solver) + + # Compute the domain-averaged flux in each energy group + for j, openmc_domain in enumerate(mgxs_lib.domains): + domain_fluxes = fsr_fluxes[fsrs_to_domains == openmc_domain.id, :] + openmoc_fluxes[j, :] = np.mean(domain_fluxes, axis=0) + + # Compute SPH factors + old_sph = np.copy(sph) + sph = openmc_fluxes / openmoc_fluxes + sph = np.nan_to_num(sph) + sph[sph == 0.0] = 1.0 + + # Compute SPH factor residuals + res = np.abs((sph - old_sph) / old_sph) + res = np.nan_to_num(res) + + # Extract residuals for fissionable domains only + res = res[sph_to_domain_indices, :] + + # Report maximum SPH factor residual + py_printf('NORMAL', 'SPH Iteration %d:\tres = %1.3e', i, res.max()) + + # Create a new MGXS library with cross sections updated by SPH factors + sph_mgxs_lib = _apply_sph_factors(mgxs_lib, geometry, sph) + + # Load the new MGXS library data into the OpenMOC geometry + load_openmc_mgxs_lib(sph_mgxs_lib, geometry) + + # Check max SPH factor residual for this domain for convergence + if res.max() < sph_tol: + break + + # Warn user if SPH factors did not converge + else: + py_printf('WARNING', 'SPH factors did not converge') + + # Collect SPH factors for each FSR, energy group + fsrs_to_sph = np.ones((num_fsrs, num_groups), dtype=np.float) + for i, openmc_domain in enumerate(mgxs_lib.domains): + if openmc_domain.id in openmoc_domains: + openmoc_domain = openmoc_domains[openmc_domain.id] + if openmoc_domain.isFissionable(): + fsr_ids = domains_to_fsrs[openmc_domain.id] + fsrs_to_sph[fsr_ids,:] = sph[i,:] + + return fsrs_to_sph, sph_mgxs_lib, np.array(sph_to_fsr_indices) + + +def _load_openmc_src(mgxs_lib, solver): + """Assign fixed sources to an OpenMOC model from an OpenMC MGXS library. + + This routine computes the fission production and scattering source in + each domain in an OpenMC MGXS library and assigns it as a fixed source + for an OpenMOC calculation. This is a helper routine for the + compute_sph_factors(...) routine. + + Parameters + ---------- + mgxs_lib : openmc.mgxs.Library object + An OpenMC multi-group cross section library + solver : openmoc.Solver + An OpenMOC solver into which to load the fixed sources + + Returns + ------- + openmc_fluxes : numpy.ndarray of Real + A NumPy array of the OpenMC fluxes indexed by domain and energy group + + """ + + # Retrieve dictionary of OpenMOC domains corresponding to OpenMC domains + geometry = solver.getGeometry() + if mgxs_lib.domain_type == 'material': + openmoc_domains = geometry.getAllMaterials() + else: + openmoc_domains = geometry.getAllCells() + + # Create variables for the number of domains and energy groups + num_groups = geometry.getNumEnergyGroups() + num_domains = len(mgxs_lib.domains) + openmc_fluxes = np.zeros((num_domains, num_groups)) + keff = mgxs_lib.keff + + # Create mapping of FSRs-to-domains to optimize fixed source setup + domains_to_fsrs = collections.defaultdict(list) + for fsr_id in range(geometry.getNumFSRs()): + cell = geometry.findCellContainingFSR(fsr_id) + if mgxs_lib.domain_type == 'material': + domain = cell.getFillMaterial() + else: + domain = cell + domains_to_fsrs[domain.getId()].append(fsr_id) + + # Compute fixed sources for all domains in the MGXS library + for i, openmc_domain in enumerate(mgxs_lib.domains): + + # Ignore domains which cannot be found in the OpenMOC Geometry + if openmc_domain.id not in openmoc_domains: + continue + + # Get OpenMOC domain corresponding to the OpenMC domain + openmoc_domain = openmoc_domains[openmc_domain.id] + + # If this domain is not found in the OpenMOC geometry, ignore it + if openmoc_domain.getNumInstances() == 0: + continue + + # Compute the total volume filled by this domain throughout the geometry + tot_volume = openmoc_domain.getVolume() + + # Extract an openmc.mgxs.MGXS object for the scattering matrix + if 'nu-scatter matrix' in mgxs_lib.mgxs_types: + scatter = mgxs_lib.get_mgxs(openmoc_domain.getId(), + 'nu-scatter matrix') + elif 'scatter matrix' in mgxs_lib.mgxs_types: + scatter = mgxs_lib.get_mgxs(openmoc_domain.getId(), + 'scatter matrix') + else: + py_printf('ERROR', 'Unable to compute SPH factors for an OpenMC ' + 'MGXS library without scattering matrices') + + # Extract an openmc.mgxs.MGXS object for the nu-fission cross section + if 'nu-fission' in mgxs_lib.mgxs_types: + nu_fission = mgxs_lib.get_mgxs(openmoc_domain.getId(), 'nu-fission') + else: + py_printf('ERROR', 'Unable to compute SPH factors for an OpenMC ' + 'MGXS library without nu-fission cross sections') + + # Extract an openmc.mgxs.MGXS object for the chi fission spectrum + if 'chi' in mgxs_lib.mgxs_types: + chi = mgxs_lib.get_mgxs(openmoc_domain.getId(), 'chi') + else: + py_printf('ERROR', 'Unable to compute SPH factors for an OpenMC ' + 'MGXS library without chi fission spectrum') + + # Retrieve the OpenMC volume-integrated flux for this domain from + # the nu-fission MGXS and store it for SPH factor calculation + flux = nu_fission.tallies['flux'].mean.flatten() + openmc_fluxes[i, :] = np.atleast_1d(np.flipud(flux)) + openmc_fluxes[i, :] /= tot_volume + + # Extract a NumPy array for each MGXS summed across all nuclides + scatter = scatter.get_xs(nuclides='sum') + nu_fission = nu_fission.get_xs(nuclides='sum') + chi = chi.get_xs(nuclides='sum') + + # Compute and store volume-averaged fission + scatter sources + for group in range(num_groups): + + # Compute the source for this group from fission and scattering + in_scatter = scatter[:, group] * openmc_fluxes[i, :] + fission = (chi[group] / keff) * nu_fission * openmc_fluxes[i, :] + source = np.sum(in_scatter) + np.sum(fission) + + # Assign the source to this domain + fsr_ids = domains_to_fsrs[openmoc_domain.getId()] + for fsr_id in fsr_ids: + solver.setFixedSourceByFSR(fsr_id, group+1, source) + + return openmc_fluxes + + +def _apply_sph_factors(mgxs_lib, geometry, sph): + """Apply SPH factors to an OpenMC MGXS library. + + This is a helper routine for the compute_sph_factors(...) routine. + + Parameters + ---------- + mgxs_lib : openmc.mgxs.Library + An OpenMC multi-group cross section library + geometry : openmoc.Geometry + An OpenMOC geometry + sph : numpy.ndarray of Real + A NumpPy array of SPH factors for each domain and energy group + + Returns + ------- + sph_mgxs_lib : openmc.mgxs.Library + A new OpenMC MGXS library with SPH factors applied to all MGXS + + """ + + # Create a copy of the MGXS library to apply SPH factors + sph_mgxs_lib = copy.deepcopy(mgxs_lib) + + # Get all OpenMOC domains + if mgxs_lib.domain_type == 'material': + openmoc_domains = geometry.getAllMaterials() + else: + openmoc_domains = geometry.getAllMaterialCells() + + # Loop over all domains + for i, openmc_domain in enumerate(mgxs_lib.domains): + + # Ignore domains which cannot be found in the OpenMOC Geometry + if openmc_domain.id not in openmoc_domains: + continue + + # Get OpenMOC domain corresponding to the OpenMC domain + openmoc_domain = openmoc_domains[openmc_domain.id] + + # Ignore non-fissionable domains + if not openmoc_domain.isFissionable(): + continue + + # Loop over all cross section types in the MGXS library + for mgxs_type in sph_mgxs_lib.mgxs_types: + + # Do not update the chi fission spectrum with SPH factors + if mgxs_type == 'chi': + continue + + # Extract the openmc.mgxs.MGXS object from the input library + mgxs = mgxs_lib.get_mgxs(openmoc_domain.getId(), mgxs_type) + + # Extract the openmc.mgxs.MGXS object to update with SPH factors + sph_mgxs = sph_mgxs_lib.get_mgxs(openmoc_domain.getId(), mgxs_type) + + # Extract the OpenMC derived Tally for the MGXS + tally = mgxs.xs_tally + sph_tally = sph_mgxs.xs_tally + flip_sph = np.flipud(sph[i,:]) + # If this is a scattering matrix, repeat for all outgoing groups + if 'scatter matrix' in mgxs_type: + flip_sph = np.repeat(flip_sph, mgxs_lib.num_groups) + # Apply SPH factors to the MGXS in each nuclide, group + sph_tally._mean = tally.mean * flip_sph[:, np.newaxis, np.newaxis] + sph_tally._std_dev = \ + tally.std_dev * flip_sph[:, np.newaxis, np.newaxis]**2 - # Return the list of materials - return materials + return sph_mgxs_lib diff --git a/openmoc/numpy.i b/openmoc/numpy.i index f2714cc34..3742c4cf9 100644 --- a/openmoc/numpy.i +++ b/openmoc/numpy.i @@ -996,7 +996,7 @@ size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } - + if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); @@ -1232,7 +1232,7 @@ size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } - + if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); @@ -1634,7 +1634,7 @@ size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } - + if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); @@ -1819,7 +1819,7 @@ size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } - + if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); @@ -2402,7 +2402,7 @@ %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif - + %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else @@ -2436,7 +2436,7 @@ %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif - + %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else diff --git a/openmoc/numpy_typemaps.i b/openmoc/numpy_typemaps.i new file mode 100644 index 000000000..6aa693618 --- /dev/null +++ b/openmoc/numpy_typemaps.i @@ -0,0 +1,77 @@ +/** Helper typemaps to enable array-based user input to be defined with + * NumPy arrays for the default build configuration of OpenMOC */ + +%module numpy_typemaps + +%include "numpy.i" + +%init %{ + import_array(); +%} + +/* The typemap used to match the method signature for the + * Lattice::setLatticeCells setter method. This allows users to set the lattice + * cells (universe IDs) using a 2D NumPy array */ +%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} + +/* The typemap used to match the method signature for the + * Cmfd::setGroupStructure method. This allows users to set the CMFD group + * structure using a NumPy array */ +%apply (int* IN_ARRAY1, int DIM1) {(int* group_indices, int length_group_indices)} + +/* The typemap used to match the method signature for the Material + * cross-section setter methods. This allows users to set the cross-sections + * using NumPy arrays */ +%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} + +/* The typemap used to match the method signature for the Cell rotation + * angle setter method. This allows users to set the rotation angles + * using NumPy arrays */ +%apply (double* IN_ARRAY1, int DIM1) {(double* rotation, int num_axes)} + +/* The typemap used to match the method signature for the Cell translation + * setter method. This allows users to set translations using NumPy arrays */ +%apply (double* IN_ARRAY1, int DIM1) {(double* translation, int num_axes)} + +/* The typemap used to match the method signature for the Cell's + * getter method for rotations used by the OpenCG compatibility module. */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* rotations, int num_axes)} + +/* The typemap used to match the method signature for the Cell's + * getter method for translations used by the OpenCG compatibility module. */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* translations, int num_axes)} + +/* The typemap used to match the method signature for the TrackGenerator's + * getter methods for track start and end coordinates for the plotting + * routines in openmoc.plotter */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} + +/* The typemap used to match the method signature for the TrackGenerator's + * getter methods for track segment start and end coordinates for the plotting + * routines in openmoc.plotter */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} + +/* The typemap used to match the method signature for the Solver's + * computeFSRFissionRates method for the data processing routines in + * openmoc.process */ +%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} + +/* The typemap used to match the method signature for the Universe's + * getCellIds method for the data processing routines in openmoc.process */ +%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} + +/* The typemap used to match the method signature for the + * PolarQuad::setSinThetas method. This allows users to set the polar angle + * quadrature sine thetas using a NumPy array */ +%apply (double* IN_ARRAY1, int DIM1) {(double* sin_thetas, int num_polar)} + +/* The typemap used to match the method signature for the + * PolarQuad::setWeights method. This allows users to set the polar angle + * quadrature weights using a NumPy array */ +%apply (double* IN_ARRAY1, int DIM1) {(double* weights, int num_polar)} + +/* The typemap used to match the method signature for Solver::getFluxes */ +%apply (FP_PRECISION* ARGOUT_ARRAY1, int DIM1) {(FP_PRECISION* out_fluxes, int num_fluxes)} + +/* The typemap used to match the method signature for Solver::setFluxes */ +%apply (FP_PRECISION* INPLACE_ARRAY1, int DIM1) {(FP_PRECISION* in_fluxes, int num_fluxes)} diff --git a/openmoc/opencg_compatible.py b/openmoc/opencg_compatible.py new file mode 100644 index 000000000..a8f9a4649 --- /dev/null +++ b/openmoc/opencg_compatible.py @@ -0,0 +1,1058 @@ +#!/usr/bin/env python + +import copy +import sys +import numpy as np + +import openmoc +import opencg + +# For Python 2.X.X +if sys.version_info[0] == 2: + import checkvalue as cv +# For Python 3.X.X +else: + import openmoc.checkvalue as cv + + +# A dictionary of all OpenMOC Materials created +# Keys - Material IDs +# Values - Materials +OPENMOC_MATERIALS = dict() + +# A dictionary of all OpenCG Materials created +# Keys - Material IDs +# Values - Materials +OPENCG_MATERIALS = dict() + +# A dictionary of all OpenMOC Surfaces created +# Keys - Surface IDs +# Values - Surfaces +OPENMOC_SURFACES = dict() + +# A dictionary of all OpenCG Surfaces created +# Keys - Surface IDs +# Values - Surfaces +OPENCG_SURFACES = dict() + +# A dictionary of all OpenMOC Cells created +# Keys - Cell IDs +# Values - Cells +OPENMOC_CELLS = dict() + +# A dictionary of all OpenCG Cells created +# Keys - Cell IDs +# Values - Cells +OPENCG_CELLS = dict() + +# A dictionary of all OpenMOC Universes created +# Keys - Universes IDs +# Values - Universes +OPENMOC_UNIVERSES = dict() + +# A dictionary of all OpenCG Universes created +# Keys - Universes IDs +# Values - Universes +OPENCG_UNIVERSES = dict() + +# A dictionary of all OpenMOC Lattices created +# Keys - Lattice IDs +# Values - Lattices +OPENMOC_LATTICES = dict() + +# A dictionary of all OpenCG Lattices created +# Keys - Lattice IDs +# Values - Lattices +OPENCG_LATTICES = dict() + + + +def get_opencg_material(openmoc_material): + """Return an OpenCG material corresponding to an OpenMOC material. + + Parameters + ---------- + openmoc_material : openmoc.Material + OpenMOC material + + Returns + ------- + opencg_material : opencg.Material + Equivalent OpenCG material + + """ + + cv.check_type('openmoc_material', openmoc_material, openmoc.Material) + + global OPENCG_MATERIALS + material_id = openmoc_material.getId() + + # If this Material was already created, use it + if material_id in OPENCG_MATERIALS: + return OPENCG_MATERIALS[material_id] + + # Create an OpenCG Material to represent this OpenMOC Material + name = openmoc_material.getName() + opencg_material = opencg.Material(material_id=material_id, name=name) + + # Add the OpenMOC Material to the global collection of all OpenMOC Materials + OPENMOC_MATERIALS[material_id] = openmoc_material + + # Add the OpenCG Material to the global collection of all OpenCG Materials + OPENCG_MATERIALS[material_id] = opencg_material + + return opencg_material + + +def get_openmoc_material(opencg_material): + """Return an OpenMOC material corresponding to an OpenCG material. + + Parameters + ---------- + opencg_material : opencg.Material + OpenCG material + + Returns + ------- + openmoc_material : openmoc.Material + Equivalent OpenMOC material + + """ + + cv.check_type('opencg_material', opencg_material, opencg.Material) + + global OPENMOC_MATERIALS + material_id = opencg_material.id + + # If this Material was already created, use it + if material_id in OPENMOC_MATERIALS: + return OPENMOC_MATERIALS[material_id] + + # Create an OpenMOC Material to represent this OpenCG Material + name = str(opencg_material.name) + openmoc_material = openmoc.Material(id=material_id, name=name) + + # Add the OpenMOC Material to the global collection of all OpenMOC Materials + OPENMOC_MATERIALS[material_id] = openmoc_material + + # Add the OpenCG Material to the global collection of all OpenCG Materials + OPENCG_MATERIALS[material_id] = opencg_material + + return openmoc_material + + +def is_opencg_surface_compatible(opencg_surface): + """Determine whether OpenCG surface is compatible with OpenMOC geometry. + + A surface is considered compatible if there is a one-to-one correspondence + between OpenMOC and OpenCG surface types. Note that some OpenCG surfaces, + e.g. SquarePrism, do not have a one-to-one correspondence with OpenMOC + surfaces but can still be converted into an equivalent collection of + OpenMOC surfaces. + + Parameters + ---------- + opencg_surface : opencg.Surface + OpenCG surface + + Returns + ------- + bool + Whether OpenCG surface is compatible with OpenMOC + + """ + + cv.check_type('opencg_surface', opencg_surface, opencg.Surface) + + if opencg_surface.type in ['z-squareprism']: + return False + else: + return True + + +def get_opencg_surface(openmoc_surface): + """Return an OpenCG surface corresponding to an OpenMOC surface. + + Parameters + ---------- + openmc_surface : openmoc.Surface + OpenMOC surface + + Returns + ------- + opencg_surface : opencg.Surface + Equivalent OpenCG surface + + """ + + cv.check_type('openmoc_surface', openmoc_surface, openmoc.Surface) + + global OPENCG_SURFACES + surface_id = openmoc_surface.getId() + + # If this Surface was already created, use it + if surface_id in OPENCG_SURFACES: + return OPENCG_SURFACES[surface_id] + + # Create an OpenCG Surface to represent this OpenMOC Surface + name = openmoc_surface.getName() + + # Correct for OpenMOC's syntax for Surfaces dividing Cells + boundary = openmoc_surface.getBoundaryType() + if boundary == openmoc.VACUUM: + boundary = 'vacuum' + elif boundary == openmoc.REFLECTIVE: + boundary = 'reflective' + elif boundary == openmoc.BOUNDARY_NONE: + boundary = 'interface' + + opencg_surface = None + surface_type = openmoc_surface.getSurfaceType() + + if surface_type == openmoc.PLANE: + openmoc_surface = openmoc.castSurfaceToPlane(openmoc_surface) + A = openmoc_surface.getA() + B = openmoc_surface.getB() + C = openmoc_surface.getC() + D = openmoc_surface.getD() + opencg_surface = opencg.Plane(surface_id, name, boundary, A, B, C, D) + + elif surface_type == openmoc.XPLANE: + openmoc_surface = openmoc.castSurfaceToXPlane(openmoc_surface) + x0 = openmoc_surface.getX() + opencg_surface = opencg.XPlane(surface_id, name, boundary, x0) + + elif surface_type == openmoc.YPLANE: + openmoc_surface = openmoc.castSurfaceToYPlane(openmoc_surface) + y0 = openmoc_surface.getY() + opencg_surface = opencg.YPlane(surface_id, name, boundary, y0) + + elif surface_type == openmoc.ZPLANE: + openmoc_surface = openmoc.castSurfaceToZPlane(openmoc_surface) + z0 = openmoc_surface.getZ() + opencg_surface = opencg.ZPlane(surface_id, name, boundary, z0) + + elif surface_type == openmoc.ZCYLINDER: + openmoc_surface = openmoc.castSurfaceToZCylinder(openmoc_surface) + x0 = openmoc_surface.getX0() + y0 = openmoc_surface.getY0() + R = openmoc_surface.getRadius() + opencg_surface = opencg.ZCylinder(surface_id, name, boundary, x0, y0, R) + + # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces + OPENMOC_SURFACES[surface_id] = openmoc_surface + + # Add the OpenCG Surface to the global collection of all OpenCG Surfaces + OPENCG_SURFACES[surface_id] = opencg_surface + + return opencg_surface + + +def get_openmoc_surface(opencg_surface): + """Return an OpenMOC surface corresponding to an OpenCG surface. + + Parameters + ---------- + opencg_surface : opencg.Surface + OpenCG surface + + Returns + ------- + openmoc_surface : openmoc.Surface + Equivalent OpenMOC surface + + """ + + cv.check_type('opencg_surface', opencg_surface, opencg.Surface) + + global OPENMOC_SURFACES + surface_id = opencg_surface.id + + # If this Surface was already created, use it + if surface_id in OPENMOC_SURFACES: + return OPENMOC_SURFACES[surface_id] + + # Create an OpenMOC Surface to represent this OpenCG Surface + name = str(opencg_surface.name) + + # Correct for OpenMOC's syntax for Surfaces dividing Cells + boundary = opencg_surface.boundary_type + if boundary == 'vacuum': + boundary = openmoc.VACUUM + elif boundary == 'reflective': + boundary = openmoc.REFLECTIVE + elif boundary == 'interface': + boundary = openmoc.BOUNDARY_NONE + + if opencg_surface.type == 'plane': + A = opencg_surface.a + B = opencg_surface.b + C = opencg_surface.c + D = opencg_surface.d + openmoc_surface = openmoc.Plane(A, B, C, D, surface_id, name) + + elif opencg_surface.type == 'x-plane': + x0 = opencg_surface.x0 + openmoc_surface = openmoc.XPlane(x0, int(surface_id), name) + + elif opencg_surface.type == 'y-plane': + y0 = opencg_surface.y0 + openmoc_surface = openmoc.YPlane(y0, surface_id, name) + + elif opencg_surface.type == 'z-plane': + z0 = opencg_surface.z0 + openmoc_surface = openmoc.ZPlane(z0, surface_id, name) + + elif opencg_surface.type == 'z-cylinder': + x0 = opencg_surface.x0 + y0 = opencg_surface.y0 + R = opencg_surface.r + openmoc_surface = openmoc.ZCylinder(x0, y0, R, surface_id, name) + + else: + msg = 'Unable to create an OpenMOC Surface from an OpenCG ' \ + 'Surface of type {0} since it is not a compatible ' \ + 'Surface type in OpenMOC'.format(opencg_surface.type) + raise ValueError(msg) + + # Set the boundary condition for this Surface + openmoc_surface.setBoundaryType(boundary) + + # Add the OpenMOC Surface to the global collection of all OpenMOC Surfaces + OPENMOC_SURFACES[surface_id] = openmoc_surface + + # Add the OpenCG Surface to the global collection of all OpenCG Surfaces + OPENCG_SURFACES[surface_id] = opencg_surface + + return openmoc_surface + + +def get_compatible_opencg_surfaces(opencg_surface): + """Generate OpenCG surfaces that are compatible with OpenMOC equivalent to + an OpenCG surface that is not compatible. For example, this method may be + used to convert a ZSquarePrism OpenCG surface into a collection of + equivalent XPlane and YPlane OpenCG surfaces. + + Parameters + ---------- + opencg_surface : opencg.Surface + OpenCG surface that is incompatible with OpenMOC + + Returns + ------- + surfaces : list of opencg.Surface + Collection of surfaces equivalent to the original one but compatible + with OpenMOC + + """ + + cv.check_type('opencg_surface', opencg_surface, opencg.Surface) + + global OPENMOC_SURFACES + surface_id = opencg_surface.id + + # If this Surface was already created, use it + if surface_id in OPENMOC_SURFACES: + return OPENMOC_SURFACES[surface_id] + + # Create an OpenMOC Surface to represent this OpenCG Surface + name = str(opencg_surface.name) + + # Correct for OpenMOC's syntax for Surfaces dividing Cells + boundary = opencg_surface.boundary_type + + if opencg_surface.type == 'x-squareprism': + y0 = opencg_surface.y0 + z0 = opencg_surface.z0 + R = opencg_surface.r + + # Create a list of the four planes we need + min_y = opencg.YPlane(y0=y0-R, name=name) + max_y = opencg.YPlane(y0=y0+R, name=name) + min_z = opencg.ZPlane(z0=z0-R, name=name) + max_z = opencg.ZPlane(z0=z0+R, name=name) + + # Set the boundary conditions for each Surface + min_y.boundary_type = boundary + max_y.boundary_type = boundary + min_z.boundary_type = boundary + max_z.boundary_type = boundary + + surfaces = [min_y, max_y, min_z, max_z] + + elif opencg_surface.type == 'y-squareprism': + x0 = opencg_surface.x0 + z0 = opencg_surface.z0 + R = opencg_surface.r + + # Create a list of the four planes we need + min_x = opencg.XPlane(name=name, boundary=boundary, x0=x0-R) + max_x = opencg.XPlane(name=name, boundary=boundary, x0=x0+R) + min_z = opencg.ZPlane(name=name, boundary=boundary, z0=z0-R) + max_z = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R) + + # Set the boundary conditions for each Surface + min_x.boundary_type = boundary + max_x.boundary_type = boundary + min_z.boundary_type = boundary + max_z.boundary_type = boundary + + surfaces = [min_x, max_x, min_z, max_z] + + elif opencg_surface.type == 'z-squareprism': + x0 = opencg_surface.x0 + y0 = opencg_surface.y0 + R = opencg_surface.r + + # Create a list of the four planes we need + min_x = opencg.XPlane(name=name, boundary=boundary, x0=x0-R) + max_x = opencg.XPlane(name=name, boundary=boundary, x0=x0+R) + min_y = opencg.YPlane(name=name, boundary=boundary, y0=y0-R) + max_y = opencg.YPlane(name=name, boundary=boundary, y0=y0+R) + + # Set the boundary conditions for each Surface + min_x.boundary_type = boundary + max_x.boundary_type = boundary + min_y.boundary_type = boundary + max_y.boundary_type = boundary + + surfaces = [min_x, max_x, min_y, max_y] + + else: + msg = 'Unable to create a compatible OpenMOC Surface an OpenCG ' \ + 'Surface of type "{0}" since it already a compatible ' \ + 'Surface type in OpenMOC'.format(opencg_surface.type) + raise ValueError(msg) + + # Add the OpenMOC Surface(s) to global collection of all OpenMOC Surfaces + OPENMOC_SURFACES[surface_id] = surfaces + + # Add the OpenCG Surface to the global collection of all OpenCG Surfaces + OPENCG_SURFACES[surface_id] = opencg_surface + + return surfaces + + +def get_opencg_cell(openmoc_cell): + """Return an OpenCG cell corresponding to an OpenMOC cell. + + Parameters + ---------- + openmoc_cell : openmoc.Cell + OpenMOC cell + + Returns + ------- + opencg_cell : opencg.Cell + Equivalent OpenCG cell + + """ + + cv.check_type('openmoc_cell', openmoc_cell, openmoc.Cell) + + global OPENCG_CELLS + cell_id = openmoc_cell.getId() + + # If this Cell was already created, use it + if cell_id in OPENCG_CELLS: + return OPENCG_CELLS[cell_id] + + # Create an OpenCG Cell to represent this OpenMOC Cell + name = openmoc_cell.getName() + opencg_cell = opencg.Cell(cell_id, name) + + if (openmoc_cell.getType() == openmoc.MATERIAL): + fill = openmoc_cell.getFillMaterial() + opencg_cell.fill = get_opencg_material(fill) + elif (openmoc_cell.getType() == openmoc.FILL): + fill = openmoc_cell.getFillUniverse() + if isinstance(fill, openmoc.Lattice): + opencg_cell.fill = get_opencg_lattice(fill) + else: + opencg_cell.fill = get_opencg_universe(fill) + + if openmoc_cell.isRotated(): + rotation = openmoc_cell.getRotation(3) + opencg_cell.rotation = rotation + if openmoc_cell.isTranslated(): + translation = openmoc_cell.getTranslation(3) + opencg_cell.translation = translation + + surfaces = openmoc_cell.getSurfaces() + + for surf_id, surface_halfspace in surfaces.items(): + halfspace = surface_halfspace._halfspace + surface = surface_halfspace._surface + opencg_cell.add_surface(get_opencg_surface(surface), halfspace) + + # Add the OpenMOC Cell to the global collection of all OpenMOC Cells + OPENMOC_CELLS[cell_id] = openmoc_cell + + # Add the OpenCG Cell to the global collection of all OpenCG Cells + OPENCG_CELLS[cell_id] = opencg_cell + + return opencg_cell + + +def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace): + """Generate OpenCG cells that are compatible with OpenMOC equivalent to an + OpenCG cell that is not compatible. + + Parameters + ---------- + opencg_cell : opencg.Cell + OpenCG cell + opencg_surface : opencg.Surface + OpenCG surface that causes the incompatibility, e.g. an instance of + XSquarePrism + halfspace : {-1, 1} + Which halfspace defined by the surface is contained in the cell + + Returns + ------- + compatible_cells : list of opencg.Cell + Collection of cells equivalent to the original one but compatible with + OpenMC + + """ + + cv.check_type('opencg_cell', opencg_cell, opencg.Cell) + cv.check_type('opencg_surface', opencg_surface, opencg.Surface) + cv.check_value('halfspace', halfspace, (-1, +1)) + + # Initialize an empty list for the new compatible cells + compatible_cells = list() + + # SquarePrism Surfaces + if opencg_surface.type in ['x-squareprism', 'y-squareprism', + 'z-squareprism']: + + # Get the compatible Surfaces (XPlanes and YPlanes) + compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface) + + opencg_cell.remove_surface(opencg_surface) + + # If Cell is inside SquarePrism, add "inside" of Surface halfspaces + if halfspace == -1: + opencg_cell.add_surface(compatible_surfaces[0], +1) + opencg_cell.add_surface(compatible_surfaces[1], -1) + opencg_cell.add_surface(compatible_surfaces[2], +1) + opencg_cell.add_surface(compatible_surfaces[3], -1) + compatible_cells.append(opencg_cell) + + # If Cell is outside the SquarePrism (positive halfspace), add "outside" + # of Surface halfspaces. Since OpenMOC does not have a SquarePrism + # Surface, individual Cells are created for the 8 Cells that make up the + # outer region of a SquarePrism. + # | | + # 0 | 1 | 2 + # ______|____________________|______ + # | SquarePrism | + # 7 | (-) halfspace | 3 + # ______|____________________|______ + # | | + # 6 | 5 | 4 + # | | + else: + + # Create 8 Cell clones to represent each of the disjoint planar + # Surface halfspace intersections + num_clones = 8 + + for clone_id in range(num_clones): + + # Create a cloned OpenCG Cell with Surfaces compatible with OpenMOC + clone = opencg_cell.clone() + compatible_cells.append(clone) + + # Top left subcell (subcell 0) + if clone_id == 0: + clone.add_surface(compatible_surfaces[0], -1) + clone.add_surface(compatible_surfaces[3], +1) + + # Top center subcell (subcell 1) + elif clone_id == 1: + clone.add_surface(compatible_surfaces[0], +1) + clone.add_surface(compatible_surfaces[1], -1) + clone.add_surface(compatible_surfaces[3], +1) + + # Top right subcell (subcell 2) + elif clone_id == 2: + clone.add_surface(compatible_surfaces[1], +1) + clone.add_surface(compatible_surfaces[3], +1) + + # Right center subcell (subcell 3) + elif clone_id == 3: + clone.add_surface(compatible_surfaces[1], +1) + clone.add_surface(compatible_surfaces[3], -1) + clone.add_surface(compatible_surfaces[2], +1) + + # Bottom right subcell (subcell 4) + elif clone_id == 4: + clone.add_surface(compatible_surfaces[1], +1) + clone.add_surface(compatible_surfaces[2], -1) + + # Bottom center subcell (subcell 5) + elif clone_id == 5: + clone.add_surface(compatible_surfaces[0], +1) + clone.add_surface(compatible_surfaces[1], -1) + clone.add_surface(compatible_surfaces[2], -1) + + # Bottom left subcell (subcell 6) + elif clone_id == 6: + clone.add_surface(compatible_surfaces[0], -1) + clone.add_surface(compatible_surfaces[2], -1) + + # Left center subcell (subcell 7) + elif clone_id == 7: + clone.add_surface(compatible_surfaces[0], -1) + clone.add_surface(compatible_surfaces[3], -1) + clone.add_surface(compatible_surfaces[2], +1) + + # Remove redundant Surfaces from the Cells + for cell in compatible_cells: + cell.remove_redundant_surfaces() + + # Return the list of compatible OpenCG Cells + return compatible_cells + + +def make_opencg_cells_compatible(opencg_universe): + """Make all cells in an OpenCG universe compatible with OpenMOC. + + Parameters + ---------- + opencg_universe : opencg.Universe + Universe to check + + """ + + if isinstance(opencg_universe, opencg.Lattice): + return + + cv.check_type('opencg_universe', opencg_universe, opencg.Universe) + + # Check all OpenCG Cells in this Universe for compatibility with OpenMOC + opencg_cells = opencg_universe.cells + + for cell_id, opencg_cell in opencg_cells.items(): + + # Check each of the OpenCG Surfaces for OpenMOC compatibility + surfaces = opencg_cell.surfaces + + for surface_id in surfaces: + surface = surfaces[surface_id][0] + halfspace = surfaces[surface_id][1] + + # If this Surface is not compatible with OpenMOC, create compatible + # OpenCG cells with a compatible version of this OpenCG Surface + if not is_opencg_surface_compatible(surface): + + # Get the one or more OpenCG Cells compatible with OpenMOC + # NOTE: This does not necessarily make OpenCG fully compatible. + # It only removes the incompatible Surface and replaces it with + # compatible OpenCG Surface(s). The recursive call at the end + # of this block is necessary in the event that there are more + # incompatible Surfaces in this Cell that are not accounted for. + cells = \ + get_compatible_opencg_cells(opencg_cell, surface, halfspace) + + # Remove the non-compatible OpenCG Cell from the Universe + opencg_universe.remove_cell(opencg_cell) + + # Add the compatible OpenCG Cells to the Universe + opencg_universe.add_cells(cells) + + # Make recursive call to look at the updated state of the + # OpenCG Universe and return + return make_opencg_cells_compatible(opencg_universe) + + # If all OpenCG Cells in the OpenCG Universe are compatible, return + return + + +def get_openmoc_cell(opencg_cell): + """Return an OpenMOC cell corresponding to an OpenCG cell. + + Parameters + ---------- + opencg_cell : opencg.Cell + OpenCG cell + + Returns + ------- + openmoc_cell : openmoc.Cell + Equivalent OpenMOC cell + + """ + + cv.check_type('openmoc_cell', opencg_cell, opencg.Cell) + + global OPENMOC_CELLS + cell_id = opencg_cell.id + + # If this Cell was already created, use it + if cell_id in OPENMOC_CELLS: + return OPENMOC_CELLS[cell_id] + + # Create an OpenMOC Cell to represent this OpenCG Cell + name = str(opencg_cell.name) + openmoc_cell = openmoc.Cell(cell_id, name) + + fill = opencg_cell.fill + if opencg_cell.type == 'universe': + openmoc_cell.setFill(get_openmoc_universe(fill)) + elif opencg_cell.type == 'lattice': + openmoc_cell.setFill(get_openmoc_lattice(fill)) + else: + openmoc_cell.setFill(get_openmoc_material(fill)) + + if opencg_cell.rotation is not None: + rotation = np.asarray(opencg_cell.rotation, dtype=np.float64) + openmoc_cell.setRotation(rotation) + if opencg_cell.translation is not None: + translation = np.asarray(opencg_cell.translation, dtype=np.float64) + openmoc_cell.setTranslation(translation) + + surfaces = opencg_cell.surfaces + + for surface_id in surfaces: + surface = surfaces[surface_id][0] + halfspace = int(surfaces[surface_id][1]) + openmoc_cell.addSurface(halfspace, get_openmoc_surface(surface)) + + # Add the OpenMOC Cell to the global collection of all OpenMOC Cells + OPENMOC_CELLS[cell_id] = openmoc_cell + + # Add the OpenCG Cell to the global collection of all OpenCG Cells + OPENCG_CELLS[cell_id] = opencg_cell + + return openmoc_cell + + +def get_opencg_universe(openmoc_universe): + """Return an OpenCG universe corresponding to an OpenMOC universe. + + Parameters + ---------- + openmoc_universe : openmoc.Universe + OpenMOC universe + + Returns + ------- + opencg_universe : opencg.Universe + Equivalent OpenCG universe + + """ + + cv.check_type('openmoc_universe', openmoc_universe, openmoc.Universe) + + global OPENCG_UNIVERSES + universe_id = openmoc_universe.getId() + + # If this Universe was already created, use it + if universe_id in OPENCG_UNIVERSES: + return OPENCG_UNIVERSES[universe_id] + + # Create an OpenCG Universe to represent this OpenMOC Universe + name = openmoc_universe.getName() + opencg_universe = opencg.Universe(universe_id, name) + + # Convert all OpenMOC Cells in this Universe to OpenCG Cells + openmoc_cells = openmoc_universe.getCells() + + for cell_id, openmoc_cell in openmoc_cells.items(): + opencg_cell = get_opencg_cell(openmoc_cell) + opencg_universe.add_cell(opencg_cell) + + # Add the OpenMOC Universe to the global collection of all OpenMOC Universes + OPENMOC_UNIVERSES[universe_id] = openmoc_universe + + # Add the OpenCG Universe to the global collection of all OpenCG Universes + OPENCG_UNIVERSES[universe_id] = opencg_universe + + return opencg_universe + + +def get_openmoc_universe(opencg_universe): + """Return an OpenMOC universe corresponding to an OpenCG universe. + + Parameters + ---------- + opencg_universe : opencg.Universe + OpenCG universe + + Returns + ------- + openmoc_universe : openmoc.Universe + Equivalent OpenMOC universe + + """ + + cv.check_type('opencg_universe', opencg_universe, opencg.Universe) + + global OPENMOC_UNIVERSES + universe_id = opencg_universe.id + + # If this Universe was already created, use it + if universe_id in OPENMOC_UNIVERSES: + return OPENMOC_UNIVERSES[universe_id] + + # Make all OpenCG Cells and Surfaces in this Universe compatible with OpenMOC + make_opencg_cells_compatible(opencg_universe) + + # Create an OpenMOC Universe to represent this OpenCG Universe + name = str(opencg_universe.name) + openmoc_universe = openmoc.Universe(universe_id, name) + + # Convert all OpenCG Cells in this Universe to OpenMOC Cells + opencg_cells = opencg_universe.cells + + for cell_id, opencg_cell in opencg_cells.items(): + openmoc_cell = get_openmoc_cell(opencg_cell) + openmoc_universe.addCell(openmoc_cell) + + # Add the OpenMOC Universe to the global collection of all OpenMOC Universes + OPENMOC_UNIVERSES[universe_id] = openmoc_universe + + # Add the OpenCG Universe to the global collection of all OpenCG Universes + OPENCG_UNIVERSES[universe_id] = opencg_universe + + return openmoc_universe + + +def get_opencg_lattice(openmoc_lattice): + """Return an OpenCG lattice corresponding to an OpenMOC lattice. + + Parameters + ---------- + openmoc_lattice : openmoc.Lattice + OpenMOC lattice + + Returns + ------- + opencg_lattice : opencg.Lattice + Equivalent OpenCG lattice + + """ + + cv.check_type('openmoc_lattice', openmoc_lattice, openmoc.Lattice) + + global OPENCG_LATTICES + lattice_id = openmoc_lattice.getId() + + # If this Lattice was already created, use it + if lattice_id in OPENCG_LATTICES: + return OPENCG_LATTICES[lattice_id] + + # Create an OpenCG Lattice to represent this OpenMOC Lattice + name = openmoc_lattice.getName() + offset = openmoc_lattice.getOffset() + dimension = [1, openmoc_lattice.getNumY(), openmoc_lattice.getNumX()] + width = [1, openmoc_lattice.getWidthY(), openmoc_lattice.getWidthX()] + lower_left = [-np.inf, width[1]*dimension[1]/2. + offset.getX(), + width[2]*dimension[2] / 2. + offset.getY()] + + # Initialize an empty array for the OpenCG nested Universes in this Lattice + universe_array = np.ndarray(tuple(np.array(dimension)[::-1]), \ + dtype=opencg.Universe) + + # Create OpenCG Universes for each unique nested Universe in this Lattice + unique_universes = openmoc_lattice.getUniqueUniverses() + + for universe_id, universe in unique_universes.items(): + unique_universes[universe_id] = get_opencg_universe(universe) + + # Build the nested Universe array + for y in range(dimension[1]): + for x in range(dimension[0]): + universe = openmoc_lattice.getUniverse(x, y) + universe_id = universe.getId() + universe_array[0][y][x] = unique_universes[universe_id] + + opencg_lattice = opencg.Lattice(lattice_id, name) + opencg_lattice.dimension = dimension + opencg_lattice.width = width + opencg_lattice.universes = universe_array + + offset = np.array(lower_left, dtype=np.float64) - \ + ((np.array(width, dtype=np.float64) * \ + np.array(dimension, dtype=np.float64))) / -2.0 + opencg_lattice.offset = offset + + # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices + OPENMOC_LATTICES[lattice_id] = openmoc_lattice + + # Add the OpenCG Lattice to the global collection of all OpenCG Lattices + OPENCG_LATTICES[lattice_id] = opencg_lattice + + return opencg_lattice + + +def get_openmoc_lattice(opencg_lattice): + """Return an OpenMOC lattice corresponding to an OpenCG lattice. + + Parameters + ---------- + opencg_lattice : opencg.Lattice + OpenCG lattice + + Returns + ------- + openmoc_lattice : openmoc.Lattice + Equivalent OpenMOC lattice + + """ + + cv.check_type('opencg_lattice', opencg_lattice, opencg.Lattice) + + global OPENMOC_LATTICES + lattice_id = opencg_lattice.id + + # If this Lattice was already created, use it + if lattice_id in OPENMOC_LATTICES: + return OPENMOC_LATTICES[lattice_id] + + name = str(opencg_lattice.name) + dimension = opencg_lattice.dimension + width = opencg_lattice.width + offset = opencg_lattice.offset + universes = opencg_lattice.universes + + # Initialize an empty array for the OpenMOC nested Universes in this Lattice + universe_array = np.ndarray(tuple(dimension[::-1]), dtype=openmoc.Universe) + + # Create OpenMOC Universes for each unique nested Universe in this Lattice + unique_universes = opencg_lattice.get_unique_universes() + + for universe_id, universe in unique_universes.items(): + unique_universes[universe_id] = get_openmoc_universe(universe) + + # Build the nested Universe array + for z in range(dimension[2]): + for y in range(dimension[1]): + for x in range(dimension[0]): + universe_id = universes[z][y][x].id + universe_array[z][dimension[1]-y-1][x] = unique_universes[universe_id] + + openmoc_lattice = openmoc.Lattice(lattice_id, name) + openmoc_lattice.setWidth(width[0], width[1], width[2]) + openmoc_lattice.setUniverses(universe_array.tolist()) + openmoc_lattice.setOffset(offset[0], offset[1], offset[2]) + + # Add the OpenMOC Lattice to the global collection of all OpenMOC Lattices + OPENMOC_LATTICES[lattice_id] = openmoc_lattice + + # Add the OpenCG Lattice to the global collection of all OpenCG Lattices + OPENCG_LATTICES[lattice_id] = opencg_lattice + + return openmoc_lattice + + +def get_opencg_geometry(openmoc_geometry): + """Return an OpenCG geometry corresponding to an OpenMOC geometry. + + Parameters + ---------- + openmoc_geometry : openmoc.Geometry + OpenMOC geometry + + Returns + ------- + opencg_geometry : opencg.Geometry + Equivalent OpenCG geometry + + """ + + cv.check_type('openmoc_geometry', openmoc_geometry, openmoc.Geometry) + + # Clear dictionaries and auto-generated IDs + OPENMOC_MATERIALS.clear() + OPENCG_MATERIALS.clear() + OPENMOC_SURFACES.clear() + OPENCG_SURFACES.clear() + OPENMOC_CELLS.clear() + OPENCG_CELLS.clear() + OPENMOC_UNIVERSES.clear() + OPENCG_UNIVERSES.clear() + OPENMOC_LATTICES.clear() + OPENCG_LATTICES.clear() + + openmoc_root_universe = openmoc_geometry.getRootUniverse() + opencg_root_universe = get_opencg_universe(openmoc_root_universe) + + opencg_geometry = opencg.Geometry() + opencg_geometry.root_universe = opencg_root_universe + opencg_geometry.initialize_cell_offsets() + + return opencg_geometry + + +def get_openmoc_geometry(opencg_geometry): + """Return an OpenMOC geometry corresponding to an OpenCG geometry. + + Parameters + ---------- + opencg_geometry : opencg.Geometry + OpenCG geometry + + Returns + ------- + openmoc_geometry : openmoc.Geometry + Equivalent OpenMOC geometry + + """ + + cv.check_type('opencg_geometry', opencg_geometry, opencg.Geometry) + + # Deep copy the goemetry since it may be modified to make all Surfaces + # compatible with OpenMOC's specifications + opencg_geometry.assign_auto_ids() + opencg_geometry = copy.deepcopy(opencg_geometry) + + # Update Cell bounding boxes in Geometry + opencg_geometry.update_bounding_boxes() + + # Clear dictionaries and auto-generated IDs + OPENMOC_MATERIALS.clear() + OPENCG_MATERIALS.clear() + OPENMOC_SURFACES.clear() + OPENCG_SURFACES.clear() + OPENMOC_CELLS.clear() + OPENCG_CELLS.clear() + OPENMOC_UNIVERSES.clear() + OPENCG_UNIVERSES.clear() + OPENMOC_LATTICES.clear() + OPENCG_LATTICES.clear() + + # Make the entire geometry "compatible" before assigning auto IDs + universes = opencg_geometry.get_all_universes() + for universe_id, universe in universes.items(): + make_opencg_cells_compatible(universe) + + opencg_geometry.assign_auto_ids() + + opencg_root_universe = opencg_geometry.root_universe + openmoc_root_universe = get_openmoc_universe(opencg_root_universe) + + openmoc_geometry = openmoc.Geometry() + openmoc_geometry.setRootUniverse(openmoc_root_universe) + + # Update OpenMOC's auto-generated object IDs (e.g., Surface, Material) + # with the maximum of those created from the OpenCG objects + all_materials = openmoc_geometry.getAllMaterials() + all_surfaces = openmoc_geometry.getAllSurfaces() + all_cells = openmoc_geometry.getAllCells() + all_universes = openmoc_geometry.getAllUniverses() + + max_material_id = max(all_materials.keys()) + max_surface_id = max(all_surfaces.keys()) + max_cell_id = max(all_cells.keys()) + max_universe_id = max(all_universes.keys()) + + openmoc.maximize_material_id(max_material_id+1) + openmoc.maximize_surface_id(max_surface_id+1) + openmoc.maximize_cell_id(max_cell_id+1) + openmoc.maximize_universe_id(max_universe_id+1) + + return openmoc_geometry diff --git a/openmoc/openmoc.i b/openmoc/openmoc.i index 1129182d5..2b2937089 100644 --- a/openmoc/openmoc.i +++ b/openmoc/openmoc.i @@ -1,27 +1,38 @@ -%define DOCSTRING +%define DOCSTRING "A method of characteristics code for nuclear reactor physics calculations." %enddef +/* Include docstrings generated from Doxygen and doxy2swig.py */ +%include docstring.i + %module(docstring=DOCSTRING) openmoc +/* Import rules for Python/C++ transferrable memory ownership */ +%include thisown.i + %{ #define SWIG_FILE_WITH_INIT + #include + #include "../src/constants.h" #include "../src/Cell.h" #include "../src/Geometry.h" - #include "../src/boundary_type.h" #include "../src/LocalCoords.h" #include "../src/log.h" #include "../src/Material.h" #include "../src/Point.h" - #include "../src/Quadrature.h" + #include "../src/PolarQuad.h" #include "../src/Solver.h" #include "../src/CPUSolver.h" + #include "../src/boundary_type.h" #include "../src/Surface.h" #include "../src/Timer.h" #include "../src/Track.h" #include "../src/TrackGenerator.h" #include "../src/Universe.h" #include "../src/Cmfd.h" + #include "../src/Vector.h" + #include "../src/Matrix.h" + #include "../src/linalg.h" #ifdef ICPC #include "../src/VectorizedSolver.h" @@ -50,6 +61,24 @@ %warnfilter(506) log_printf(logLevel level, const char *format, ...); %warnfilter(511) swig::SwigPyIterator; +%warnfilter(511) Cell::setFill; + +/* Methods for SWIG to ignore in generating Python API */ +%ignore setFSRCentroid(int fsr, Point* centroid); +%ignore setFSRKeysMap(std::unordered_map* FSR_keys_map); +%ignore setFSRsToKeys(std::vector* FSRs_to_keys); +%ignore setFSRsToMaterialIDs(std::vector* FSRs_to_material_IDs); +%ignore setFSRKeysMap(ParallelHashMap* FSR_keys_map); +%ignore initializeFSRVectors(); + +/* Instruct SWIG to ignore methods used in getting CSR Matrix format and Vector + * attributes. These attributes should be used internally only by the Matrix and + * Vector class methods and linear algrebra (linalg.h/linalg.cpp) methods. */ +%ignore Matrix::getArray(); +%ignore Matrix::getA(); +%ignore Matrix::getIA(); +%ignore Matrix::getJA(); +%ignore Matrix::getDiag(); %exception { try { @@ -59,377 +88,39 @@ } } -/* C++ casting helper method for openmoc.process computePinPowers - * routine and the OpenCG compatibility module */ -%inline %{ - - CellFill* castCellToCellFill(Cell* cell) { - return dynamic_cast(cell); - } - - CellBasic* castCellToCellBasic(Cell* cell) { - return dynamic_cast(cell); - } - - Lattice* castUniverseToLattice(Universe* universe) { - return dynamic_cast(universe); - } - - Universe* castLatticeToUniverse(Lattice* lattice) { - return dynamic_cast(lattice); - } - - Plane* castSurfaceToPlane(Surface* plane) { - return dynamic_cast(plane); - } - - XPlane* castSurfaceToXPlane(Surface* xplane) { - return dynamic_cast(xplane); - } - - YPlane* castSurfaceToYPlane(Surface* yplane) { - return dynamic_cast(yplane); - } - - ZPlane* castSurfaceToZPlane(Surface* zplane) { - return dynamic_cast(zplane); - } - - Circle* castSurfaceToCircle(Surface* circle) { - return dynamic_cast(circle); - } - -%} - - -/* If the user uses the --no-numpy flag, then NumPy typemaps will not be used - * and the NumPy C API will not be embedded in the source code. The NumPy - * typemaps are used to allow users to pass NumPy arrays to/from the C++ source - * code. This does not work well on BGQ, and some users may prefer not to embed - * this into their code, so if --no-numpy is passed in we use SWIG typemaps to - * allow users to pass in arrays of data as Python lists. */ -#ifdef NO_NUMPY - - -/* Typemap for the Material::set_____XS(double* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (double* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (double*) malloc($2 * sizeof(double)); // cross-section array +/* Routines to allow parent classes to be cast to subclasses from Python */ +%include casting.i - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If value is a number, cast it as an int and set the input array value */ - if (PyNumber_Check(o)) { - $1[i] = (double) PyFloat_AsDouble(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Material::set_____XS(float* xs, int num_groups) - * method - allows users to pass in a Python list of cross-sections - * for each energy group */ -%typemap(in) (float* xs, int num_groups) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the cross-section array"); - return NULL; - } - - $2 = PySequence_Length($input); // num_groups - $1 = (float*) malloc($2 * sizeof(float)); // cross-section array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If value is a number, cast it as an int and set input array value */ - if (PyNumber_Check(o)) { - $1[i] = (float) PyFloat_AsFloat(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for cross-section values\n"); - return NULL; - } - } -} - - -/* Typemap for the Cmfd::setGroupStructure - * (int* group_indices, int length_group_indices) - * method - allows users to pass in a Python list of group indices - * for each CMFD energy group */ -%typemap(in) (int* group_indices, int length_group_indices) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " - "for the group indices array"); - return NULL; - } - - $2 = PySequence_Length($input); // length_group_indices - $1 = (int*) malloc($2 * sizeof(int)); // group indices array - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Extract the value from the list at this location */ - PyObject *o = PySequence_GetItem($input,i); - - /* If value is a number, cast it as an int and set the input array value */ - if (PyNumber_Check(o)) { - $1[i] = (int) PyInt_AS_LONG(o); - } - else { - free($1); - PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " - "for group indices values\n"); - return NULL; - } - } -} - - - -/* If the user did not pass in the --no-numpy flag, then NumPy typemaps will be - * used and the NumPy C API will be embedded in the source code. This will allow - * users to pass arrays of data to/from the C++ source code (ie, setting group - * cross-section values or extracting the scalar flux). */ -#else - -%include "numpy.i" - -%init %{ - import_array(); -%} - -/* The typemap used to match the method signature for the - * Lattice::setLatticeCells setter method. This allows users to set the lattice - * cells (universe IDs) using a 2D NumPy array */ -%apply (int DIM1, int DIM2, int* IN_ARRAY2) {(int num_x, int num_y, int* universes)} - -/* The typemap used to match the method signature for the - * Cmfd::setGroupStructure method. This allows users to set the CMFD group - * structure using a NumPy array */ -%apply (int* IN_ARRAY1, int DIM1) {(int* group_indices, int length_group_indices)} - -/* The typemap used to match the method signature for the Material - * cross-section setter methods. This allows users to set the cross-sections - * using NumPy arrays */ -%apply (double* IN_ARRAY1, int DIM1) {(double* xs, int num_groups)} - -/* The typemap used to match the method signature for the TrackGenerator's - * getter methods for track start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_tracks)} - -/* The typemap used to match the method signature for the TrackGenerator's - * getter methods for track segment start and end coordinates for the plotting - * routines in openmoc.plotter */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* coords, int num_segments)} - -/* The typemap used to match the method signature for the Solver's - * computeFSRFissionRates method for the data processing routines in - * openmoc.process */ -%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* fission_rates, int num_FSRs)} - -/* The typemap used to match the method signature for the Universe's - * getCellIds method for the data processing routines in openmoc.process */ -%apply (int* ARGOUT_ARRAY1, int DIM1) {(int* cell_ids, int num_cells)} - -#endif - - -/* Typemap for all methods which return a std::map. This includes - * the Geometry::getAllCells(), Universe::getAllCells(), etc. These methods - * are particularly useful for OpenCG compatibility. */ -%include -%clear std::map; -%typemap(out) std::map { - - $result = PyDict_New(); - int size = $1.size(); - - std::map::iterator iter; - Cell* cell; - int cell_id; - - for (iter = $1.begin(); iter != $1.end(); ++iter) { - cell_id = iter->first; - cell = iter->second; - PyObject* value = - SWIG_NewPointerObj(SWIG_as_voidptr(cell), $descriptor(Cell*), 0); - PyDict_SetItem($result, PyInt_FromLong(cell_id), value); - } -} - - -/* Typemap for all methods which return a std::map. - * This includes the Cell::getSurfaces() method, which is useful for OpenCG - * compatibility. */ -%include -%clear std::map; -%typemap(out) std::map { - - $result = PyDict_New(); - int size = $1.size(); - - std::map::iterator iter; - surface_halfspace* surf; - int surf_id; - - for (iter = $1.begin(); iter != $1.end(); ++iter) { - surf_id = iter->first; - surf = &iter->second; - PyObject* value = - SWIG_NewPointerObj(SWIG_as_voidptr(surf), - $descriptor(surface_halfspace*), 0); - PyDict_SetItem($result, PyInt_FromLong(surf_id), value); - } -} - - -/* Typemap for all methods which return a std::map. - * This includes the Geometry::getAllMaterials() method, which is useful - * for OpenCG compatibility. */ -%include -%clear std::map; -%typemap(out) std::map { - - $result = PyDict_New(); - int size = $1.size(); - - std::map::iterator iter; - Material* mat; - int mat_id; - - for (iter = $1.begin(); iter != $1.end(); ++iter) { - mat_id = iter->first; - mat = iter->second; - PyObject* value = - SWIG_NewPointerObj(SWIG_as_voidptr(mat), $descriptor(Material*), 0); - PyDict_SetItem($result, PyInt_FromLong(mat_id), value); - } -} - - -/* Typemap for all methods which return a std::map. - * This includes the Lattice::getUniqueUniverses() method which is ueseful for - * OpenCG compatibility. */ -%include -%clear std::map; -%typemap(out) std::map { - - $result = PyDict_New(); - int size = $1.size(); - - std::map::iterator iter; - Universe* univ; - int univ_id; - - for (iter = $1.begin(); iter != $1.end(); ++iter) { - univ_id = iter->first; - univ = iter->second; - PyObject* value = - SWIG_NewPointerObj(SWIG_as_voidptr(univ), $descriptor(Universe*), 0); - PyDict_SetItem($result, PyInt_FromLong(univ_id), value); - } -} - - -/* Typemap for Lattice::setUniverses(int num_x, int num_y, Universe** universes) - * method - allows users to pass in Python lists of Universes for each - * lattice cell */ -%typemap(in) (int num_x, int num_y, Universe** universes) { - - if (!PyList_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a Python list of integers " - "for the Lattice cells"); - return NULL; - } - - $1 = PySequence_Length($input); // num_x - $2 = PySequence_Length(PyList_GetItem($input,0)); // num_y - $3 = (Universe**) malloc(($1 * $2) * sizeof(Universe*)); // universes - - /* Loop over x */ - for (int i = 0; i < $2; i++) { - - /* Get the inner list in the nested list for the lattice */ - PyObject* outer_list = PyList_GetItem($input,i); - - /* Check that the length of this list is the same as the length - * of the first list */ - if (PySequence_Length(outer_list) != $2) { - PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1 x $2 " - "elements for Lattice\n"); - return NULL; - } - - /* Loop over y */ - for (int j =0; j < $1; j++) { - /* Extract the value from the list at this location and convert - * SWIG wrapper to pointer to underlying C++ class instance */ - PyObject* o = PyList_GetItem(outer_list,j); - void *p1 = 0; - SWIG_ConvertPtr(o, &p1, SWIGTYPE_p_Universe, 0 | 0); - $3[i*$1+j] = (Universe*) p1; - } - } -} +/* Routines which convert std::map return types to Python dictionaries */ +%include map_to_dict.i +/* Routines which pass / return NumPy arrays to / from C++ routine **/ +%include numpy_typemaps.i %include -%include +%include ../src/constants.h %include ../src/Cell.h %include ../src/Geometry.h -%include ../src/boundary_type.h %include ../src/LocalCoords.h %include ../src/log.h %include ../src/Material.h %include ../src/Point.h -%include ../src/Quadrature.h +%include ../src/PolarQuad.h %include ../src/Solver.h %include ../src/CPUSolver.h +%include ../src/boundary_type.h %include ../src/Surface.h %include ../src/Timer.h %include ../src/Track.h %include ../src/TrackGenerator.h %include ../src/Universe.h %include ../src/Cmfd.h +%include ../src/Vector.h +%include ../src/Matrix.h +%include ../src/linalg.h #ifdef ICPC -%include "../src/VectorizedSolver.h" +%include ../src/VectorizedSolver.h #endif #define printf PySys_WriteStdout - -#ifdef DOUBLE -typedef double FP_PRECISION; -#else -typedef float FP_PRECISION; -#endif diff --git a/openmoc/options.py b/openmoc/options.py index 3f8cbedfe..12e3cf42a 100644 --- a/openmoc/options.py +++ b/openmoc/options.py @@ -1,218 +1,199 @@ -## -# @file options.py -# @package openmoc.options -# @brief The options module provides the Options class to parse, interpret -# and encapsulate command line arguments for OpenMOC runtime options. -# @author William Boyd (wboyd@mit.edu) -# @date July 24, 2013 - -import getopt, sys +import sys +import getopt import multiprocessing # For Python 2.X.X -if (sys.version_info[0] == 2): - from log import * +if sys.version_info[0] == 2: + from log import py_printf # For Python 3.X.X else: - from openmoc.log import * - - -## -# @class Options process.py "openmoc/options.py" -# @brief Command-line options for runtime configuration of OpenMOC. -# @details This class parses, interprets and encapsulates the runtime options -# for OpenMOC. This class can be instantiate in any OpenMOC Python -# script which imports the openmoc.process module. The user may -# request the value of any or all command line options and use them -# as they wish. An example of how the Options class would be used -# is given as follows: -# -# @code -# import from openmoc.options import Options -# -# # Create an Options object which will parse all arguments -# # from the command line -# options = Options() -# -# # Retrieve useful command line options -# num_azim = options.num_azim -# ... -# -# # Do something useful with command line arguments -# ... -# @endcode -# -class Options: - - - ## - # @brief Options class constructor. - # @details This method initializes an Options object with default values - # for each runtime parameter, and then parses the arguments - # passed in at runtime and assigns the appropriate value to each. - # - def __init__(self): - - ## The default number of azimuthal angles - self._num_azim = 4 - - ## The default track spacing - self._track_spacing = 0.1 - - ## The default maximum number of source iterations - self._max_iters = 1000 - - ## The default tolerance on the source distribution convergence - self._tolerance = 1E-5 - - ## The default number of OpenMP threads - self._num_omp_threads = multiprocessing.cpu_count() - - ## The default number of GPU threadblocks - self._num_thread_blocks = 64 - - ## The default number of GPU threads per threadblock - self._num_gpu_threads = 64 - - # Parse in arguments from the command line - self.parseArguments() - - - ## - # @brief This method parses command line options using the Python getopt - # module and assigns the appropriate values to the corresponding - # Options class attributes. - # @param self the Options object pointer - def parseArguments(self): - try: - opts, args = getopt.getopt(sys.argv[1:], - 'hfa:s:i:c:t:b:g:r:l:', - ['help', - 'num-azim=', - 'track-spacing=', - 'tolerance=', - 'max-iters=', - 'num-omp-threads=', - 'num-thread-blocks=', - 'num-gpu-threads=']) - - except getopt.GetoptError as err: - py_printf('ERROR', str(err)) - pass - - - # Parse the command line arguments - error checking will occur - # at the setter method level in C++ - for opt, arg in opts: - - # Print a report of all supported runtime options and exit - if opt in ('-h', '--help'): - - print('{:-^80}'.format('')) - print('{: ^80}'.format('OpenMOC v.0.1.1 runtime options')) - print('{:-^80}'.format('')) - print('') - - help_msg = '\t{: <35}'.format('-h, --help') - help_msg = 'Report OpenMOC runtime options\n' - print(help_msg) - - num_azim = '\t{: <35}'.format('-a, --num-azim=<4>') - num_azim += 'the number of azimuthal angles\n' - print(num_azim) - - track_spacing = '\t{: <35}'.format('-s, --track-spacing=<0.1>') - track_spacing += 'The track spacing [cm]\n' - print(track_spacing) - - max_iters = '\t{: <35}'.format('-i, --max-iters=<1000>') - max_iters += 'The max number of source iterations\n' - print(max_iters) - - tolerance = '\t{: <35}'.format('-c, --tolerance=<1E-5>') - tolerance += 'The source convergence tolerance\n' - print(tolerance) - - num_omp_threads = '\t{: <35}'.format('-t, --num-omp-threads=<1>') - num_omp_threads += 'The number of OpenMP threads\n' - print(num_omp_threads) - - num_gpu_threadblocks = '\t{: <35}'.format('-b, ' + \ - '--num-gpu-threadblocks=<64>') - num_gpu_threadblocks += 'The number of GPU threadblocks\n' - print(num_gpu_threadblocks) - - num_gpu_threads = '\t{: <35}'.format('-g, --num-gpu-threads=<64>') - num_gpu_threads += 'The number of GPU threads per block\n' - print(num_gpu_threads) - - sys.exit() - - elif opt in ('-a', '--num-azim'): - self._num_azim = int(arg) - - elif opt in ('-s', '--track-spacing'): - self._track_spacing = float(arg) - - elif opt in ('-i', '--max-iters'): - self._max_iters = int(arg) - - elif opt in ('-c', '--tolerance'): - self._tolerance = float(arg) - - elif opt in ('-t', '--num-omp-threads'): - self._num_omp_threads = int(arg) - - elif opt in ('-b', '--num-thread-blocks'): - self._num_thread_blocks = int(arg) - - elif opt in ('-g', '--num-gpu-threads'): - self._num_gpu_threads = int(arg) - - ## - # @brief Returns the number of azimuthal angles. - # @return the number of azimuthal angles - def getNumAzimAngles(self): - return self._num_azim - - - ## - # @brief Returns the track spacing [cm]. - # @return the track spacing [cm]. - def getTrackSpacing(self): - return self._track_spacing - - - ## - # @brief Returns the maximum number of source iterations. - # @return the maximum number of source iterations - def getMaxIterations(self): - return self._max_iters - - - ## - # @brief Returns the source convergence tolerance. - # @return the source convergence tolerance - def getTolerance(self): - return self._tolerance - - - ## - # @brief Returns the number of OpenMP multi-core CPU threads. - # @return the number of OpenMP threads - def getNumThreads(self): - return self._num_omp_threads - - - ## - # @brief Returns the number of CUDA thread blocks for a GPU. - # @return the number of CUDA thread blocks - def getNumThreadBlocks(self): - return self._num_thread_blocks - - - ## - # @brief Returns the number of CUDA threads per block for a GPU. - # @return the number of CUDA threads per block - def getNumThreadsPerBlock(self): - return self._num_gpu_threads + from openmoc.log import py_printf + + +class Options(object): + """Command-line options for runtime configuration of OpenMOC. + + This class parses, interprets and encapsulates the runtime options for + OpenMOC. This class can be instantiate in any OpenMOC Python script which + imports the openmoc.process module. The user may request the value of any + or all command line options and use them as they wish. + + Attributes + ---------- + num_azim : Integral + The number of azimuthal angles (default is 4) + track_spacing : Real + The track spacing in centimeters (default is 0.1 cm) + max_iters : Integral + The maximum number of source iterations (default is 1000) + tolerance : Real + The tolerance on convergence (default is 1E-5) + num_omp_threads : Integral + The number of OpenMP threads (default is the # of CPU cores) + num_thread_blocks : Integral + The number of GPU threadblocks (default is 64) + num_threads_per_block : Integral + The number of GPU threads per threadblock (default is 64) + + Examples + -------- + An example of how the Options class would be used is given as follows: + + >>> import from openmoc.options import Options + + >>> # Create an Options object which will parse all arguments + >>> # from the command line + >>> options = Options() + + >>> # Retrieve useful command line options + >>> num_azim = options.num_azim + >>> ... + + >>> # Do something useful with command line arguments + >>> ... + + """ + + def __init__(self): + """Initialize default values for each runtime parameter and parses the + command line arguments assigns the appropriate value to each.""" + + self._short_args = 'hfa:s:i:c:t:b:g:r:l:' + self._long_args = ['help', + 'num-azim=', + 'track-spacing=', + 'tolerance=', + 'max-iters=', + 'num-omp-threads=', + 'num-thread-blocks=', + 'num-threads-per-block='] + + self._num_azim = 4 + self._track_spacing = 0.1 + self._max_iters = 1000 + self._tolerance = 1E-5 + self._num_omp_threads = multiprocessing.cpu_count() + self._num_thread_blocks = 64 + self._num_threads_per_block = 64 + + self._opts = None + self._args = None + + self.parseArguments() + + @property + def short_args(self): + return self._short_args + + @property + def long_args(self): + return self._long_args + + @property + def opts(self): + return self._opts + + @property + def args(self): + return self._args + + @property + def num_azim(self): + return self._num_azim + + @property + def track_spacing(self): + return self._track_spacing + + @property + def max_iters(self): + return self._max_iters + + @property + def tolerance(self): + return self._tolerance + + @property + def num_omp_threads(self): + return self._num_omp_threads + + @property + def num_thread_blocks(self): + return self._num_thread_blocks + + @property + def num_threads_per_block(self): + return self._num_threads_per_block + + def parseArguments(self): + """This method parses command line options and assigns the appropriate + values to the corresponding class attributes.""" + + try: + self._opts, self._args = \ + getopt.getopt(sys.argv[1:], self.short_args, self.long_args) + except getopt.GetoptError as err: + py_printf('ERROR', str(err)) + + # Parse the command line arguments - error checking will occur + # at the setter method level in C++ + for opt, arg in self.opts: + + # Print a report of all supported runtime options and exit + if opt in ('-h', '--help'): + + print('{:-^80}'.format('')) + print('{: ^80}'.format('OpenMOC v.0.1.1 runtime options')) + print('{:-^80}'.format('')) + print('') + + help_msg = '\t{: <35}'.format('-h, --help') + help_msg += 'Report OpenMOC runtime options\n' + print(help_msg) + + num_azim = '\t{: <35}'.format('-a, --num-azim=<4>') + num_azim += 'the number of azimuthal angles\n' + print(num_azim) + + track_spacing = '\t{: <35}'.format('-s, --track-spacing=<0.1>') + track_spacing += 'The track spacing [cm]\n' + print(track_spacing) + + max_iters = '\t{: <35}'.format('-i, --max-iters=<1000>') + max_iters += 'The max number of source iterations\n' + print(max_iters) + + tolerance = '\t{: <35}'.format('-c, --tolerance=<1E-5>') + tolerance += 'The source convergence tolerance\n' + print(tolerance) + + num_omp_threads = '\t{: <35}'.format('-t, --num-omp-threads=<1>') + num_omp_threads += 'The number of OpenMP threads\n' + print(num_omp_threads) + + num_threadblocks = '\t{: <35}'.format('-b, ' + \ + '--num-thread-blocks=<64>') + num_threadblocks += 'The number of GPU threadblocks\n' + print(num_threadblocks) + + num_threads_per_block = \ + '\t{: <35}'.format('-g, --num-threads-per-block=<64>') + num_threads_per_block += 'The number of GPU threads per block\n' + print(num_threads_per_block) + + sys.exit() + + elif opt in ('-a', '--num-azim'): + self._num_azim = int(arg) + elif opt in ('-s', '--track-spacing'): + self._track_spacing = float(arg) + elif opt in ('-i', '--max-iters'): + self._max_iters = int(arg) + elif opt in ('-c', '--tolerance'): + self._tolerance = float(arg) + elif opt in ('-t', '--num-omp-threads'): + self._num_omp_threads = int(arg) + elif opt in ('-b', '--num-thread-blocks'): + self._num_thread_blocks = int(arg) + elif opt in ('-g', '--num-threads-per-block'): + self._num_threads_per_block = int(arg) diff --git a/openmoc/plotter.py b/openmoc/plotter.py index 29c7fe37c..7ff49a1d5 100644 --- a/openmoc/plotter.py +++ b/openmoc/plotter.py @@ -1,880 +1,1679 @@ -# -# @file plotter.py -# @package openmoc.plotter -# @brief The plotter module provides utility functions to plot data from -# OpenMOCs C++ classes, in particular, the geomery, including Material, -# Cells and flat source regions, and fluxes and pin powers. -# @author William Boyd (wboyd@mit.edu) -# @date March 10, 2013 - +import os import sys +from numbers import Integral, Real +from collections import Iterable -## @var openmoc -# @brief The openmoc module in use in the Python script using the -# openmoc.plotter module. -openmoc = '' - -# Determine which OpenMOC module is being used -if 'openmoc.gnu.double' in sys.modules: - openmoc = sys.modules['openmoc.gnu.double'] -elif 'openmoc.gnu.single' in sys.modules: - openmoc = sys.modules['openmoc.gnu.single'] -elif 'openmoc.intel.double' in sys.modules: - openmoc = sys.modules['openmoc.intel.double'] -elif 'openmoc.intel.single' in sys.modules: - openmoc = sys.modules['openmoc.intel.single'] -elif 'openmoc.bgq.double' in sys.modules: - openmoc = sys.modules['openmoc.bgq.double'] -elif 'openmoc.bgq.single' in sys.modules: - openmoc = sys.modules['openmoc.bgq.single'] -else: - from openmoc import * - - +import numpy as np +import numpy.random import matplotlib +from mpl_toolkits.mplot3d import Axes3D -# force headless backend, or set 'backend' to 'Agg' -# in your ~/.matplotlib/matplotlibrc +# Force headless backend for plotting on clusters matplotlib.use('Agg') import matplotlib.pyplot as plt - -# Force non-interactive mode, or set 'interactive' to False -# in your ~/.matplotlib/matplotlibrc -plt.ioff() - import matplotlib.colors as colors import matplotlib.cm as cmx -import numpy as np -import numpy.random -import os, sys + +import openmoc # For Python 2.X.X if (sys.version_info[0] == 2): - from log import * - from process import * + from log import * + from process import get_scalar_fluxes + import checkvalue as cv # For Python 3.X.X else: - from openmoc.log import * - from openmoc.process import * + from openmoc.log import * + from openmoc.process import get_scalar_fluxes + import openmoc.checkvalue as cv + +# Force non-interactive mode for plotting on clusters +plt.ioff() +# Default matplotlib parameters to use in all plots +matplotlib_rcparams = matplotlib.rcParamsDefault +matplotlib_rcparams['font.family'] = 'sans-serif' +matplotlib_rcparams['font.weight'] = 'normal' +matplotlib_rcparams['font.size'] = 15 +matplotlib_rcparams['savefig.dpi'] = 500 +matplotlib_rcparams['figure.dpi'] = 500 -## A static variable for the output directory in which to save plots +# A static variable for the output directory in which to save plots subdirectory = "/plots/" +TINY_MOVE = openmoc.TINY_MOVE + +if sys.version_info[0] >= 3: + basestring = str + + +def plot_tracks(track_generator, get_figure=False): + """Plot the characteristic tracks from an OpenMOC simulation. + + This method requires that tracks have been generated by a TrackGenerator. + + Parameters + ---------- + track_generator : openmoc.TrackGenerator + A TrackGenerator with the tracks to plot + get_figure : bool + Whether or not to return the Matplotlib figure + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: -## -# @brief Plots the characteristic tracks from an OpenMOC simulation. -# @details This method requires that Tracks have been generated by a -# TrackGenerator object. A user may invoke this function from -# an OpenMOC Python file as follows: -# -# @code -# openmoc.plotter.plot_tracks(track_generator) -# @endcode -# -# @param track_generator the TrackGenerator which has generated Tracks -def plot_tracks(track_generator): - - global subdirectory - - directory = get_output_directory() + subdirectory - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Error checking - if not 'TrackGenerator' in str(type(track_generator)): - py_printf('ERROR', 'Unable to plot Tracks since %s was input rather ' + \ - 'than a TrackGenerator', str(type(track_generator))) - - if not track_generator.containsTracks(): - py_printf('ERROR', 'Unable to plot Tracks since the track ' + \ - 'generator has not yet generated tracks') - - py_printf('NORMAL', 'Plotting the tracks...') - - # Retrieve data from TrackGenerator - num_azim = track_generator.getNumAzim() - spacing = track_generator.getTrackSpacing() - num_tracks = track_generator.getNumTracks() - coords = track_generator.retrieveTrackCoords(num_tracks*4) - - # Convert data to NumPy arrays - coords = np.array(coords) - x = coords[0::2] - y = coords[1::2] - - # Make figure of line segments for each Track - fig = plt.figure() - for i in range(num_tracks): - plt.plot([x[i*2], x[i*2+1]], [y[i*2], y[i*2+1]], 'b-') - - plt.xlim([x.min(), x.max()]) - plt.ylim([y.min(), y.max()]) - - title = 'Tracks for ' + str(num_azim) + ' angles and ' + str(spacing) + \ - ' cm spacing' - - plt.title(title) - - filename = directory + 'tracks-' + str(num_azim) + '-angles-' + \ - str(spacing) + '-spacing.png' - - fig.savefig(filename, bbox_inches='tight') - plt.close(fig) - - -## -# @brief Plots the characteristic Track segments from an OpenMOC simulation. -# @details This method requires that tracks have been generated by a -# TrackGenerator object. Each segment is colored by the ID of the -# unique flat flat source region it is within. A user may invoke -# this function from an OpenMOC Python file as follows: -# -# @code -# openmoc.plotter.plot_segments(track_generator) -# @endcode -# -# @param track_generator the TrackGenerator which has generated Tracks -def plot_segments(track_generator): - - global subdirectory - - directory = get_output_directory() + subdirectory - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Error checking - if not 'TrackGenerator' in str(type(track_generator)): - py_printf('ERROR', 'Unable to plot Track segments since %s was input ' + \ - 'rather than a TrackGenerator', str(type(track_generator))) - - if not track_generator.containsTracks(): - py_printf('ERROR', 'Unable to plot Track segments since the ' + \ - 'TrackGenerator has not yet generated Tracks.') - - py_printf('NORMAL', 'Plotting the track segments...') - - # Retrieve data from TrackGenerator - num_azim = track_generator.getNumAzim() - spacing = track_generator.getTrackSpacing() - num_segments = track_generator.getNumSegments() - num_fsrs = track_generator.getGeometry().getNumFSRs() - coords = track_generator.retrieveSegmentCoords(num_segments*5) - - # Convert data to NumPy arrays - coords = np.array(coords) - x = numpy.zeros(num_segments*2) - y = numpy.zeros(num_segments*2) - fsrs = numpy.zeros(num_segments) + >>> openmoc.plotter.plot_tracks(track_generator) - for i in range(num_segments): - fsrs[i] = coords[i*5] - x[i*2] = coords[i*5+1] - y[i*2] = coords[i*5+2] - x[i*2+1] = coords[i*5+3] - y[i*2+1] = coords[i*5+4] - - # Create array of equally spaced randomized floats as a color map for plots - # Seed the NumPy random number generator to ensure reproducible color maps - numpy.random.seed(1) - color_map = np.linspace(0., 1., num_fsrs, endpoint=False) - numpy.random.shuffle(color_map) - - # Make figure of line segments for each track - fig = plt.figure() + """ - for i in range(num_segments): + cv.check_type('track_generator', track_generator, openmoc.TrackGenerator) + if not track_generator.containsTracks(): + py_printf('ERROR', 'Unable to plot Tracks since the track ' + + 'generator has not yet generated tracks') + + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory + + # Ensure that normal settings are used even if called from ipython + curr_rc = dict(matplotlib.rcParams) + matplotlib.rcParams.update(matplotlib_rcparams) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + py_printf('NORMAL', 'Plotting the tracks...') + + # Retrieve data from TrackGenerator + vals_per_track = openmoc.NUM_VALUES_PER_RETRIEVED_TRACK + num_azim = track_generator.getNumAzim() + spacing = track_generator.getTrackSpacing() + num_tracks = track_generator.getNumTracks() + coords = track_generator.retrieveTrackCoords(num_tracks*vals_per_track) + + # Convert data to NumPy arrays + coords = np.array(coords) + x = coords[0::vals_per_track/2] + y = coords[1::vals_per_track/2] + + # Make figure of line segments for each Track + fig = plt.figure() + fig.patch.set_facecolor('none') + for i in range(num_tracks): + plt.plot([x[i*2], x[i*2+1]], [y[i*2], y[i*2+1]], 'b-') + + plt.xlim([x.min(), x.max()]) + plt.ylim([y.min(), y.max()]) + + title = 'Tracks for {0} angles and {1} cm spacing'.format(num_azim, spacing) + plt.title(title) + + # Restore settings if called from ipython + matplotlib.rcParams.update(curr_rc) + + # Save the figure to a file or return to user + if get_figure: + return fig + else: + filename = \ + 'tracks-{1}-angles-{2}.png'.format(directory, num_azim, spacing) + fig.savefig(directory+filename, bbox_inches='tight') + plt.close(fig) + + +def plot_segments(track_generator, get_figure=False): + """Plot the characteristic track segments from an OpenMOC simulation. + + This method requires that tracks have been generated by a TrackGenerator. + Each segment is colored by the ID of the unique FSR it is within. + + Parameters + ---------- + track_generator : openmoc.TrackGenerator + A TrackGenerator with the track segments to plot + get_figure : bool + Whether or not to return the Matplotlib figure + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_segments(track_generator) + + """ + + cv.check_type('track_generator', track_generator, openmoc.TrackGenerator) + if not track_generator.containsTracks(): + py_printf('ERROR', 'Unable to plot Track segments since the ' + + 'TrackGenerator has not yet generated Tracks.') + + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory + + # Ensure that normal settings are used even if called from ipython + curr_rc = dict(matplotlib.rcParams) + matplotlib.rcParams.update(matplotlib_rcparams) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + py_printf('NORMAL', 'Plotting the track segments...') + + # Retrieve data from TrackGenerator + vals_per_segment = openmoc.NUM_VALUES_PER_RETRIEVED_SEGMENT + num_azim = track_generator.getNumAzim() + spacing = track_generator.getTrackSpacing() + num_segments = track_generator.getNumSegments() + num_fsrs = track_generator.getGeometry().getNumFSRs() + coords = \ + track_generator.retrieveSegmentCoords(num_segments*vals_per_segment) + + # Convert data to NumPy arrays + coords = np.array(coords) + x = np.zeros(num_segments*2) + y = np.zeros(num_segments*2) + z = np.zeros(num_segments*2) + fsrs = np.zeros(num_segments) + + for i in range(num_segments): + fsrs[i] = coords[i*vals_per_segment] + x[i*2] = coords[i*vals_per_segment+1] + y[i*2] = coords[i*vals_per_segment+2] + z[i*2] = coords[i*vals_per_segment+3] + x[i*2+1] = coords[i*vals_per_segment+4] + y[i*2+1] = coords[i*vals_per_segment+5] + z[i*2+1] = coords[i*vals_per_segment+6] + + # Create array of equally spaced randomized floats as a color map for plots + # Seed the NumPy random number generator to ensure reproducible color maps + numpy.random.seed(1) + color_map = np.linspace(0., 1., num_fsrs, endpoint=False) + numpy.random.shuffle(color_map) + + # Make figure of line segments for each track + fig = plt.figure() + fig.patch.set_facecolor('none') # Create a color map corresponding to FSR IDs - jet = cm = plt.get_cmap('jet') - cNorm = colors.Normalize(vmin=0, vmax=max(color_map)) - scalarMap = cmx.ScalarMappable(norm=cNorm) - color = scalarMap.to_rgba(color_map[fsrs[i] % num_fsrs]) - plt.plot([x[i*2], x[i*2+1]], [y[i*2], y[i*2+1]], c=color) + for i in range(num_segments): + cNorm = colors.Normalize(vmin=0, vmax=max(color_map)) + scalarMap = cmx.ScalarMappable(norm=cNorm) + color = scalarMap.to_rgba(color_map[fsrs[i] % num_fsrs]) + plt.plot([x[i*2], x[i*2+1]], [y[i*2], y[i*2+1]], c=color) + + plt.xlim([x.min(), x.max()]) + plt.ylim([y.min(), y.max()]) - plt.xlim([x.min(), x.max()]) - plt.ylim([y.min(), y.max()]) + suptitle = 'Segments ({0} angles, {1} cm spacing)'.format(num_azim, spacing) + title = 'z = {0}'.format(z[0]) + plt.suptitle(suptitle) + plt.title(title) - title = 'Segments for ' + str(num_azim) + ' angles and ' + str(spacing) + \ - ' cm spacing' - - plt.title(title) - - filename = directory + 'segments-' + str(num_azim) + '-angles-' + \ - str(spacing) + '-spacing.png' - - fig.savefig(filename, bbox_inches='tight') - plt.close(fig) - - - -## -# @brief This method takes in a Geometry object and plots a color-coded 2D -# surface plot representing the Materials in the Geometry. -# @details The Geometry object must be initialized with Materials, Cells, -# Universes and lattices before being passed into this method. A user -# may invoke this function from an OpenMOC Python file as follows: -# -# @code -# openmoc.plotter.plot_materials(geometry) -# @endcode -# -# @param geometry a geometry object which has been initialized with Materials, -# Cells, Universes and Lattices -# @param gridsize an optional number of grid cells for the plot -# @param xlim optional list/tuple of the minimim/maximum x-coordinates -# @param ylim optional list/tuple of the minimim/maximum y-coordinates -def plot_materials(geometry, gridsize=250, xlim=None, ylim=None): - - global subdirectory - - directory = get_output_directory() + subdirectory - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Error checking - if not 'Geometry' in str(type(geometry)): - py_printf('ERROR', 'Unable to plot the Materials since ' + \ - 'input was not a geometry class object') - - if not is_integer(gridsize): - py_printf('ERROR', 'Unable to plot the Materials since ' + \ - 'since the gridsize %d is not an integer', gridsize) - - if gridsize <= 0: - py_printf('ERROR', 'Unable to plot the Materials ' + \ - 'with a negative gridsize (%d)', gridsize) - - py_printf('NORMAL', 'Plotting the materials...') - - # Initialize a NumPy array for the surface colors - surface = numpy.zeros((gridsize, gridsize), numpy.int64) - - # Retrieve the pixel coordinates - coords = get_pixel_coords(geometry, gridsize, xlim, ylim) - - # Find the geometry.getNumEnergyGroups(): - py_printf('ERROR', 'Unable to plot the flat source region scalar ' + \ - 'flux since the energy_groups list contains %d which is' + \ - ' greater than the index for all energy groups', group) - - elif is_integer(energy_groups): - if energy_groups <= 0: - py_printf('ERROR', 'Unable to plot the flat source region scalar ' + \ - 'flux since the energy_groups argument contains %d which is' + \ - ' less than the index for all energy groups', energy_groups) - - elif energy_groups > geometry.getNumEnergyGroups(): - py_printf('ERROR', 'Unable to plot the flat source region ' + \ - 'scalar flux since the energy_groups argument ' + \ - 'contains %d which is greater than the index ' + \ - 'for all energy groups', energy_groups) + # Restore settings if called from ipython + matplotlib.rcParams.update(curr_rc) + if get_figure: + return fig else: - py_printf('ERROR', 'Unable to plot the flat source region ' + \ - 'scalar flux since the energy_groups argument ' + \ - 'is %s which is not an energy group index or a list ' + \ - 'of energy group indices', str(energy_groups)) + filename = 'segments-{0}-angles-{1}-spacing'.format(num_azim, spacing) + filename = '{0}-z-{1}.png'.format(filename, z[0]) + fig.savefig(directory+filename, bbox_inches='tight') + plt.close(fig) + + +def plot_materials(geometry, gridsize=250, xlim=None, ylim=None, zcoord=None, + get_figure=False, library='matplotlib'): + """Plot a color-coded 2D surface plot of the materials in the geometry. + + The geometry must be initialized with materials, cells, universes and + lattices before being passed into this routine. + + Parameters + ---------- + geometry : openmoc.Geometry + An OpenMOC geometry + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + zcoord : Real, optional + The z coordinate (default is 0.0) + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_materials(geometry) + + """ + + cv.check_type('geometry', geometry, openmoc.Geometry) + + py_printf('NORMAL', 'Plotting the materials...') + + # Create an array of random integer colors for each Material + materials = geometry.getAllMaterials() + num_materials = len(materials) + colors = np.arange(num_materials) + numpy.random.seed(1) + numpy.random.shuffle(colors) + for i, material_id in enumerate(materials): + materials[material_id] = colors[i] + + # Initialize plotting parameters + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.domain_type = 'material' + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.zcoord = zcoord + plot_params.suptitle = 'Materials' + plot_params.title = 'z = {0}'.format(plot_params.zcoord) + plot_params.filename = 'materials-z-{0}'.format(plot_params.zcoord) + plot_params.interpolation = 'nearest' + plot_params.vmin = 0 + plot_params.vmax = num_materials + + # Plot a 2D color map of the Materials + figures = plot_spatial_data(materials, plot_params, get_figure) + + # Return the figure to the user if requested + if get_figure: + return figures[0] + + +def plot_cells(geometry, gridsize=250, xlim=None, ylim=None, + zcoord=None, get_figure=False, library='matplotlib'): + """Plots a color-coded 2D surface plot of the cells in the geometry. + + The geometry must be initialized with materials, cells, universes and + lattices before being passed into this routine. + + Parameters + ---------- + geometry : openmoc.Geometry + An OpenMOC geometry + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + zcoord : Real, optional + The z coordinate (default is 0.0) + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_cells(geometry) + + """ + + cv.check_type('geometry', geometry, openmoc.Geometry) + + py_printf('NORMAL', 'Plotting the cells...') + + # Create an array of random integer colors for each Cell + cells = geometry.getAllMaterialCells() + num_cells = len(cells) + colors = np.arange(num_cells) + numpy.random.seed(1) + numpy.random.shuffle(colors) + for i, cell_id in enumerate(cells): + cells[cell_id] = colors[i] + + # Initialize plotting parameters + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.domain_type = 'cell' + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.zcoord = zcoord + plot_params.suptitle = 'Cells' + plot_params.title = 'z = {0}'.format(plot_params.zcoord) + plot_params.filename = 'cells-z-{0}'.format(plot_params.zcoord) + plot_params.interpolation = 'nearest' + plot_params.vmin = 0 + plot_params.vmax = num_cells + + # Plot a 2D color map of the Cells + figures = plot_spatial_data(cells, plot_params, get_figure) + + # Return the figure to the user if requested + if get_figure: + return figures[0] + + +def plot_flat_source_regions(geometry, gridsize=250, xlim=None, ylim=None, + centroids=False, marker_type='o', marker_size=2, + get_figure=False, library='matplotlib'): + """Plots a color-coded 2D surface plot of the FSRs in the geometry. + + The geometry must be initialized with materials, cells, universes and + lattices before being passed into this routine. + + Parameters + ---------- + geometry : openmoc.Geometry + An OpenMOC geometry + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + centroids : bool + Whether to plot the FSR centroids (False by default) + marker_type : str + The marker type to use for FSR centroids ('o' by default) + marker_size : Integral + The marker size to use for FSR centroids (2 by default) + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_flat_source_regions(geometry) + + """ + + cv.check_type('geometry', geometry, openmoc.Geometry) + cv.check_type('centroids', centroids, bool) + cv.check_type('marker_type', marker_type, basestring) + cv.check_value('marker_type', marker_type, + tuple(matplotlib.markers.MarkerStyle().markers.keys())) + cv.check_type('marker_size', marker_size, Real) + cv.check_greater_than('marker_size', marker_size, 0) + + if geometry.getNumFSRs() == 0: + py_printf('ERROR', 'Unable to plot the flat source regions ' + + 'since no tracks have been generated.') + + py_printf('NORMAL', 'Plotting the flat source regions...') + + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory + + num_fsrs = geometry.getNumFSRs() + fsrs_to_fsrs = np.arange(num_fsrs, dtype=np.int64) + fsrs_to_fsrs = _colorize(fsrs_to_fsrs, num_fsrs) + + # Initialize plotting parameters + zcoord = geometry.getFSRPoint(0).getZ() + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.zcoord = zcoord + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.suptitle = 'Flat Source Regions' + plot_params.title = 'z = {0}'.format(zcoord) + plot_params.filename = 'flat-source-regions-z-{0}'.format(zcoord) + plot_params.interpolation = 'nearest' + plot_params.vmin = 0 + plot_params.vmax = num_fsrs - if not is_integer(gridsize): - py_printf('ERROR', 'Unable to plot the flat source region scalar flux ' + \ - 'since since the gridsize %s is not an integer', str(gridsize)) + # Plot a 2D color map of the flat source regions + figures = plot_spatial_data(fsrs_to_fsrs, plot_params, get_figure=True) + fig = figures[0] + + # Plot centroids on top of 2D flat source region color map + if centroids: + + # Populate a NumPy array with the FSR centroid coordinates + centroids = np.zeros((num_fsrs, 2), dtype=np.float) + for fsr_id in range(num_fsrs): + point = geometry.getFSRCentroid(fsr_id) + centroids[fsr_id,:] = [point.getX(), point.getY()] + + # Plot centroids on figure using matplotlib + if library == 'pil': + + # Retrieve the plot bounds + coords = _get_pixel_coords(plot_params) + r = marker_size + + # Open a PIL ImageDraw portal on the Image object + from PIL import ImageDraw + draw = ImageDraw.Draw(fig) + + for fsr_id in range(num_fsrs): + # Retrieve the pixel coordinates for this centroid + x, y = centroids[fsr_id,:] + + # Only plot centroid if it is within the plot bounds + if x < coords['bounds'][0] or x > coords['bounds'][1]: + continue + elif y < coords['bounds'][2] or y > coords['bounds'][3]: + continue + + # Transform the centroid into pixel coordinates + x = int((x-coords['x'][1]) / (coords['x'][1]-coords['x'][0])) + y = int((y-coords['y'][1]) / (coords['y'][1]-coords['y'][0])) + + # Draw circle for this centroid on the image + draw.ellipse((x-r, y-r, x+r, y+r), fill=(0, 0, 0)) + + # Plot centroids on figure using PIL + else: + plt.scatter(centroids[:,0], centroids[:,1], color='k', + marker=marker_type, s=marker_size) + + # Return the figure to the user if requested + if get_figure: + return figures[0] + # Set the plot title and save the figure + else: + plot_filename = directory + plot_params.filename + plot_params.extension + + if library == 'pil': + fig.save(plot_filename) + else: + fig.savefig(plot_filename, bbox_inches='tight') + plt.close(fig) + + +def plot_cmfd_cells(geometry, cmfd, gridsize=250, xlim=None, ylim=None, + get_figure=False, library='matplotlib'): + """Plots a color-coded 2D surface plot of the CMFD cells in a geometry. + + The geometry must be initialized with materials, cells, universes and + lattices before being passed into this method. Plotting the CMFD cells + requires that segments must have been created for the geometry and FSR IDs + assigned to regions. + + Parameters + ---------- + geometry : openmoc.Geometry + An OpenMOC geometry + cmfd : openmoc.Cmfd + An OpenMOC cmfd + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_cmfd_cells(geometry, cmfd) + + """ + + cv.check_type('geometry', geometry, openmoc.Geometry) + cv.check_type('cmfd', cmfd, openmoc.Cmfd) + + py_printf('NORMAL', 'Plotting the CMFD cells...') + + # Create a NumPy array to map FSRs to CMFD cells + num_fsrs = geometry.getNumFSRs() + fsrs_to_cmfd_cells = np.zeros(num_fsrs, dtype=np.int64) + for fsr_id in range(num_fsrs): + fsrs_to_cmfd_cells[fsr_id] = cmfd.convertFSRIdToCmfdCell(fsr_id) + + # Assign random color scheme to CMFD cells + num_cmfd_cells = cmfd.getNumCells() + fsrs_to_cmfd_cells = _colorize(fsrs_to_cmfd_cells, num_cmfd_cells) + + # Initialize plotting parameters + zcoord = geometry.getFSRPoint(0).getZ() + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.zcoord = zcoord + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.suptitle = 'CMFD Cells' + plot_params.title = 'z = {0}'.format(zcoord) + plot_params.filename = 'cmfd-cells-{0}'.format(zcoord) + plot_params.interpolation = 'nearest' + plot_params.vmin = 0 + plot_params.vmax = num_cmfd_cells + + # Plot the CMFD cells + figures = plot_spatial_data(fsrs_to_cmfd_cells, plot_params, get_figure) + + # Return the figure to the user if requested + if get_figure: + return figures[0] + + +def plot_spatial_fluxes(solver, energy_groups=[1], norm=False, gridsize=250, + xlim=None, ylim=None, get_figure=False, + library='matplotlib'): + """Plot a color-coded 2D surface plot of the FSR scalar fluxes for one or + more energy groups. + + The solver must have converged the FSR sources before calling this routine. + + Parameters + ---------- + solver : openmoc.Solver + An OpenMOC solver used to compute the flux + energy_groups : Iterable of Integral + The energy groups to plot (starting at 1 for the highest energy) + norm : bool, optional + Whether to normalize the fluxes to the mean (False by default) + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : list of matplotlib.Figure or None + The Matplotlib figures are returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,7]) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_type('energy_groups', energy_groups, Iterable, Integral) + + py_printf('NORMAL', 'Plotting the FSR scalar fluxes...') + + # Initialize plotting parameters + geometry = solver.getGeometry() + zcoord = geometry.getFSRPoint(0).getZ() + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.zcoord = zcoord + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.colorbar = True + plot_params.cmap = plt.get_cmap('jet') + plot_params.norm = norm + + # Get array of FSR energy-dependent fluxes + fluxes = get_scalar_fluxes(solver) + + # Initialize an empty list of Matplotlib figures if requestd by the user + figures = [] + + # Loop over all energy group and create a plot + for index, group in enumerate(energy_groups): + plot_params.suptitle = 'FSR Scalar Flux (Group {0})'.format(group) + plot_params.title = 'z = {0}'.format(zcoord) + plot_params.filename = 'fsr-flux-group-{0}-z-{1}'.format(group, zcoord) + fig = plot_spatial_data(fluxes[:,index], plot_params, get_figure) + + if get_figure: + figures.append(fig[0]) + + # Return figures if requested by the user + if get_figure: + return figures + + +def plot_energy_fluxes(solver, fsrs, group_bounds=None, norm=True, + loglog=True, get_figure=False): + """Plot the scalar flux vs. energy for one or more FSRs. + + The Solver must have converged the FSR sources before calling this routine. + The routine will generate a step plot of the flux across each energy group. + + An optional parameter for the energy group bounds may be input. The group + bounds should be input in increasing order of energy. If group bounds are + not specified, the routine will use equal width steps for each energy group. + + Parameters + ---------- + solver : openmoc.Solver + An OpenMOC solver used to compute the flux + fsrs : Iterable of Integral + The FSRs for which to plot the flux + group_bounds : Iterable of Real or None, optional + The bounds of the energy groups + norm : bool, optional + Whether to normalize the fluxes (True by default) + loglog : bool + Whether to use a log scale on the x- and y-axes (True by default) + get_figure : bool + Whether to return the Matplotlib figure + + Returns + ------- + fig : list of matplotlib.Figure or None + The Matplotlib figures are returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_energy_fluxes(solver, fsrs=[1,5,20], \ + group_bounds=[0., 0.625, 2e7]) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_type('fsrs', fsrs, Iterable, Integral) + cv.check_type('norm', norm, bool) + cv.check_type('loglog', loglog, bool) + cv.check_type('get_figure', get_figure, bool) + + geometry = solver.getGeometry() + num_groups = geometry.getNumEnergyGroups() + + if group_bounds: + cv.check_type('group_bounds', group_bounds, Iterable, Real) + if not all(low < up for low, up in zip(group_bounds, group_bounds[1:])): + py_printf('ERROR', 'Unable to plot the flux vs. energy since ' + + 'the group bounds are not monotonically increasing') + else: + group_bounds = np.arange(num_groups+1, dtype=np.int) + loglog = False + + py_printf('NORMAL', 'Plotting the scalar fluxes vs. energy...') + + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory + + # Ensure that normal settings are used even if called from ipython + curr_rc = dict(matplotlib.rcParams) + matplotlib.rcParams.update(matplotlib_rcparams) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + # Compute difference in energy bounds for each group + group_deltas = np.ediff1d(group_bounds) + group_bounds = np.flipud(group_bounds) + group_deltas = np.flipud(group_deltas) + + # Initialize an empty list of Matplotlib figures if requestd by the user + figures = [] + + # Iterate over all flat source regions + for fsr in fsrs: + + # Allocate memory for an array of this FSR's fluxes + fluxes = np.zeros(num_groups, dtype=np.float) + + # Extract the flux in each energy group + for group in range(num_groups): + fluxes[group] = solver.getFlux(fsr, group+1) + + # Normalize fluxes to the total integrated flux + if norm: + fluxes /= np.sum(group_deltas * fluxes) + + # Initialize a separate plot for this FSR's fluxes + fig = plt.figure() + fig.patch.set_facecolor('none') + + # Draw horizontal/vertical lines on the plot for each energy group + for group in range(num_groups): + + # Horizontal line + if loglog: + plt.loglog(group_bounds[group:group+2], [fluxes[group]]*2, + linewidth=3, c='b', label='openmoc', linestyle='-') + else: + plt.plot(group_bounds[group:group+2], [fluxes[group]]*2, + linewidth=3, c='b', label='openmoc', linestyle='-') + + # Vertical lines + if group < num_groups - 1: + if loglog: + plt.loglog([group_bounds[group+1]]*2, fluxes[group:group+2], + c='b', linestyle='--') + else: + plt.plot([group_bounds[group+1]]*2, fluxes[group:group+2], + c='b', linestyle='--') + + plt.xlabel('Energy') + plt.ylabel('Flux') + plt.xlim((min(group_bounds), max(group_bounds))) + plt.grid() + plt.title('FSR {0} Flux ({1} groups)'.format(fsr, num_groups)) + + # Save the figure to a file or return to user if requested + if get_figure: + figures.append(fig) + else: + filename = 'flux-fsr-{0}.png'.format(fsr) + plt.savefig(directory+filename, bbox_inches='tight') + plt.close(fig) + + # Restore settings if called from ipython + matplotlib.rcParams.update(curr_rc) + + # Return the figures if requested by user + if get_figure: + return figures + + +def plot_fission_rates(solver, norm=False, transparent_zeros=True, gridsize=250, + xlim=None, ylim=None, get_figure=False, + library='matplotlib'): + """Plot a color-coded 2D surface plot representing the FSR fission rates. + + The Solver must have converged the FSR sources before calling this routine. + The fission rates are computed as the volume-averaged and energy-integrated + fission rates in each FSR. + + Parameters + ---------- + solver : openmoc.Solver + An OpenMOC solver used to compute the flux + norm : bool + Whether to normalize the fission rates (False by default) + transparent_zeros : bool + Whether to make all non-fissionable FSRs transparent (True by default) + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_fission_rates(solver) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + + py_printf('NORMAL', 'Plotting the flat source region fission rates...') + + # Compute the volume-weighted fission rates for each FSR + geometry = solver.getGeometry() + fission_rates = solver.computeFSRFissionRates(geometry.getNumFSRs()) + + # Initialize plotting parameters + zcoord = geometry.getFSRPoint(0).getZ() + plot_params = PlotParams() + plot_params.geometry = geometry + plot_params.zcoord = zcoord + plot_params.gridsize = gridsize + plot_params.library = library + plot_params.xlim = xlim + plot_params.ylim = ylim + plot_params.suptitle = 'Flat Source Region Fission Rates' + plot_params.title = 'z = {0}'.format(zcoord) + plot_params.filename = 'fission-rates-z-{0}.png'.format(zcoord) + plot_params.transparent_zeros = True + plot_params.colorbar = True + plot_params.cmap = plt.get_cmap('jet') + plot_params.norm = norm + + # Plot the fission rates + figures = plot_spatial_data(fission_rates, plot_params, get_figure) + + # Return the figure if requested by user + if get_figure: + return figures[0] + + +def plot_eigenmode_fluxes(iramsolver, eigenmodes=[], energy_groups=[1], + norm=False, gridsize=250, xlim=None, ylim=None, + get_figure=False, library='matplotlib'): + """Plot the color-coded 2D surface plot of FSR scalar fluxes for one or + more eigenmodes from an IRAMSolver. + + The IRAMSolver must have computed the eigenmodes before calling this routine. + + Parameters + ---------- + iramsolver : openmoc.krylov.IRAMSolver + An OpenMOC IRAM solver used to compute the flux eigenmodes + energy_groups : Iterable of Integral + The energy groups to plot (starting at 1 for the highest energy) + norm : bool + Whether to normalize the fission rates (False by default) + gridsize : Integral, optional + The number of grid cells for the plot (250 by default) + xlim : 2-tuple of Real, optional + The minimim/maximum x-coordinates + ylim : 2-tuple of Real, optional + The minimim/maximum y-coordinates + get_figure : bool + Whether to return the Matplotlib figure (only if library='matplotlib') + library : {'matplotlib', 'pil'} + The plotting library to use + + Returns + ------- + fig : list of matplotlib.Figure or None + The Matplotlib figures are returned if get_figure is True + + Examples + -------- + A user may invoke this function from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_eigenmode_fluxes(iramsolver, energy_groups=[3]) + + """ + + cv.check_type('iramsolver', iramsolver, openmoc.krylov.IRAMSolver) + cv.check_type('eigenmodes', eigenmodes, Iterable, Integral) + + py_printf('NORMAL', 'Plotting the eigenmode fluxes...') + + global subdirectory + directory = openmoc.get_output_directory() + subdirectory + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + # Extract the MOC Solver from the IRAMSolver + moc_solver = iramsolver._moc_solver + + # Initialize a list of figures to return to user if requested + figures = [] + + # Loop over each eigenmode + for mode in eigenmodes: + + # Extract the eigenvector for this eigenmode from the IRAMSolver + eigenvec = iramsolver._eigenvectors[:,mode-1] + + # Convert it into a form that SWIG will be happy with + eigenvec = np.squeeze(np.ascontiguousarray(eigenvec)) + eigenvec = np.real(eigenvec).astype(iramsolver._precision) + + # Ensure the primary eigenvector is positive + if mode == 1: + eigenvec = np.abs(eigenvec) + + # Insert eigenvector into MOC Solver object + moc_solver.setFluxes(eigenvec) + + # Set subdirectory folder for this eigenmode + num_digits = len(str(max(eigenmodes))) + subdirectory = \ + '/plots/eig-{0}-flux/'.format(str(mode).zfill(num_digits)) + + # Plot this eigenmode's spatial fluxes + fig = plot_spatial_fluxes(moc_solver, energy_groups, norm, gridsize, + xlim, ylim, get_figure, library) + + if get_figure: + figures.append(fig[0]) + + # Reset global subdirectory + subdirectory = '/plots/' + + # Return Matplotlib figures if requested by user + if get_figure: + return figures + + +def plot_spatial_data(domains_to_data, plot_params, get_figure=False): + """Plots a color-coded 2D surface plot of arbitrary data mapped to each + spatial domain in the geometry. + + The plot_params must include the domain type encoded in domains_to_data. + + Parameters + ---------- + domains_to_data : dict or numpy.ndarray or pandas.DataFrame + A mapping between spatial domain IDs and numerical data to plot. + In the case of 'material' and 'cell' domain types, domains_to_data must + be a Python dictionary with keys representing material/cell IDs and + values of the data to plot. In the case of the 'fsr' domain type, + domains_to_data may be a dictionary, NumPy array or a Pandas DataFrame + indexed by FSR ID and values of the data to plot. + plot_params : openmoc.plotter.PlotParams + The plotting parameters + get_figure : bool, optional + Whether to return the Matplotlib figures (False by default) + + Returns + ------- + fig : list of matplotlib.Figure or None + The Matplotlib figures are returned if get_figure is True - if not is_integer(energy_groups) and not isinstance(energy_groups, list): - py_printf('ERROR', 'Unable to plot the flat source region scalar ' + \ - 'flux since the energy_groups is not an int or a list') + Examples + -------- + A user may invoke this function from an Python file as follows: + >>> fsrs_to_data = numpy.random.rand(geometry.getNumFSRS()) + >>> plot_params = PlotParams() + >>> plot_params.domain_type = 'fsr' + >>> openmoc.plotter.plot_spatial_data(fsrs_to_data, plot_params) - if gridsize <= 0: - py_printf('ERROR', 'Unable to plot the flat source regions ' + \ - 'with a negative gridsize (%d)', gridsize) + """ - py_printf('NORMAL', 'Plotting the flat source region scalar fluxes...') + cv.check_type('plot_params', plot_params, PlotParams) - if not isinstance(energy_groups, list): - energy_groups = [energy_groups] + # Determine the number of domains + if plot_params.domain_type == 'material': + num_domains = len(plot_params.geometry.getAllMaterials()) + elif plot_params.domain_type == 'cell': + num_domains = len(plot_params.geometry.getAllMaterialCells()) + else: + num_domains = plot_params.geometry.getNumFSRs() + + if isinstance(domains_to_data, (np.ndarray, dict)): + pandas_df = False + if len(domains_to_data) != num_domains: + py_printf('ERROR', 'The domains_to_data array is length %d but ' + + 'there are %d domains', len(domains_to_data), num_domains) + elif 'DataFrame' in str(type(domains_to_data)): + pandas_df = True + if len(domains_to_data) != plot_params.geometry.getNumFSRs(): + py_printf('ERROR', 'The domains_to_data DataFrame is length %d ' + + 'but there are %d domains in the Geometry', + len(domains_to_data), num_domains) + else: + py_printf('ERROR', 'Unable to plot spatial data since ' + + 'domains_to_data is not a dict, array or DataFrame') - # Initialize a numpy array for the groupwise scalar fluxes - fluxes = numpy.zeros((len(energy_groups), gridsize, gridsize)) + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory - # Retrieve the pixel coordinates - coords = get_pixel_coords(geometry, gridsize, xlim, ylim) + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) - for i in range(gridsize): - for j in range(gridsize): + # Initialize a numpy array for the spatial data + domains = np.zeros((plot_params.gridsize, plot_params.gridsize), dtype=np.int) - # Find the flat source region IDs for each grid point - x = coords['x'][i] - y = coords['y'][j] + # Retrieve the pixel coordinates + coords = _get_pixel_coords(plot_params) - point = LocalCoords(x, y) - point.setUniverse(geometry.getRootUniverse()) - geometry.findCellContainingCoords(point) - fsr_id = geometry.getFSRId(point) + for i in range(plot_params.gridsize): + for j in range(plot_params.gridsize): - # If we did not find a region for this region, use a -1 "bad" number color - if np.isnan(fsr_id): - fluxes[:,j,i] = -1 + # Find the domain IDs for each grid point + x = coords['x'][i] + y = coords['y'][j] - # Get the scalar flux for each energy group in this FSR - else: - for index, group in enumerate(energy_groups): - fluxes[index,j,i] = solver.getFSRScalarFlux(fsr_id, group) + point = openmoc.LocalCoords(x, y, plot_params.zcoord) + point.setUniverse(plot_params.geometry.getRootUniverse()) + cell = plot_params.geometry.findCellContainingCoords(point) - # Loop over all energy group and create a plot - for index, group in enumerate(energy_groups): + if plot_params.domain_type == 'fsr': + domain_id = plot_params.geometry.getFSRId(point) + elif plot_params.domain_type == 'material': + domain_id = cell.getFillMaterial().getId() + else: + domain_id = cell.getId() - # Plot a 2D color map of the flat source regions + # If we did not find a domain, use a -1 "bad" number color + if np.isnan(domain_id): + domains[j][i] = -1 + else: + domains[j][i] = domain_id + + # Make domains-to-data array 2D to mirror a Pandas DataFrame + if isinstance(domains_to_data, np.ndarray): + domains_to_data.shape += (1,) + + # Determine the number of plots to generate + if pandas_df or isinstance(domains_to_data, np.ndarray): + num_plots = domains_to_data.shape[1] + else: + num_plots = int(len(domains_to_data) / num_domains) + + # Initialize a list of Matplotlib figures to return to user if requested + figures = [] + + # Loop over all columns in NumPy array or Pandas DataFrame input + for i in range(num_plots): + + # Use domain IDs to appropriately index into FSR data + # If domains-to-data was input as a Pandas DataFrame + if pandas_df: + surface = domains_to_data.ix[:,i].values + surface = surface.take(domains.flatten()) + # If domains-to-data was input as a NumPy array + elif isinstance(domains_to_data, np.ndarray): + surface = domains_to_data.take(domains.flatten()) + # If domains-to-data was input as a Python dictionary + else: + surface = np.zeros(domains.shape, dtype=np.int) + for domain_id in domains_to_data: + indices = np.where(domains == domain_id) + surface[indices] = domains_to_data[domain_id] + + # Reshape data to 2D array for Matplotlib image plot + surface.shape = (plot_params.gridsize, plot_params.gridsize) + + # Normalize data to maximum if requested + if plot_params.norm: + surface /= np.max(surface) + + # Set zero data entries to NaN so Matplotlib will make them transparent + if plot_params.transparent_zeros: + indices = np.where(surface == 0.0) + surface[indices] = np.nan + + # Color "bad" numbers (ie, NaN, INF) with transparent pixels + if plot_params.cmap: + plot_params.cmap.set_bad(alpha=0.0) + + # Create plot filename + plot_filename = directory + plot_params.filename + + # If input was Pandas DataFrame, append column name to filename + if pandas_df: + plot_filename += '-{0}'.format(domains_to_data.columns[i]) + + # Append file extension (e.g., '.png', '.ppm') to filename + plot_filename += plot_params.extension + + # Use Python Imaging Library (PIL) to plot 2D color map of domain data + if plot_params.library == 'pil': + img = _get_pil_image(np.flipud(surface), plot_params) + + if get_figure: + figures.append(img) + else: + img.save(plot_filename) + + # Use Matplotlib to plot 2D color map of domain data + else: + + # Ensure that normal settings are used even if called from ipython + curr_rc = dict(matplotlib.rcParams) + matplotlib.rcParams.update(matplotlib_rcparams) + + fig = plt.figure() + fig.patch.set_facecolor('none') + plt.imshow(np.flipud(surface), extent=coords['bounds'], + interpolation=plot_params.interpolation, + vmin=plot_params.vmin, vmax=plot_params.vmax, + cmap=plot_params.cmap) + + if plot_params.colorbar: + plt.colorbar() + if plot_params.title: + plt.title(plot_params.title) + + if plot_params.suptitle: + # If input was Pandas DataFrame, append column name to suptitle + if pandas_df: + suptitle = plot_params.suptitle + suptitle += ' ({0})'.format(domains_to_data.columns[i]) + else: + suptitle = plot_params.suptitle + + plt.suptitle(suptitle) + + # If the user requested the Matplotlib figure handles for further + # specialization, append the handle to this figure to a list + if get_figure: + figures.append(fig) + + # Otherwise, save this Matplotlib figure + else: + fig.savefig(plot_filename, bbox_inches='tight') + plt.close() + + # Restore settings if called from ipython + matplotlib.rcParams.update(curr_rc) + + # Return Matplotlib figures if requested by user + if get_figure: + return figures + + +def plot_quadrature(solver, get_figure=False): + """Plots the quadrature set used for an OpenMOC simulation. + + This method requires that tracks have been generated by a TrackGenerator + owned by the solver. + + Paramters + --------- + solver : openmoc.Solver + An OpenMOC solver with a trackgenerator + get_figure : bool + Whether to return the Matplotlib figure + + Returns + ------- + fig : matplotlib.Figure or None + The Matplotlib figure is returned if get_figure is True + + Examples + -------- + A user may invoke this routine from an OpenMOC Python file as follows: + + >>> openmoc.plotter.plot_quadrature(solver) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + + py_printf('NORMAL', 'Plotting the quadrature...') + + global subdirectory, matplotlib_rcparams + directory = openmoc.get_output_directory() + subdirectory + + # Ensure that normal settings are used even if called from ipython + curr_rc = dict(matplotlib.rcParams) + matplotlib.rcParams.update(matplotlib_rcparams) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + # Retrieve data from TrackGenerator + track_generator = solver.getTrackGenerator() + polar_quad = solver.getPolarQuad() + num_azim = track_generator.getNumAzim() + azim_spacing = track_generator.getTrackSpacing() + num_polar = polar_quad.getNumPolarAngles() + phis = np.zeros(num_azim/4) + thetas = np.zeros(num_polar) + + # Get the polar angles + for p in range(num_polar): + thetas[p] = np.arcsin(polar_quad.getSinTheta(p)) + + # Get the azimuthal angles + for a in range(int(num_azim / 4)): + phis[a] = track_generator.getPhi(a) + + # Make a 3D figure fig = plt.figure() - plt.imshow(np.flipud(fluxes[index,:,:]), extent=coords['bounds']) - plt.colorbar() - plt.title('Flat Source Region Scalar Flux in Group ' + str(group)) - filename = directory + 'fsr-flux-group-' + str(group) + '.png' - fig.savefig(filename, bbox_inches='tight') - plt.close(fig) - - -## -# @brief This method takes in a Geometry object and plots a color-coded 2D -# surface plot representing the flat source region fission rates in -# the Geometry. -# @details The geometry object must be initialized with Materials, Cells, -# Universes and Lattices before being passed into this method. A user -# may invoke this function from an OpenMOC Python file as follows: -# -# @code -# openmoc.plotter.plot_fission_rates(geometry, solver) -# @endcode -# -# @param geometry a Geometry object which has been initialized with Materials, -# Cells, Universes and Lattices -# @param solver a Solver object that has converged the source for the Geometry -# @param gridsize an optional number of grid cells for the plot -# @param xlim optional list/tuple of the minimim/maximum x-coordinates -# @param ylim optional list/tuple of the minimim/maximum y-coordinates -def plot_fission_rates(geometry, solver, gridsize=250, xlim=None, ylim=None): - - global subdirectory - - directory = get_output_directory() + subdirectory - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Error checking - if not 'Geometry' in str(type(geometry)): - py_printf('ERROR', 'Unable to plot the fission rates ' + \ - 'since input did not contain a geometry class object') - - if not 'Solver' in str(type(solver)): - py_printf('ERROR', 'Unable to plot the fission rates ' + \ - 'since input did not contain a solver class object') - - if not is_integer(gridsize): - py_printf('ERROR', 'Unable to plot the fission rates ' + \ - 'since since the gridsize %s is not an integer', str(gridsize)) - - if gridsize <= 0: - py_printf('ERROR', 'Unable to plot the fission rates ' + \ - 'with a negative gridsize (%d)', gridsize) - - py_printf('NORMAL', 'Plotting the flat source region fission rates...') - - # Get geometry - geometry = solver.getGeometry() - - # Compute the volume-weighted fission rates for each FSR - fission_rates = solver.computeFSRFissionRates(geometry.getNumFSRs()) - - # Initialize a numpy array of fission rates - surface = numpy.zeros((gridsize, gridsize)) - - # Retrieve the pixel coordinates - coords = get_pixel_coords(geometry, gridsize, xlim, ylim) - - for i in range(gridsize): - for j in range(gridsize): - - # Find the flat source region IDs for each grid point - x = coords['y'][i] - y = coords['x'][j] - - point = LocalCoords(x, y) - point.setUniverse(geometry.getRootUniverse()) - geometry.findCellContainingCoords(point) - fsr_id = geometry.getFSRId(point) - - # If we did not find a region for this region, use a -1 "bad" number color - if np.isnan(fsr_id): - surface[j][i] = -1 - # Get the fission rate in this FSR - else: - surface[j][i] = fission_rates[fsr_id] - - # Plot a 2D color map of the flat source regions fission rates - fig = plt.figure() - plt.imshow(np.flipud(surface), extent=coords['bounds']) - plt.colorbar() - plt.title('Flat Source Region Fission Rates') - filename = directory + 'fission-rates.png' - fig.savefig(filename, bbox_inches='tight') - - -## -# @brief This is a helper method to define coordinates for a plotting window. -# @details This routine builds a coordinate surface map for the plotting -# window defined for by the user. If no window was defined, then -# this routine uses the outer bounding box around the geometry as -# the plotting window. -# @param geometry a Geometry object which has been initialized with Materials, -# Cells, Universes and Lattices -# @param gridsize an optional number of grid cells for the plot -# @param xlim optional list/tuple of the minimim/maximum x-coordinates -# @param ylim optional list/tuple of the minimim/maximum y-coordinates -# @return a dictionary with the plotting window map and bounding box -def get_pixel_coords(geometry, gridsize, xlim, ylim): - - # initialize variables to be returned - bounds = [geometry.getMinX() + TINY_MOVE, geometry.getMaxX() - TINY_MOVE, - geometry.getMinY() + TINY_MOVE, geometry.getMaxY() - TINY_MOVE] - xcoords = None - ycoords = None - coords = dict() - - if not xlim is None: - bounds[0] = xlim[0] - bounds[1] = xlim[1] - - if not ylim is None: - bounds[2] = ylim[0] - bounds[3] = ylim[1] - - xcoords = np.linspace(bounds[0], bounds[1], gridsize) - ycoords = np.linspace(bounds[2], bounds[3], gridsize) - - # add attributes to coords dictionary - coords['x'] = xcoords - coords['y'] = ycoords - coords['bounds'] = bounds - - return coords + fig.patch.set_facecolor('none') + ax = fig.gca(projection ='3d') + + # Plot a wire mesh on one octant of the unit sphere + u = np.linspace(0, np.pi/2.0, 100) + v = np.linspace(0, np.pi/2.0, 100) + x = np.outer(np.cos(u), np.sin(v)) + y = np.outer(np.sin(u), np.sin(v)) + z = np.outer(np.ones(np.size(u)), np.cos(v)) + ax.plot_wireframe(x, y, z, rstride=5, cstride=5, color='k', linewidth=0.1) + + # Plot the quadrature points on the octant unit sphere + for a in range(int(num_azim / 4)): + for p in range(num_polar): + ax.scatter(np.cos(phis[a]) * np.sin(thetas[p]), np.sin(phis[a]) * + np.sin(thetas[p]), np.cos(thetas[p]), s=50, color='b') + + # Get the quadrature type + quad_type = '' + if polar_quad.getQuadratureType() is openmoc.TABUCHI_YAMAMOTO: + quad_type = 'TABUCHI_YAMAMOTO' + title = 'TABUCHI YAMAMOTO' + elif polar_quad.getQuadratureType() is openmoc.LEONARD: + quad_type = 'LEONARD' + title = 'LEONARD' + elif polar_quad.getQuadratureType() is openmoc.GAUSS_LEGENDRE: + quad_type = 'GAUSS_LEGENDRE' + title = 'GAUSS LEGENDRE' + elif polar_quad.getQuadratureType() is openmoc.EQUAL_WEIGHTS: + quad_type = 'EQUAL_WEIGHTS' + title = 'EQUAL WEIGHTS' + elif polar_quad.getQuadratureType() is openmoc.EQUAL_ANGLES: + quad_type = 'EQUAL_ANGLES' + title = 'EQUAL ANGLES' + elif polar_quad.getQuadratureType() is openmoc.CUSTOM: + quad_type = 'CUSTOM' + title = 'CUSTOM' + else: + py_printf('ERROR', 'Unable to plot the quadrature since the ' + + 'quadrature type could not be recognized') + + title += ' with ' + str(num_azim) + ' azim, ' + \ + '{:5.3f}'.format(azim_spacing) + ' spacing and ' \ + + str(num_polar) + ' polar' + + filename = directory + 'quad_' + quad_type + '_' + \ + str(num_azim) + '_azim_' + '{:5.3f}'.format(azim_spacing) + \ + '_cm_spacing_' + str(num_polar) + '_polar.png' + + ax.view_init(elev=30, azim=45) + ax.set_xlim([0,1]) + ax.set_ylim([0,1]) + ax.set_zlim([0,1]) + plt.title(title) + + # Restore settings if called from ipython + matplotlib.rcParams.update(curr_rc) + + # Save the figure or return to user + if get_figure: + return fig + else: + fig.savefig(filename, bbox_inches='tight') + plt.close(fig) + + +class PlotParams(object): + """A container for plotting parameters for spatially-varying plots. + + Attributes + ---------- + geometry : openomc.Geometry + The Geometry to query when generating the spatial map + domain_type : str + The domain type used to map spatial data to the geometry + filename : str + The filename string + extension : str + The image file extension (e.g., '.png') + library : {'matplotlib', 'pil'} + The image processing library to use to generate the plot + zcoord : Real + The z-coordinate at which to slice the Geometry + gridsize : Integral + The number of points along the x- and y-axes + xlim : 2-tuple of Real + A 2-tuple of (maximum, minimum) x-coordinates to display + ylim : 2-tuple of Real + A 2-tuple of (maximum, minimum) y-coordinates to display + title : str + The minor title string + suptitle : str + The major title string + norm : bool + Normalize the plotted data to unity + transparent_zeros : bool + Make zeros in the data appear transparent + interpolation : str + Interpolation used between points (e.g., 'nearest') + colorbar : bool + Include a colorbar to the right of the plot + cmap : matplotlib.colormap + A Matplotlib colormap for the plot + vmin : Real + The minimum value used in colormapping the data + vmax : Real + The maximum value used in colormapping the data + + """ + + def __init__(self): + + self._geometry = None + self._domain_type = 'fsr' + self._filename = None + self._extension = '.png' + self._library = 'matplotlib' + self._zcoord = 0 + self._gridsize = 250 + self._xlim = None + self._ylim = None + self._title = None + self._suptitle = None + self._norm = False + self._transparent_zeros = False + self._interpolation = None + self._colorbar = False + self._cmap = plt.get_cmap('spectral') + self._vmin = None + self._vmax = None + + @property + def geometry(self): + return self._geometry + + @property + def domain_type(self): + return self._domain_type + + @property + def filename(self): + return self._filename + + @property + def extension(self): + return self._extension + + @property + def library(self): + return self._library + + @property + def zcoord(self): + return self._zcoord + + @property + def gridsize(self): + return self._gridsize + + @property + def xlim(self): + return self._xlim + + @property + def ylim(self): + return self._ylim + + @property + def colorbar(self): + return self._colorbar + + @property + def title(self): + return self._title + + @property + def suptitle(self): + return self._suptitle + + @property + def norm(self): + return self._norm + + @property + def transparent_zeros(self): + return self._transparent_zeros + + @property + def interpolation(self): + return self._interpolation + + @property + def cmap(self): + return self._cmap + + @property + def vmin(self): + return self._vmin + + @property + def vmax(self): + return self._vmax + + @geometry.setter + def geometry(self, geometry): + cv.check_type('geometry', geometry, openmoc.Geometry) + self._geometry = geometry + self._check_zcoord() + + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain_type', domain_type, ('material', 'cell', 'fsr')) + self._domain_type = domain_type + + @filename.setter + def filename(self, filename): + cv.check_type('filename', filename, basestring) + self._filename = filename + + @extension.setter + def extension(self, extension): + cv.check_type('extension', extension, basestring) + self._extension = extension + + @library.setter + def library(self, library): + cv.check_value('library', library, ('matplotlib', 'pil')) + self._library = library + + @zcoord.setter + def zcoord(self, zcoord): + if zcoord: + self._zcoord = zcoord + self._check_zcoord() + + @gridsize.setter + def gridsize(self, gridsize): + cv.check_type('gridsize', gridsize, Integral) + cv.check_greater_than('gridsize', gridsize, 0) + self._gridsize = gridsize + + @xlim.setter + def xlim(self, xlim): + if xlim: + cv.check_type('xlim', xlim, tuple) + cv.check_length('xlim', xlim, 2, 2) + self._xlim = xlim + + @ylim.setter + def ylim(self, ylim): + if ylim: + cv.check_type('ylim', ylim, tuple) + cv.check_length('ylim', ylim, 2, 2) + self._ylim = ylim + + @colorbar.setter + def colorbar(self, colorbar): + cv.check_type('colorbar', colorbar, bool) + self._colorbar = colorbar + + @title.setter + def title(self, title): + cv.check_type('title', title, basestring) + self._title = title + + @suptitle.setter + def suptitle(self, suptitle): + cv.check_type('suptitle', suptitle, basestring) + self._suptitle = suptitle + + @norm.setter + def norm(self, norm): + cv.check_type('norm', norm, bool) + self._norm = norm + + @transparent_zeros.setter + def transparent_zeros(self, transparent_zeros): + cv.check_type('transparent_zeros', transparent_zeros, bool) + self._transparent_zeros = transparent_zeros + + @interpolation.setter + def interpolation(self, interpolation): + cv.check_type('interpolation', interpolation, basestring) + self._interpolation = interpolation + + @cmap.setter + def cmap(self, cmap): + cv.check_type('cmap', cmap, matplotlib.colors.Colormap) + self._cmap = cmap + + @vmin.setter + def vmin(self, vmin): + cv.check_type('vmin', vmin, Real) + self._vmin = vmin + + @vmax.setter + def vmax(self, vmax): + cv.check_type('vmax', vmax, Real) + self._vmax = vmax + + def _check_zcoord(self): + if self.zcoord and self.geometry: + cv.check_type('zcoord', self.zcoord, Real) + cv.check_greater_than('zcoord', self.zcoord, + self.geometry.getMinZ(), equality=True) + cv.check_less_than('zcoord', self.zcoord, + self.geometry.getMaxZ(), equality=True) + + +def _get_pixel_coords(plot_params): + """A helper method to define coordinates for a plotting window. + + This routine builds a coordinate surface map for the plotting window defined + for by the user. If no window was defined, then this routine uses the outer + bounding box around the geometry as the plotting window. + + Parameters + ---------- + plot_params : openmoc.plotter.PlotParams + A PlotParams object initialized with a geometry + + Returns + ------- + coords : dict + A dictionary with the plotting window map and bounding box + + """ + + # initialize variables to be returned + geometry = plot_params.geometry + bounds = [geometry.getMinX() + TINY_MOVE, geometry.getMaxX() - TINY_MOVE, + geometry.getMinY() + TINY_MOVE, geometry.getMaxY() - TINY_MOVE] + coords = dict() + + if not plot_params.xlim is None: + bounds[0] = plot_params.xlim[0] + bounds[1] = plot_params.xlim[1] + + if not plot_params.ylim is None: + bounds[2] = plot_params.ylim[0] + bounds[3] = plot_params.ylim[1] + + xcoords = np.linspace(bounds[0], bounds[1], plot_params.gridsize) + ycoords = np.linspace(bounds[2], bounds[3], plot_params.gridsize) + + # add attributes to coords dictionary + coords['x'] = xcoords + coords['y'] = ycoords + coords['bounds'] = bounds + + return coords + + +def _colorize(data, num_colors, seed=1): + """Replace unique data values with a random but reproducible color IDs. + + This routine randomly assigns a random integer to each unique value in the + input array. This is a helper routine for the plotting routine. + + Parameters + ---------- + data : numpy.ndarray + A NumPy array of data to colorize + num_colors : Integral + The number of random colors to generate + seed : Integral + The random number seed used to generate colors + + Returns + ------- + ids_to_colors : numpy.ndarray + A NumPy array with the random integer colors + + """ + + # Generate linearly-spaced array of color indices + all_ids = np.arange(num_colors, dtype=np.int64) + + # Generate linearly-spaced integer color IDs + id_colors = np.arange(num_colors, dtype=np.int64) + + # Randomly shuffle the linearly-spaced integer color IDs + numpy.random.seed(seed) + np.random.shuffle(id_colors) + + # Insert random colors into appropriate locations in data array + ids_to_colors = np.arange(num_colors, dtype=np.int64) + ids_to_colors[all_ids] = id_colors + + return ids_to_colors.take(data) + + +def _get_pil_image(array, plot_params): + """Plot 2D NumPy array data using Python Imaging Library (PIL). + + This is a good alternative to matplotlib for high-resolution images. + + Parameters + ---------- + array : numpy.ndarray + A NumPy array of data + plot_params : openmoc.plotter.PlotParmas + A PlotParams object with the matplotlib colormap to use + + Returns + ------- + float_array : PIL.Image + A Python Imaging Library (PIL) Image object + + """ + + from PIL import Image + + # Convert array to a normalized array of floating point values + float_array = np.zeros(array.shape, dtype=np.float) + float_array[:,:] = array[:,:] + float_array[:,:] /= np.max(float_array) + + # Use Python Imaging Library (PIL) to create an image from the array + return Image.fromarray(np.uint8(plot_params.cmap(float_array) * 255)) diff --git a/openmoc/process.py b/openmoc/process.py index ba47fd89b..77e2d7276 100644 --- a/openmoc/process.py +++ b/openmoc/process.py @@ -1,597 +1,991 @@ -## -# @file process.py -# @package openmoc.process -# @brief The process module provides utility functions for processing of -# OpenMOC simulations. -# @details This module provides downstream data processing capabilities for -# OpenMOC simulations, such as storing and retrieving simulation -# statepoint files, computing pin/assembly powers, and more. -# @author William Boyd (wboyd@mit.edu) -# @date April 27, 2013 - +import os +import re +import mmap import sys - -## @var openmoc -# @brief The openmoc module in use in the Python script using the -# openmoc.process module. -openmoc = '' - -# Determine which OpenMOC module is being used -if 'openmoc.gnu.double' in sys.modules: - openmoc = sys.modules['openmoc.gnu.double'] -elif 'openmoc.gnu.single' in sys.modules: - openmoc = sys.modules['openmoc.gnu.single'] -elif 'openmoc.intel.double' in sys.modules: - openmoc = sys.modules['openmoc.intel.double'] -elif 'openmoc.intel.single' in sys.modules: - openmoc = sys.modules['openmoc.intel.single'] -elif 'openmoc.bgq.double' in sys.modules: - openmoc = sys.modules['openmoc.bgq.double'] -elif 'openmoc.bgq.single' in sys.modules: - openmoc = sys.modules['openmoc.bgq.single'] -else: - from openmoc import * +import math +import datetime +import operator +from numbers import Integral, Real +from collections import Iterable +import pickle import numpy as np -import os +import h5py + +import openmoc # For Python 2.X.X if (sys.version_info[0] == 2): - from log import * + from log import * + import checkvalue as cv # For Python 3.X.X else: - from openmoc.log import * - - -## -# @brief This routine checks if a given value is an integer data type. -# -# @param val a value to check -def is_integer(val): - return isinstance(val, (int, np.int32, np.int64)) - - -## -# @brief This routine checks if a given value is a string data type. -# -# @param val a value to check -def is_string(val): - return isinstance(val, (str, np.str)) - - -## -# @brief This routine checks if a given value is an float data type. -# -# @param val a value to check -def is_float(val): - return isinstance(val, (float, np.float32, np.float64)) - - -## -# @brief This routine computes the fission rate in each flat source region, -# and combines the rates based on their hierarchical universe/lattice -# structure. The fission rates are then exported to a binary HDF5 -# or python pickle file. -# @details This routine is intended to be called by the user in Python to -# compute fission rates. Typically, the fission rates will represent -# pin powers. The routine either exports fission rates to an HDF5 -# binary file or pickle file with each fission rate being indexed by -# a string representing the universe/lattice hierarchy. -# This routine may be called from a Python script as follows: -# -# @code -# compute_fission_rates(solver, use_hdf5=True) -# @endcode -# -# @param solver a pointer to a Solver class object -# @param use_hdf5 whether or not to export fission rates to an HDF5 file -def compute_fission_rates(solver, use_hdf5=False): + from openmoc.log import * + import openmoc.checkvalue as cv - # create directory and filename - directory = get_output_directory() + '/fission-rates/' - filename = 'fission-rates' +if sys.version_info[0] >= 3: + basestring = str - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - # Get geometry - geometry = solver.getGeometry() +def get_scalar_fluxes(solver, fsrs='all', groups='all'): + """Return an array of scalar fluxes in one or more FSRs and groups. - # Compute the volume-weighted fission rates for each FSR - fsr_fission_rates = solver.computeFSRFissionRates(geometry.getNumFSRs()) + This routine builds a 2D NumPy array indexed by FSR and energy group for + the corresponding scalar fluxes. The fluxes are organized in the array in + order of increasing FSR and enery group if 'all' FSRs or energy groups are + requested (the default). If the user requests fluxes for specific FSRs or + energy groups, then the fluxes are returned in the order in which the FSRs + and groups are enumerated in the associated paramters. - # Initialize fission rates dictionary - fission_rates_sum = {} + Parameters + ---------- + solver : openmoc.Solver + The solver used to compute the flux + fsrs : Iterable of Integral or 'all' + A collection of integer FSR IDs or 'all' (default) + groups : Iterable of Integral or 'all' + A collection of integer energy groups or 'all' (default) - # Loop over FSRs and populate fission rates dictionary - for fsr in range(geometry.getNumFSRs()): + Returns + ------- + fluxes : ndarray + The scalar fluxes indexed by FSR ID and energy group. Note that the + energy group index starts at 0 rather than 1 for the highest energy + in accordance with Python's 0-based indexing. - if geometry.findFSRMaterial(fsr).isFissionable(): + """ - # Get the linked list of LocalCoords - point = geometry.getFSRPoint(fsr) - coords = LocalCoords(point.getX(), point.getY()) - coords.setUniverse(geometry.getRootUniverse()) - geometry.findCellContainingCoords(coords) - coords = coords.getHighestLevel().getNext() + cv.check_type('solver', solver, openmoc.Solver) - # initialize dictionary key - key = 'UNIV = 0 : ' + if isinstance('fsrs', basestring): + cv.check_value('fsrs', fsrs, 'all') + else: + cv.check_type('fsrs', Iterable, Integral) - # Parse through the linked list and create fsr key. - # If lowest level sub dictionary already exists, then increment - # fission rate; otherwise, set the fission rate. - while True: - if coords.getType() is LAT: - key += 'LAT = ' + str(coords.getLattice().getId()) + ' (' + \ - str(coords.getLatticeX()) + ', ' + \ - str(coords.getLatticeY()) + ') : ' - else: - key += 'UNIV = ' + str(coords.getUniverse().getId()) + ' : ' + if isinstance('groups', basestring): + cv.check_value('groups', fsrs, 'all') + else: + cv.check_type('groups', Iterable, Integral) - # Remove the trailing ' : ' on the end of the key if at last univ/lat - if coords.getNext() is None: - key = key[:-3] - break - else: - coords = coords.getNext() + # Build a list of FSRs to iterate over + if fsrs == 'all': + num_fsrs = solver.getGeometry().getNumFSRs() + fsrs = np.arange(num_fsrs) + else: + num_fsrs = len(fsrs) + + # Build a list of enery groups to iterate over + if groups == 'all': + num_groups = solver.getGeometry().getNumEnergyGroups() + groups = np.arange(num_groups) + 1 + else: + num_groups = len(groups) - # Increment or set fission rate - if key in fission_rates_sum: - fission_rates_sum[key] += fsr_fission_rates[fsr] - else: - fission_rates_sum[key] = fsr_fission_rates[fsr] + # Extract the FSR scalar fluxes + fluxes = np.zeros((num_fsrs, num_groups)) + for fsr in fsrs: + for group in groups: + fluxes[fsr, group-1] = solver.getFlux(int(fsr), int(group)) - # If using HDF5 - if use_hdf5: + return fluxes - import h5py - # Open HDF5 file - f = h5py.File(directory + filename + '.h5', 'w') +def compute_fission_rates(solver, use_hdf5=False): + """Computes the fission rate in each FSR. + + This method combines the rates based on their hierarchical universe/lattice + structure. The fission rates are then exported to a binary HDF5 or Python + pickle file. + + This routine is intended to be called by the user in Python to compute + fission rates. Typically, the fission rates will represent pin powers. The + routine either exports fission rates to an HDF5 binary file or pickle file + with each fission rate being indexed by a string representing the + universe/lattice hierarchy. + + Parameters + ---------- + solver : openmoc.Solver + The solver used to compute the flux + use_hdf5 : bool + Whether or not to export fission rates to an HDF5 file + + Examples + -------- + This routine may be called from a Python script as follows: + + >>> compute_fission_rates(solver, use_hdf5=True) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_type('use_hdf5', use_hdf5, bool) + + # Make directory if it does not exist + directory = openmoc.get_output_directory() + '/fission-rates/' + filename = 'fission-rates' + if not os.path.exists(directory): + os.makedirs(directory) + + # Get geometry + geometry = solver.getGeometry() + + # Compute the volume-weighted fission rates for each FSR + fsr_fission_rates = solver.computeFSRFissionRates(geometry.getNumFSRs()) + + # Initialize fission rates dictionary + fission_rates_sum = {} + + # Loop over FSRs and populate fission rates dictionary + for fsr in range(geometry.getNumFSRs()): + + if geometry.findFSRMaterial(fsr).isFissionable(): + + # Get the linked list of LocalCoords + point = geometry.getFSRPoint(fsr) + coords = openmoc.LocalCoords(point.getX(), point.getY(), point.getZ()) + coords.setUniverse(geometry.getRootUniverse()) + geometry.findCellContainingCoords(coords) + coords = coords.getHighestLevel().getNext() + + # initialize dictionary key + key = 'UNIV = 0 : ' + + # Parse through the linked list and create fsr key. + # If lowest level sub dictionary already exists, then increment + # fission rate; otherwise, set the fission rate. + while True: + if coords.getType() is openmoc.LAT: + key += 'LAT = ' + str(coords.getLattice().getId()) + ' (' + \ + str(coords.getLatticeX()) + ', ' + \ + str(coords.getLatticeY()) + ', ' + \ + str(coords.getLatticeZ()) + ') : ' + else: + key += 'UNIV = ' + str(coords.getUniverse().getId()) + ' : ' + + # Remove trailing ' : ' on end of key if at last univ/lat + if coords.getNext() is None: + key = key[:-3] + break + else: + coords = coords.getNext() + + # Increment or set fission rate + if key in fission_rates_sum: + fission_rates_sum[key] += fsr_fission_rates[fsr] + else: + fission_rates_sum[key] = fsr_fission_rates[fsr] # Write the fission rates to the HDF5 file - fission_rates_group = f.create_group('fission-rates') - for key, value in fission_rates_sum.items(): - fission_rates_group.attrs[key] = value + if use_hdf5: + f = h5py.File(directory + filename + '.h5', 'w') + fission_rates_group = f.create_group('fission-rates') + for key, value in fission_rates_sum.items(): + fission_rates_group.attrs[key] = value + f.close() - # Close hdf5 file - f.close() - - else: + # Pickle the fission rates to a file + else: + pickle.dump(fission_rates_sum, open(directory + filename + '.pkl', 'wb')) - import pickle - # Pickle the fission rates to a file - pickle.dump(fission_rates_sum, open(directory + filename + '.pkl', 'wb')) - -## -# @brief This method stores all of the data for an OpenMOC simulation to a -# a binary file for downstream data processing. -# @details The method may be used to store the type of Solver used, floating -# point precision, exponential evaluation method, number of FSRs, -# number of materials, number of energy groups, number of azimuthal -# angles, number of polar angles, track spacing, number of Tracks, -# number of Track segments, number of source iterations, source -# convergence tolerance, converged \f$ k_{eff} \f$, total runtime, -# and number of OpenMP or CUDA threads. In addition, the routine -# can store the FSR flux array, FSR source array, and pin and -# assembly fission rates. -# -# The routine may export the simulation data to either an HDF5 or -# a Python pickle binary file. Users may tell the routine to either -# create a new binary output file, or append to an existing file -# using a timestamp to record multiple simulation states to the -# same file. -# -# This method may be called from Python as follows: -# -# @code -# store_simulation_state(solver, fluxes=True, source=True, \ -# fission_rates=True, use_hdf5=True) -# @endcode -# -# @param solver a pointer to a Solver object -# @param fluxes whether to store FSR scalar fluxes (false by default) -# @param sources whether to store FSR sources (false by default) -# @param fission_rates whether to store fission rates (false by default) -# @param use_hdf5 whether to export to HDF5 (default) or Python pickle file -# @param filename the filename to use (default is 'simulation-state.h5') -# @param directory the directory to use (default is 'simulation-states') -# @param append append to existing file or create new one (false by default) -# @param note an additional string note to include in state file def store_simulation_state(solver, fluxes=False, sources=False, fission_rates=False, use_hdf5=False, - filename='simulation-state', + filename='simulation-state', directory = 'simulation-states', append=True, note=''): + """Store all of the data for an OpenMOC simulation to a binary file for + downstream data processing. + + This routine may be used to store the following: + + * type of Solver used + * floating point precision + * exponential evaluation method + * number of FSRs + * number of materials + * number of energy groups + * number of azimuthal angles + * number of polar angles + * track spacing + * number of tracks + * number of track segments + * number of source iterations + * source convergence tolerance + * converged $k_{eff}$ + * total runtime [seconds] + * number of OpenMP or CUDA threads + + In addition, the routine can optionally store the FSR scalar fluxes, FSR + sources, and pin and assembly fission rates. + + The routine may export the simulation data to either an HDF5 or a Python + pickle binary file. Users may tell the routine to either create a new binary + output file, or append to an existing file using a timestamp to record + multiple simulation states to the same file. + + Parameters + ---------- + solver : openmoc.Solver + The solver used to compute the flux + fluxes : bool + Whether to store FSR scalar fluxes (False by default) + sources : bool + Whether to store FSR sources (False by default) + fission_rates : bool + Whether to store fission rates (False by default) + use_hdf5 : bool + Whether to export to HDF5 (True by default) or Python pickle file + filename : str + The filename to use (default is 'simulation-state.h5') + directory : str + The directory to use (default is 'simulation-states') + append : bool + Append to existing file or create new one (False by default) + note : str, optional + An optional string note to include in state file + + Examples + -------- + This routine may be called from Python as follows: + + >>> store_simulation_state(solver, fluxes=True, source=True, \ + fission_rates=True, use_hdf5=True) + + See Also + -------- + restore_simulation_state(...) + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_type('fluxes', fluxes, bool) + cv.check_type('sources', sources, bool) + cv.check_type('fission_rates', fission_rates, bool) + cv.check_type('use_hdf5', use_hdf5, bool) + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + cv.check_type('append', append, bool) + cv.check_type('note', note, basestring) + + # Make directory if it does not exist + if not os.path.exists(directory): + os.makedirs(directory) + + # Get the day and time to construct the appropriate groups in the file + time = datetime.datetime.now() + year = time.year + month = time.month + day = time.day + hr = time.hour + mins = time.minute + sec = time.second + + # Determine the Solver type + solver_type = '' + + if 'CPUSolver' in str(solver.__class__): + solver_type = 'CPUSolver' + elif 'VectorizedSolver' in str(solver.__class__): + solver_type = 'VectorizedSolver' + elif 'GPUSolver' in str(solver.__class__): + solver_type = 'GPUSolver' + + # Determine the floating point precision level + if solver.isUsingDoublePrecision(): + precision = 'double' + else: + precision = 'single' + + # Determine whether we are using the exponential + # linear interpolation for exponential evaluations + if solver.isUsingExponentialInterpolation(): + method = 'linear interpolation' + else: + method = 'exp intrinsic' - import datetime - - # Make directory if it does not exist - if not os.path.exists(directory): - os.makedirs(directory) - - # Get the day and time to construct the appropriate groups in the file - time = datetime.datetime.now() - year = time.year - month = time.month - day = time.day - hr = time.hour - mins = time.minute - sec = time.second - - # Determine the Solver type - solver_type = '' - - if 'CPUSolver' in str(solver.__class__): - solver_type = 'CPUSolver' - elif 'ThreadPrivateSolver' in str(solver.__class__): - solver_type = 'ThreadPrivateSolver' - elif 'VectorizedSolver' in str(solver.__class__): - solver_type = 'VectorizedSolver' - elif 'VectorizedPrivateSolver' in str(solver.__class__): - solver_type = 'VectorizedPrivateSolver' - elif 'GPUSolver' in str(solver.__class__): - solver_type = 'GPUSolver' - - # Determine the floating point precision level - if solver.isUsingDoublePrecision(): - precision = 'double' - else: - precision = 'single' - - # Determine whether we are using the exponential intrinsic or - # linear interpolation for exponential evaluations - if solver.isUsingExponentialIntrinsic(): - method = 'exp intrinsic' - else: - method = 'linear interpolation' - - # Determine whether the Solver has initialized Coarse Mesh Finite - # Difference Acceleration (CMFD) - if solver.getGeometry().getCmfd() is not None: - cmfd = True - else: - cmfd = False - - # Get the Geometry and TrackGenerator from the solver - geometry = solver.getGeometry() - track_generator = solver.getTrackGenerator() - - # Retrieve useful data from the Solver, Geometry and TrackGenerator - num_FSRs = geometry.getNumFSRs() - num_materials = geometry.getNumMaterials() - num_groups = geometry.getNumEnergyGroups() - num_tracks = track_generator.getNumTracks() - num_segments = track_generator.getNumSegments() - spacing = track_generator.getTrackSpacing() - num_azim = track_generator.getNumAzim() - num_polar = solver.getNumPolarAngles() - num_iters = solver.getNumIterations() - thresh = solver.getSourceConvergenceThreshold() - tot_time = solver.getTotalTime() - keff = solver.getKeff() - - if solver_type is 'GPUSolver': - num_threads = solver.getNumThreadsPerBlock() - num_blocks = solver.getNumThreadBlocks() - else: - num_threads = solver.getNumThreads() - - # If the user requested to store the FSR fluxes - if fluxes: - - # Allocate array - scalar_fluxes = np.zeros((num_FSRs, num_groups)) - - # Get the scalar flux for each FSR and energy group - for i in range(num_FSRs): - for j in range(num_groups): - scalar_fluxes[i,j] = solver.getFSRScalarFlux(i,j+1) - - # If the user requested to store the FSR sources - if sources: - - # Allocate array - sources_array = np.zeros((num_FSRs, num_groups)) - - # Get the scalar flux for each FSR and energy group - for i in range(num_FSRs): - for j in range(num_groups): - sources_array[i,j] = solver.getFSRSource(i,j+1) - - # If using HDF5 - if use_hdf5: - - import h5py - - # Create a file handle - if append: - f = h5py.File(directory + '/' + filename + '.h5', 'a') + # Determine whether the Solver has initialized Coarse Mesh Finite + # Difference Acceleration (CMFD) + if solver.getGeometry().getCmfd() is not None: + cmfd = True else: - f = h5py.File(directory + '/' + filename + '.h5', 'w') - - # Create groups for the day in the HDF5 file - day_key = '{0:02}-{1:02}-{2:02}'.format(month, day, year) - day_group = f.require_group(day_key) - - # Create group for the time - use counter in case two simulations - # write simulation state at the exact same hour,minute, and second - time_key = '{0:02}:{1:02}:{2:02}'.format(hr, mins, sec) - counter = 0 - while time_key in day_group.keys(): - time_key = '{0:02}:{1:02}:{2:02}-{3}'.format(hr, mins, sec, counter) - counter += 1 - - time_group = day_group.require_group(time_key) - - # Store a note for this simulation state - if not note is '': - time_group.attrs['note'] = note - - # Store simulation data to the HDF5 file - time_group.create_dataset('solver type', data=solver_type) - time_group.create_dataset('# FSRs', data=num_FSRs) - time_group.create_dataset('# materials', data=num_materials) - time_group.create_dataset('# energy groups', data=num_groups) - time_group.create_dataset('# tracks', data=num_tracks) - time_group.create_dataset('# segments', data=num_segments) - time_group.create_dataset('track spacing [cm]', data=spacing) - time_group.create_dataset('# azimuthal angles', data=num_azim) - time_group.create_dataset('# polar angles', data=num_polar) - time_group.create_dataset('# iterations', data=num_iters) - time_group.create_dataset('source residual threshold', data=thresh) - time_group.create_dataset('exponential', data=method) - time_group.create_dataset('floating point', data=precision) - time_group.create_dataset('CMFD', data=cmfd) - time_group.create_dataset('time [sec]', data=tot_time) - time_group.create_dataset('keff', data=keff) + cmfd = False + + # Get the Geometry and TrackGenerator from the solver + geometry = solver.getGeometry() + track_generator = solver.getTrackGenerator() + + # Retrieve useful data from the Solver, Geometry and TrackGenerator + num_FSRs = geometry.getNumFSRs() + num_materials = geometry.getNumMaterials() + num_groups = geometry.getNumEnergyGroups() + zcoord = track_generator.getZCoord() + num_tracks = track_generator.getNumTracks() + num_segments = track_generator.getNumSegments() + spacing = track_generator.getTrackSpacing() + num_azim = track_generator.getNumAzim() + num_polar = solver.getNumPolarAngles() + num_iters = solver.getNumIterations() + thresh = solver.getConvergenceThreshold() + tot_time = solver.getTotalTime() + keff = solver.getKeff() if solver_type is 'GPUSolver': - time_group.create_dataset('# threads per block', data=num_threads) - time_group.create_dataset('# thread blocks', data=num_blocks) + num_threads = solver.getNumThreadsPerBlock() + num_blocks = solver.getNumThreadBlocks() else: - time_group.create_dataset('# threads', data=num_threads) + num_threads = solver.getNumThreads() + # If the user requested to store the FSR fluxes if fluxes: - time_group.create_dataset('FSR scalar fluxes', data=scalar_fluxes) - - if sources: - time_group.create_dataset('FSR sources', data=sources_array) - - if fission_rates: - compute_fission_rates(solver, use_hdf5=True) + # Allocate array + scalar_fluxes = np.zeros((num_FSRs, num_groups)) - # Open the fission rates file generated by compute_fission_rates(...) - fission_rates_file = h5py.File('fission-rates/fission-rates.h5', 'r') + # Get the scalar flux for each FSR and energy group + for i in range(num_FSRs): + for j in range(num_groups): + scalar_fluxes[i,j] = solver.getFlux(i,j+1) - # Deep copy the group of fission rates from fission_rates_file - f.copy(fission_rates_file, time_group, name='fission-rates') - - # Close the pin powers file - fission_rates_file.close() - - # Close the HDF5 file - f.close() - - # If not using HDF5, we are pickling all of the data - else: - - import pickle + # If the user requested to store the FSR sources + if sources: - # Load the dictionary from the Pickle file - filename = directory + '/' + filename + '.pkl' - if os.path.exists(filename) and append: - sim_states = pickle.load(file(filename, 'rb')) - else: - sim_states = {} - - # Create strings for the day and time - day = str(month).zfill(2)+'-'+str(day).zfill(2)+'-'+str(year) - time = str(hr).zfill(2)+':'+str(mins).zfill(2)+':'+str(sec).zfill(2) - - # Create dictionaries for this day and time within the pickled file - if not day in sim_states.keys(): - sim_states[day] = {} - - sim_states[day][time] = {} - state = sim_states[day][time] - - # Store a note for this simulation state - if not note is '': - state['note'] = note - - # Store simulation data to a Python dictionary - state['solver type'] = solver_type - state['# FSRs'] = num_FSRs - state['# materials'] = num_materials - state['# energy groups'] = num_groups - state['# tracks'] = num_tracks - state['# segments'] = num_segments - state['track spacing [cm]'] = spacing - state['# azimuthal angles'] = num_azim - state['# polar angles'] = num_polar - state['# iterations'] = num_iters - state['source residual threshold'] = thresh - state['exponential'] = method - state['floating point'] = precision - state['CMFD'] = cmfd - state['time [sec]'] = tot_time - state['keff'] = keff + # Allocate array + sources_array = np.zeros((num_FSRs, num_groups)) - if solver_type is 'GPUSolver': - state['# threads per block'] = num_threads - state['# thread blocks'] = num_blocks - else: - state['# threads'] = num_threads + # Get the scalar flux for each FSR and energy group + for i in range(num_FSRs): + for j in range(num_groups): + sources_array[i,j] = solver.getFSRSource(i,j+1) - if fluxes: - state['FSR scalar fluxes'] = scalar_fluxes + # If using HDF5 + if use_hdf5: + if append: + f = h5py.File(directory + '/' + filename + '.h5', 'a') + else: + f = h5py.File(directory + '/' + filename + '.h5', 'w') + + # Create groups for the day in the HDF5 file + day_key = '{0:02}-{1:02}-{2:02}'.format(month, day, year) + day_group = f.require_group(day_key) + + # Create group for the time - use counter in case two simulations + # write simulation state at the exact same hour,minute, and second + time_key = '{0:02}:{1:02}:{2:02}'.format(hr, mins, sec) + counter = 0 + while time_key in day_group.keys(): + time_key = '{0:02}:{1:02}:{2:02}-{3}'.format(hr, mins, sec, counter) + counter += 1 + + time_group = day_group.require_group(time_key) + + # Store a note for this simulation state + if not note is '': + time_group.attrs['note'] = note + + # Store simulation data to the HDF5 file + time_group.create_dataset('solver type', data=solver_type) + time_group.create_dataset('# FSRs', data=num_FSRs) + time_group.create_dataset('# materials', data=num_materials) + time_group.create_dataset('# energy groups', data=num_groups) + time_group.create_dataset('z coord', data=zcoord) + time_group.create_dataset('# tracks', data=num_tracks) + time_group.create_dataset('# segments', data=num_segments) + time_group.create_dataset('track spacing [cm]', data=spacing) + time_group.create_dataset('# azimuthal angles', data=num_azim) + time_group.create_dataset('# polar angles', data=num_polar) + time_group.create_dataset('# iterations', data=num_iters) + time_group.create_dataset('convergence threshold', data=thresh) + time_group.create_dataset('exponential', data=method) + time_group.create_dataset('floating point', data=precision) + time_group.create_dataset('CMFD', data=cmfd) + time_group.create_dataset('time [sec]', data=tot_time) + time_group.create_dataset('keff', data=keff) - if sources: - state['FSR sources'] = sources_array - - if fission_rates: - compute_fission_rates(solver, False) - state['fission-rates'] = pickle.load(file('fission-rates/fission-rates.pkl', 'rb')) - - # Pickle the simulation states to a file - pickle.dump(sim_states, open(filename, 'wb')) - - # Pickle the simulation states to a file - pickle.dump(sim_states, open(filename, 'wb')) - - -## -# @brief -# @details - -## -# @brief -# @details - -## -# @brief This method restores all of the data for an OpenMOC simulation from a -# a binary file for downstream data processing to a Python dictionary. -# @details The routine may import the simulation state from either an HDF5 or a -# Python pickle binary file created by the store_simulation_state(...) -# method. The method may be used to restore the type of Solver used, -# floating point precision, exponential evaluation method, number of -# FSRs, number of materials, number of energy groups, number of -# azimuthal angles, number of polar angles, track spacing, number of -# Tracks, number of Track segments, number of source iterations, source -# convergence tolerance, converged \f$ k_{eff} \f$, total runtime, -# and number of OpenMP or CUDA threads. In addition, the routine -# can restore the FSR flux array, FSR source array. -# -# Note: If the fission rates were stored in a hdf5 binary file, -# they are not restored and returned in this method. -# -# This method may be called from Python as follows: -# -# @code -# restore_simulation_state(filename='simulation-state-v1.3.h5') -# @endcode -# -# @param filename the simulation state filename string -# @param directory the directory where to find the simulation state file -# @return a Python dictionary of key/value pairs for simulation state data -def restore_simulation_state(filename='simulation-state.h5', - directory='simulation-states'): + if solver_type is 'GPUSolver': + time_group.create_dataset('# threads per block', data=num_threads) + time_group.create_dataset('# thread blocks', data=num_blocks) + else: + time_group.create_dataset('# threads', data=num_threads) - # If using HDF5 - if '.h5' in filename or '.hdf5' in filename: + if fluxes: + time_group.create_dataset('FSR scalar fluxes', data=scalar_fluxes) - import h5py + if sources: + time_group.create_dataset('FSR sources', data=sources_array) - # Create a file handle - f = h5py.File(directory + '/' + filename, 'r') + if fission_rates: + compute_fission_rates(solver, use_hdf5=True) + fission_rates_file = h5py.File('fission-rates/fission-rates.h5', 'r') + f.copy(fission_rates_file, time_group, name='fission-rates') + fission_rates_file.close() - states = {} + # Close the HDF5 file + f.close() - # Loop over all simulation state timestamps by day - for day in f.keys(): + # If not using HDF5, we are pickling all of the data + else: + filename = directory + '/' + filename + '.pkl' + if os.path.exists(filename) and append: + sim_states = pickle.load(open(filename, 'rb')) + else: + sim_states = {} - # Create sub-dictionary for this day - states[day] = {} + # Create strings for the day and time + day = str(month).zfill(2)+'-'+str(day).zfill(2)+'-'+str(year) + time = str(hr).zfill(2)+':'+str(mins).zfill(2)+':'+str(sec).zfill(2) - # Loop over all simulation state timestamps by time of day - for time in f[day]: + # Create dictionaries for this day and time within the pickled file + if not day in sim_states.keys(): + sim_states[day] = {} - # Create sub-dictionary for this simulation state - dataset = f[day][time] - states[day][time] = {} - state = states[day][time] + sim_states[day][time] = {} + state = sim_states[day][time] - # Extract simulation data and store it in the sub-dictionary + # Store a note for this simulation state + if not note is '': + state['note'] = note - solver_type = str(dataset['solver type']) + # Store simulation data to a Python dictionary state['solver type'] = solver_type - - num_FSRs = int(dataset['# FSRs'][...]) state['# FSRs'] = num_FSRs - - num_materials = int(dataset['# materials'][...]) state['# materials'] = num_materials - - num_tracks = int(dataset['# tracks'][...]) - state['# tracks'] = num_materials - - num_segments = int(dataset['# segments'][...]) + state['# energy groups'] = num_groups + state['z coord'] = zcoord + state['# tracks'] = num_tracks state['# segments'] = num_segments - - spacing = int(dataset['track spacing [cm]'][...]) state['track spacing [cm]'] = spacing - - num_azim = int(dataset['# azimuthal angles'][...]) state['# azimuthal angles'] = num_azim - - num_polar = int(dataset['# polar angles'][...]) state['# polar angles'] = num_polar - - num_iters = int(dataset['# iterations'][...]) state['# iterations'] = num_iters - - thresh = float(dataset['source residual threshold'][...]) - state['source residual threshold'] = thresh - - method = str(dataset['exponential'][...]) + state['convergence threshold'] = thresh state['exponential'] = method - - precision = str(dataset['floating point'][...]) state['floating point'] = precision - - cmfd = str(dataset['CMFD'][...]) state['CMFD'] = cmfd - - time = float(dataset['time [sec]'][...]) - state['time [sec]'] = time - - keff = float(dataset['keff'][...]) + state['time [sec]'] = tot_time state['keff'] = keff if solver_type is 'GPUSolver': - num_threads = int(dataset['# threads per block']) - num_blocks = int(dataset['# thread blocks']) + state['# threads per block'] = num_threads + state['# thread blocks'] = num_blocks else: - num_threads = int(dataset['# threads'][...]) + state['# threads'] = num_threads - if 'FSR scalar fluxes' in dataset: - fluxes = dataset['FSR scalar fluxes'][...] - state['FSR scalar fluxes'] = fluxes + if fluxes: + state['FSR scalar fluxes'] = scalar_fluxes - if 'FSR sources' in dataset: - sources_array = dataset['FSR sources'][...] - state['FSR sources'] = sources_array + if sources: + state['FSR sources'] = sources_array - if 'note' in dataset: - state['note'] = str(dataset['note']) + if fission_rates: + compute_fission_rates(solver, False) + state['fission-rates'] = \ + pickle.load(open('fission-rates/fission-rates.pkl', 'rb')) - if 'fission-rates' in dataset: - py_printf('WARNING', 'The process.restore_simulation_state(...)'+\ - 'method does not yet support fission rates') + # Pickle the simulation states to a file + pickle.dump(sim_states, open(filename, 'wb')) - return states + # Pickle the simulation states to a file + pickle.dump(sim_states, open(filename, 'wb')) - # If using a Python pickled file - elif '.pkl' in filename: - - import pickle +def restore_simulation_state(filename='simulation-state.h5', + directory='simulation-states'): + """Restore all of the data for an OpenMOC simulation from a binary file for + downstream data processing to a Python dictionary. + + This routine may import the simulation state from either an HDF5 or a Python + pickle binary file created by the store_simulation_state(...) method. The + method may be used to restore the following information: + + * type of Solver used + * floating point precision + * exponential evaluation method + * number of FSRs + * number of materials + * number of energy groups + * number of azimuthal angles + * number of polar angles + * track spacing + * number of tracks + * number of track segments + * number of source iterations + * source convergence tolerance + * converged $k_{eff}$ + * total runtime [seconds] + * number of OpenMP or CUDA threads + + Note: If the fission rates were stored in a hdf5 binary file, + they are not restored and returned in this method. + + Paramters + --------- + filename : str + The simulation state filename string + directory : str + The directory where to find the simulation state file + + Returns + ------- + states : dict + The dictionary of key/value pairs for simulation state data + + Examples + -------- + This method may be called from Python as follows: + + >>> restore_simulation_state(filename='simulation-state-v1.3.h5') + + See Also + -------- + store_simulation_state(...) + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) - # Load the dictionary from the pickle file filename = directory + '/' + filename - states = pickle.load(file(filename, 'rb')) - - return states - - # If file does not have a recognizable extension - else: - py_printf('WARNING', 'Unable to restore the simulation states file %s' + \ - ' since it does not have a supported file extension. Only ' + \ - '*.h5, *.hdf5, and *.pkl files are supported', filename) - - return {} + if not os.path.isfile(filename): + py_printf('ERROR', 'Unable restore simulation state since "{0}" ' + \ + 'is not an existing simulation state file'.format(filename)) + + # If using HDF5 + if '.h5' in filename or '.hdf5' in filename: + + import h5py + + # Create a file handle + f = h5py.File(filename, 'r') + + states = {} + + # Loop over all simulation state timestamps by day + for day in f.keys(): + + # Create sub-dictionary for this day + states[day] = {} + + # Loop over all simulation state timestamps by time of day + for time in f[day]: + + # Create sub-dictionary for this simulation state + dataset = f[day][time] + states[day][time] = {} + state = states[day][time] + + # Extract simulation state data + solver_type = str(dataset['solver type']) + num_FSRs = int(dataset['# FSRs'][...]) + num_materials = int(dataset['# materials'][...]) + num_tracks = int(dataset['# tracks'][...]) + num_segments = int(dataset['# segments'][...]) + spacing = int(dataset['track spacing [cm]'][...]) + num_azim = int(dataset['# azimuthal angles'][...]) + num_polar = int(dataset['# polar angles'][...]) + num_iters = int(dataset['# iterations'][...]) + thresh = float(dataset['convergence threshold'][...]) + method = str(dataset['exponential'][...]) + precision = str(dataset['floating point'][...]) + cmfd = str(dataset['CMFD'][...]) + time = float(dataset['time [sec]'][...]) + keff = float(dataset['keff'][...]) + + # Store simulation state data in sub-dictionary + state['solver type'] = solver_type + state['# FSRs'] = num_FSRs + state['# materials'] = num_materials + state['# tracks'] = num_tracks + state['# segments'] = num_segments + state['track spacing [cm]'] = spacing + state['# azimuthal angles'] = num_azim + state['# polar angles'] = num_polar + state['# iterations'] = num_iters + state['convergence threshold'] = thresh + state['exponential'] = method + state['floating point'] = precision + state['CMFD'] = cmfd + state['time [sec]'] = time + state['keff'] = keff + + if solver_type is 'GPUSolver': + state['# threads per block'] = \ + int(dataset['# threads per block']) + state['# thread blocks'] = int(dataset['# thread blocks']) + else: + state['# threads'] = int(dataset['# threads'][...]) + if 'FSR scalar fluxes' in dataset: + state['FSR scalar fluxes'] = \ + dataset['FSR scalar fluxes'][...] + if 'FSR sources' in dataset: + state['FSR sources'] = dataset['FSR sources'][...] + if 'note' in dataset: + state['note'] = str(dataset['note']) + if 'fission-rates' in dataset: + py_printf('WARNING', 'The restore_simulation_state(...)' + + 'method does not yet support fission rates') + + return states + + # If using a Python pickled file + elif '.pkl' in filename: + states = pickle.load(open(filename, 'rb')) + return states + + # If file does not have a recognizable extension + else: + py_printf('WARNING', 'Unable to restore the simulation states file %s' + + ' since it does not have a supported file extension. Only ' + + '*.h5, *.hdf5, and *.pkl files are supported', filename) + return {} + + +def parse_convergence_data(filename, directory=''): + """Parse an OpenMOC log file to obtain a simulation's convergence data. + + This method compiles the eigenvalue and source residuals from each iteration + of an OpenMOC simulation. This data is inserted into a Python dictionary + under the key names 'eigenvalues' and 'residuals', along with an integer + '# iters', and returned to the user. + + Parameters + ---------- + filename : str + The OpenMOC log filename string + directory : str + The directory where to find the log file + + Returns + ------- + convergence_data : dict + A Python dictionary of key/value pairs for convergence data + + Examples + -------- + This method may be called from Python as follows: + + >>> parse_convergence_data(filename='openmoc-XX-XX-XXXX--XX:XX:XX.log') + + """ + + cv.check_type('filename', filename, basestring) + cv.check_type('directory', directory, basestring) + + # If the user specified a directory + if len(directory) > 0: + filename = directory + '/' + filename + + if not os.path.isfile(filename): + py_printf('ERROR', 'Unable to parse convergence data since "{0}" is ' + + 'not an existing OpenMOC log file'.format(filename)) + + # Compile regular expressions to find the residual and eigenvalue data + res = re.compile(b'res = ([0-9].[0-9]+E[+|-][0-9]+)') + keff = re.compile(b'k_eff = ([0-9]+.[0-9]+)') + + # Parse the eigenvalues + with open(filename, 'r+') as f: + data = mmap.mmap(f.fileno(), 0) + eigenvalues = keff.findall(data) + + # Parse the source residuals + with open(filename, 'r+') as f: + data = mmap.mmap(f.fileno(), 0) + residuals = res.findall(data) + + # Create NumPy arrays of the data + eigenvalues = np.array([float(eigenvalue) for eigenvalue in eigenvalues]) + residuals = np.array([float(residual) for residual in residuals]) + + # Find the total number of source iterations + num_iters = len(residuals) + + # Store the data in a dictionary to return to the user + convergence_data = dict() + convergence_data['# iters'] = num_iters + convergence_data['eigenvalues'] = eigenvalues + convergence_data['residuals'] = residuals + return convergence_data + + +class Mesh(object): + """A structured Cartesian mesh in two or three dimensions + + Attributes + ---------- + dimension : Iterable of int + The number of mesh cells in each direction. + lower_left : Iterable of float + The lower-left corner of the structured mesh. If only two coordinate are + given, it is assumed that the mesh is an x-y mesh. + upper_right : Iterable of float + The upper-right corner of the structrued mesh. If only two coordinate + are given, it is assumed that the mesh is an x-y mesh. + width : Iterable of float + The width of mesh cells in each direction. + num_mesh_cells : Integral + The total number of mesh cells in all dimensions + mesh_cell_volume : Real + The volume or area of a mesh cell in 2D or 3D in units of cm^3 or cm^2 + + """ + + def __init__(self): + self._dimension = None + self._lower_left = None + self._upper_right = None + self._width = None + + @property + def dimension(self): + return self._dimension + + @property + def lower_left(self): + return self._lower_left + + @property + def upper_right(self): + return self._upper_right + + @property + def width(self): + return self._width + + @property + def num_mesh_cells(self): + return np.prod(self._dimension) + + @property + def mesh_cell_volume(self): + return reduce(operator.mul, self.dimension, 1) + + @dimension.setter + def dimension(self, dimension): + cv.check_type('mesh dimension', dimension, Iterable, Integral) + cv.check_length('mesh dimension', dimension, 2, 3) + self._dimension = dimension + + @lower_left.setter + def lower_left(self, lower_left): + cv.check_type('mesh lower_left', lower_left, Iterable, Real) + cv.check_length('mesh lower_left', lower_left, 2, 3) + self._lower_left = lower_left + + @upper_right.setter + def upper_right(self, upper_right): + cv.check_type('mesh upper_right', upper_right, Iterable, Real) + cv.check_length('mesh upper_right', upper_right, 2, 3) + self._upper_right = upper_right + + @width.setter + def width(self, width): + cv.check_type('mesh width', width, Iterable, Real) + cv.check_length('mesh width', width, 2, 3) + self._width = width + + def get_mesh_cell_indices(self, point): + """Get the mesh cell indices for a point within the geometry. + + Parameters + ---------- + point : openmoc.Point + A point within the geometry + + Returns + ------- + indices : 2- or 3-tuple of Integral + The mesh cell indices for the point. If the mesh is 2D then indices + for x and y are returned; if the mesh is 3d indices for x, y, and z + are returned. + + """ + + cv.check_type('point', point, openmoc.Point) + + # Extract the x,y,z coordinates from the OpenMOC Point + x, y, z = point.getX(), point.getY(), point.getZ() + + # Translate the point with respect to the center of the mesh + x -= (self.upper_right[0] + self.lower_left[0]) / 2. + y -= (self.upper_right[1] + self.lower_left[1]) / 2. + if len(self.dimension) != 2: + z -= (self.upper_right[2] + self.lower_left[2]) / 2. + + # Compute the mesh cell indices + mesh_x = (x + self.dimension[0] * self.width[0] * 0.5) / self.width[0] + mesh_y = (y + self.dimension[1] * self.width[1] * 0.5) / self.width[1] + if len(self.dimension) == 2: + mesh_z = 0 + else: + mesh_z = (z + self.dimension[2] * self.width[2] * 0.5) / self.width[2] + + # Round the mesh cell indices down + mesh_x = int(math.floor(mesh_x)) + mesh_y = int(math.floor(mesh_y)) + mesh_z = int(math.floor(mesh_z)) + + # Throw error if indices are outside of the Mesh + if len(self.dimension) == 2: + if (mesh_x < 0 or mesh_x >= self.dimension[0]) or \ + (mesh_y < 0 or mesh_y >= self.dimension[1]): + py_printf('ERROR', 'Unable to find cell since indices (%d, ' + + '%d, %d) are outside mesh', mesh_x, mesh_y, mesh_z) + else: + if (mesh_x < 0 or mesh_x >= self.dimension[0]) or \ + (mesh_y < 0 or mesh_y >= self.dimension[1]) or \ + (mesh_z < 0 or mesh_z >= self.dimension[2]): + py_printf('ERROR', 'Unable to find cell since indices (%d, ' + + '%d, %d) are outside mesh', mesh_x, mesh_y, mesh_z) + + # Return mesh cell indices + if len(self.dimension) == 2: + return mesh_x, mesh_y + else: + return mesh_x, mesh_y, mesh_z + + def tally_fission_rates(self, solver, volume='integrated'): + """Compute the fission rates in each mesh cell. + + NOTE: This method assumes that the mesh perfectly aligns with the + flat source region mesh used in the OpenMOC calculation. + + NOTE: The user must supply 'fission' as well as 'nu-fission' multi-group + cross sections to each material in the geometry. Although 'nu-fission' + is all that is required for an MOC calculation, 'fission' is what is + used to compute the fission rates. + + Parameters + ---------- + solver : {openmoc.CPUSolver, openmoc.GPUSolver, openmoc.VectorizedSolver} + The solver used to compute the flux + volume : {'averaged' ,'integrated'} + Compute volume-averaged or volume-integrated fission rates + + Returns + ------- + tally : numpy.ndarray of Real + A NumPy array of the fission rates tallied in each mesh cell + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_value('volume', volume, ('averaged', 'integrated')) + + geometry = solver.getGeometry() + num_fsrs = geometry.getNumFSRs() + + # Compute the volume- and energy-integrated fission rates for each FSR + fission_rates = solver.computeFSRFissionRates(geometry.getNumFSRs()) + + # Initialize a 2D or 3D NumPy array in which to tally + tally = np.zeros(tuple(self.dimension), dtype=np.float) + + # Tally the fission rates in each FSR to the corresponding mesh cell + for fsr in range(num_fsrs): + point = geometry.getFSRPoint(fsr) + mesh_indices = self.get_mesh_cell_indices(point) + tally[mesh_indices] += fission_rates[fsr] + + # Average the fission rates by mesh cell volume if needed + if volume == 'averaged': + tally /= self.mesh_cell_volume + + return tally + + def tally_on_mesh(self, solver, domains_to_coeffs, domain_type='fsr', + volume='integrated', energy='integrated'): + """Compute arbitrary reaction rates in each mesh cell. + + NOTE: This method assumes that the mesh perfectly aligns with the + flat source region mesh used in the OpenMOC calculation. + + Parameters + ---------- + solver : {openmoc.CPUSolver, openmoc.GPUSolver, openmoc.VectorizedSolver} + The solver used to compute the flux + domains_to_coeffs : dict or numpy.ndarray of Real + A mapping of spatial domains and energy groups to the coefficients + to multiply the flux in each domain. If domain_type is 'material' + or 'cell' then the coefficients must be a Python dictionary indexed + by material/cell ID mapped to NumPy arrays indexed by energy group. + If domain_type is 'fsr' then the coefficients may be a dictionary + or NumPy array indexed by FSR ID and energy group. Note that the + energy group indexing should start at 0 rather than 1 for the + highest energy in accordance with Python's 0-based indexing. + domain_type : {'fsr', 'cell', 'material'} + The type of domain for which the coefficients are defined + volume : {'averaged', 'integrated'} + Compute volume-averaged or volume-integrated tallies + energy : {'by_group', 'integrated'} + Compute tallies by energy group or integrate across groups + + Returns + ------- + tally : numpy.ndarray of Real + A NumPy array of the fission rates tallied in each mesh cell indexed + by FSR ID and energy group (if energy is 'by_group') + + """ + + cv.check_type('solver', solver, openmoc.Solver) + cv.check_value('domain_type', domain_type, ('fsr', 'cell', 'material')) + cv.check_value('volume', volume, ('averaged', 'integrated')) + cv.check_value('energy', energy, ('by_group', 'integrated')) + + # Extract parameters from the Geometry + geometry = solver.getGeometry() + num_groups = geometry.getNumEnergyGroups() + num_fsrs = geometry.getNumFSRs() + + # Coefficients must be specified as a dict, ndarray or DataFrame + if domain_type in ['material', 'cell']: + cv.check_type('domains_to_coeffs', domains_to_coeffs, dict) + else: + cv.check_type('domains_to_coeffs', + domains_to_coeffs, (dict, np.ndarray)) + + # Extract the FSR fluxes from the Solver + fluxes = get_scalar_fluxes(solver) + + # Initialize a 2D or 3D NumPy array in which to tally + tally_shape = tuple(self.dimension) + (num_groups,) + tally = np.zeros(tally_shape, dtype=np.float) + + # Compute product of fluxes with domains-to-coeffs mapping by group, FSR + for fsr in range(num_fsrs): + point = geometry.getFSRPoint(fsr) + mesh_indices = self.get_mesh_cell_indices(point) + volume = solver.getFSRVolume(fsr) + fsr_tally = np.zeros(num_groups, dtype=np.float) + + # Determine domain ID (material, cell or FSR) for this FSR + if domain_type == 'fsr': + domain_id = fsr + else: + coords = \ + openmoc.LocalCoords(point.getX(), point.getY(), point.getZ()) + coords.setUniverse(geometry.getRootUniverse()) + cell = geometry.findCellContainingCoords(coords) + if domain_type == 'cell': + domain_id = cell.getId() + else: + domain_id = cell.getFillMaterial().getId() + + # Tally flux multiplied by coefficients by energy group + for group in range(num_groups): + fsr_tally[group] = \ + fluxes[fsr, group] * domains_to_coeffs[domain_id][group] + + # Increment mesh tally with volume-integrated FSR tally + tally[mesh_indices] += fsr_tally * volume + + # Integrate the energy groups if needed + if energy == 'integrated': + tally = np.sum(tally, axis=len(self.dimension)) + + # Average the fission rates by mesh cell volume if needed + if volume == 'averaged': + tally /= self.mesh_cell_volume + + return tally diff --git a/openmoc/swig_typemaps.i b/openmoc/swig_typemaps.i new file mode 100644 index 000000000..5bef81413 --- /dev/null +++ b/openmoc/swig_typemaps.i @@ -0,0 +1,106 @@ +/** Helper typemaps to enable array-based user input to be defined with Python + * lists when the --no-numpy build system flag is used at compile time. */ + +%module swig_typemaps + +/* Typemap for the Material::set_____XS(double* xs, int num_groups) + * method - allows users to pass in a Python list of cross-sections + * for each energy group */ +%typemap(in) (double* xs, int num_groups) { + + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " + "for the cross-section array"); + return NULL; + } + + $2 = PySequence_Length($input); // num_groups + $1 = (double*) malloc($2 * sizeof(double)); // cross-section array + + /* Loop over x */ + for (int i = 0; i < $2; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If value is a number, cast it as an int and set the input array value */ + if (PyNumber_Check(o)) { + $1[i] = (double) PyFloat_AsDouble(o); + } + else { + free($1); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " + "for cross-section values\n"); + return NULL; + } + } +} + + +/* Typemap for the Material::set_____XS(float* xs, int num_groups) + * method - allows users to pass in a Python list of cross-sections + * for each energy group */ +%typemap(in) (float* xs, int num_groups) { + + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " + "for the cross-section array"); + return NULL; + } + + $2 = PySequence_Length($input); // num_groups + $1 = (float*) malloc($2 * sizeof(float)); // cross-section array + + /* Loop over x */ + for (int i = 0; i < $2; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If value is a number, cast it as an int and set input array value */ + if (PyNumber_Check(o)) { + $1[i] = (float) PyFloat_AsFloat(o); + } + else { + free($1); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " + "for cross-section values\n"); + return NULL; + } + } +} + + +/* Typemap for the Cmfd::setGroupStructure + * (int* group_indices, int length_group_indices) + * method - allows users to pass in a Python list of group indices + * for each CMFD energy group */ +%typemap(in) (int* group_indices, int length_group_indices) { + + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a Python list of values " + "for the group indices array"); + return NULL; + } + + $2 = PySequence_Length($input); // length_group_indices + $1 = (int*) malloc($2 * sizeof(int)); // group indices array + + /* Loop over x */ + for (int i = 0; i < $2; i++) { + + /* Extract the value from the list at this location */ + PyObject *o = PySequence_GetItem($input,i); + + /* If value is a number, cast it as an int and set the input array value */ + if (PyNumber_Check(o)) { + $1[i] = (int) PyInt_AS_LONG(o); + } + else { + free($1); + PyErr_SetString(PyExc_ValueError,"Expected a list of numbers " + "for group indices values\n"); + return NULL; + } + } +} diff --git a/openmoc/test-options.py b/openmoc/test-options.py deleted file mode 100644 index f8affe7d9..000000000 --- a/openmoc/test-options.py +++ /dev/null @@ -1,72 +0,0 @@ -## Works when run from commandline using python test-options.py - -## DOES NOT work from IDLE (Python crashes when importing options) -## DOES NOT work with nosetests from command line (module does not have attribute 'test-options') - -import unittest -import nose -from options import * - -class TestDefaultInit(unittest.TestCase): - - # creates a new Options() every test... can it just be done once? - - def setUp(self): - self._default_options = Options() - - def test_default_num_azim(self): - self.assertEqual(self._default_options._num_azim, 4) - - def test_default_track_spacing(self): - self.assertEqual(self._default_options._track_spacing, 0.1) - - def test_default_max_iters(self): - self.assertEqual(self._default_options._max_iters, 1000) - - def test_default_tolerance(self): - self.assertEqual(self._default_options._tolerance, .00001) - - def test_default_num_omp_threads(self): - self.assertEqual(self._default_options._num_omp_threads, 1) - - def test_default_num_thread_blocks(self): - self.assertEqual(self._default_options._num_thread_blocks, 64) - - def test_default_num_gpu_threads(self): - self.assertEqual(self._default_options._num_gpu_threads, 64) - - def test_default_cmfd_acceleration(self): - self.assertFalse(self._default_options._use_cmfd_acceleration) - - def test_default_cmfd_relax_factor(self): - self.assertEqual(self._default_options._cmfd_relax_factor, 0.6) - - def test_default_cmfd_mesh_level(self): - self.assertEqual(self._default_options._cmfd_mesh_level, -1) - - def tearDown(self): - self._default_options = None - -class TestCustomInit(unittest.TestCase): - - def setUp(self): - self._options = Options() - opts, args = getopt.getopt('REPLACE THIS WITH THE ARGS', - 'hfa:s:i:c:t:b:g:r:l:', - ['help', - 'num-azim=', - 'track-spacing=', - 'tolerance=', - 'max-iters=', - 'num-omp-threads=', - 'num-thread-blocks=', - 'num-gpu-threads=', - 'relax-factor=', - 'cmfd-acceleration', - 'mesh-level=']) - - -suite = unittest.TestLoader().loadTestsFromTestCase(TestDefaultInit) -#suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCustomInit)) - -unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/openmoc/thisown.i b/openmoc/thisown.i new file mode 100644 index 000000000..c18a4071d --- /dev/null +++ b/openmoc/thisown.i @@ -0,0 +1,298 @@ +/** Rules for Python/C++ transferrable memory ownership */ + +%module thisown + +/* A Cell owns the memory for each Surface it contains */ +%pythonappend Cell::addSurface %{ + # SWIG 3 + if 'surface'in locals(): + surface = locals()['surface'] + elif 'args' in locals() and 'surface' in locals()['args']: + surface = locals()['args']['surface'] + elif 'kwargs' in locals() and 'surface' in locals()['kwargs']: + surface = locals()['kwargs']['surface'] + + # SWIG 2 + else: + surface = locals()['args'][1] + + surface.thisown = False +%} + +/* Python must free memory for each Surface that is not in a Cell */ +%pythonappend Cell::removeSurface %{ + # SWIG 3 + if 'surface' in locals(): + surface = locals()['surface'] + elif 'args' in locals() and 'surface' in locals()['args']: + surface = locals()['args']['surface'] + elif 'kwargs' in locals() and 'surface' in locals()['kwargs']: + surface = locals()['kwargs']['surface'] + + # SWIG 2 + else: + surface = locals()['args'][0] + + surface.thisown = True +%} + +/* A Cell owns the memory for its Material/Universe fill */ +%pythonappend Cell::setFill %{ + # SWIG 3 + if 'fill' in locals(): + fill = locals()['fill'] + elif 'args' in locals() and 'fill' in locals()['args']: + fill = locals()['args']['fill'] + elif 'kwargs' in locals() and 'fill' in locals()['kwargs']: + fill = locals()['kwargs']['fill'] + + # SWIG 2 + else: + fill = locals()['args'][0] + + fill.thisown = False +%} + +/* A Universe owns the memory for each Cell it contains */ +%pythonappend Universe::addCell %{ + # SWIG 3 + if 'cell' in locals(): + cell = locals()['cell'] + elif 'args' in locals() and 'cell' in locals()['args']: + cell = locals()['args']['cell'] + elif 'kwargs' in locals() and 'cell' in locals()['kwargs']: + cell = locals()['kwargs']['cell'] + + # SWIG 2 + else: + cell = locals()['args'][0] + + cell.thisown = False +%} + +/* Python must free memory for each Cell that is not in a Universe */ +%pythonappend Universe::removeCell %{ + # SWIG 3 + if 'cell' in locals(): + cell = locals()['cell'] + elif 'args' in locals() and 'cell' in locals()['args']: + cell = locals()['args']['cell'] + elif 'kwargs' in locals() and 'cell' in locals()['kwargs']: + cell = locals()['kwargs']['cell'] + + # SWIG 2 + else: + cell = locals()['args'][0] + + cell.thisown = True +%} + +/* A Lattice owns the memory for each Universe it contains */ +%pythonappend Lattice::setUniverses %{ + # SWIG 3 + if 'num_z' in locals(): + universes = locals()['num_z'] + elif 'args' in locals() and 'num_z' in locals()['args']: + universes = locals()['args']['num_z'] + elif 'kwargs' in locals() and 'num_z' in locals()['kwargs']: + universes = locals()['kwargs']['num_z'] + + # SWIG 2 + else: + universes = locals()['args'][0] + + for i in range(len(universes)): + for j in range(len(universes[i])): + for k in range(len(universes[i][j])): + universes[i][j][k].thisown = False +%} + +/* Python must free memory for each Universe that is not in a Lattice */ +%pythonappend Lattice::removeUniverse %{ + # SWIG 3 + if 'universe' in locals(): + universe = locals()['universe'] + elif 'args' in locals() and 'universe' in locals()['args']: + universe = locals()['args']['universe'] + elif 'kwargs' in locals() and 'universe' in locals()['kwargs']: + universe = locals()['kwargs']['universe'] + + # SWIG 2 + else: + universe = locals()['args'][0] + + universe.thisown = True +%} + +/* A TrackGenerator owns the memory for the Geometry it contains */ +%pythonappend TrackGenerator::TrackGenerator %{ + # SWIG 3 + if 'geometry' in locals(): + geometry = locals()['geometry'] + elif 'args' in locals() and 'geometry' in locals()['args']: + geometry = locals()['args']['geometry'] + elif 'kwargs' in locals() and 'geometry' in locals()['kwargs']: + geometry = locals()['kwargs']['geometry'] + + # SWIG 2 + else: + geometry = locals()['args'][0] + + geometry.thisown = False +%} + +/* A TrackGenerator owns the memory for the Geometry it contains */ +%pythonappend TrackGenerator::setGeometry %{ + # SWIG 3 + if 'geometry' in locals(): + geometry = locals()['geometry'] + elif 'args' in locals() and 'geometry' in locals()['args']: + geometry = locals()['args']['geometry'] + elif 'kwargs' in locals() and 'geometry' in locals()['kwargs']: + geometry = locals()['kwargs']['geometry'] + + # SWIG 2 + else: + geometry = locals()['args'][0] + + geometry.thisown = False +%} + +/* A Geometry owns the memory for the root Universe it contains */ +%pythonappend Geometry::setRootUniverse %{ + # SWIG 3 + if 'root_universe' in locals(): + root_universe = locals()['root_universe'] + elif 'args' in locals() and 'root_universe' in locals()['args']: + root_universe = locals()['args']['root_universe'] + elif 'kwargs' in locals() and 'root_universe' in locals()['kwargs']: + root_universe = locals()['kwargs']['root_universe'] + + # SWIG 2 + else: + root_universe = locals()['args'][0] + + root_universe.thisown = False +%} + +/* A Solver owns the memory for the PolarQuadrature it contains */ +%pythonappend Solver::setPolarQuadrature %{ + # SWIG 3 + if 'polar_quad' in locals(): + polar_quad = locals()['polar_quad'] + elif 'args' in locals() and 'polar_quad' in locals()['args']: + polar_quad = locals()['args']['polar_quad'] + elif 'kwargs' in locals() and 'polar_quad' in locals()['kwargs']: + polar_quad = locals()['kwargs']['polar_quad'] + + # SWIG 2 + else: + polar_quad = locals()['args'][0] + + polar_quad.thisown = False +%} + +/* A Solver owns the memory for the TrackGenerator it contains */ +%pythonappend Solver::setTrackGenerator %{ + # SWIG 3 + if 'track_generator' in locals(): + track_generator = locals()['track_generator'] + elif 'args' in locals() and 'track_generator' in locals()['args']: + track_generator = locals()['args']['track_generator'] + elif 'kwargs' in locals() and 'track_generator' in locals()['kwargs']: + track_generator = locals()['kwargs']['track_generator'] + + # SWIG 2 + else: + track_generator = locals()['args'][0] + + track_generator.thisown = False +%} + +/* A Solver owns the memory for the TrackGenerator it contains */ +%pythonappend Solver::Solver %{ + # SWIG 3 + if 'track_generator' in locals(): + track_generator = locals()['track_generator'] + elif 'args' in locals() and 'track_generator' in locals()['args']: + track_generator = locals()['args']['track_generator'] + elif 'kwargs' in locals() and 'track_generator' in locals()['kwargs']: + track_generator = locals()['kwargs']['track_generator'] + + # SWIG 2 + else: + track_generator = locals()['args'][0] + + track_generator.thisown = False +%} + +/* A CPUSolver owns the memory for the TrackGenerator it contains */ +%pythonappend CPUSolver::CPUSolver %{ + # SWIG 3 + if 'track_generator' in locals(): + track_generator = locals()['track_generator'] + elif 'args' in locals() and 'track_generator' in locals()['args']: + track_generator = locals()['args']['track_generator'] + elif 'kwargs' in locals() and 'track_generator' in locals()['kwargs']: + track_generator = locals()['kwargs']['track_generator'] + + # SWIG 2 + else: + track_generator = locals()['args'][0] + + # Only disown if user specified optional track_generator parameter + if track_generator: + track_generator.thisown = False +%} + +/* A GPUSolver owns the memory for the TrackGenerator it contains */ +%pythonappend GPUSolver::GPUSolver %{ + # SWIG 3 + if 'track_generator' in locals(): + track_generator = locals()['track_generator'] + elif 'args' in locals() and 'track_generator' in locals()['args']: + track_generator = locals()['args']['track_generator'] + elif 'kwargs' in locals() and 'track_generator' in locals()['kwargs']: + track_generator = locals()['kwargs']['track_generator'] + + # SWIG 2 + else: + track_generator = locals()['args'][0] + + track_generator.thisown = False +%} + +/* A VectorizedSolver owns the memory for the TrackGenerator it contains */ +%pythonappend VectorizedSolver::VectorizedSolver %{ + # SWIG 3 + if 'track_generator' in locals(): + track_generator = locals()['track_generator'] + elif 'args' in locals() and 'track_generator' in locals()['args']: + track_generator = locals()['args']['track_generator'] + elif 'kwargs' in locals() and 'track_generator' in locals()['kwargs']: + track_generator = locals()['kwargs']['track_generator'] + + # SWIG 2 + else: + track_generator = locals()['args'][0] + + track_generator.thisown = False +%} + + +/* A Geometry owns the memory for its Cmfd (if any) */ +%pythonappend Geometry::setCmfd %{ + # SWIG 3 + if 'cmfd' in locals(): + cmfd = locals()['cmfd'] + elif 'args' in locals() and 'cmfd' in locals()['args']: + cmfd = locals()['args']['cmfd'] + elif 'kwargs' in locals() and 'cmfd' in locals()['kwargs']: + cmfd = locals()['kwargs']['cmfd'] + + # SWIG 2 + else: + cmfd = locals()['args'][0] + + cmfd.thisown = False +%} diff --git a/profile/Makefile b/profile/Makefile new file mode 100644 index 000000000..712d9b4ad --- /dev/null +++ b/profile/Makefile @@ -0,0 +1,187 @@ +#=============================================================================== +# User Options +#=============================================================================== + +COMPILER = gnu +OPENMP = yes +OPTIMIZE = yes +DEBUG = no +PROFILE = no +PRECISION = single + +#=============================================================================== +# Source Code List +#=============================================================================== + +case = c5g7/c5g7-cmfd.cpp + +source = \ +Cell.cpp \ +Cmfd.cpp \ +CPUSolver.cpp \ +ExpEvaluator.cpp \ +Geometry.cpp \ +LocalCoords.cpp \ +linalg.cpp \ +log.cpp \ +Material.cpp \ +Matrix.cpp \ +Point.cpp \ +PolarQuad.cpp \ +Solver.cpp \ +Surface.cpp \ +Timer.cpp \ +Track.cpp \ +TrackGenerator.cpp \ +Universe.cpp \ +Vector.cpp + +cases = \ +gradients/one-directional/one-directional-gradient.cpp \ +gradients/two-directional/two-directional-gradient.cpp \ +homogeneous/homogeneous-one-group.cpp \ +c5g7/c5g7.cpp \ +c5g7/c5g7-cmfd.cpp + +#=============================================================================== +# Sets Flags +#=============================================================================== + +CFLAGS = -std=gnu++0x + +# Regular gcc Compiler +ifeq ($(COMPILER),gnu) + CC = g++ + CFLAGS += -DGNU +endif + +# intel Compiler +ifeq ($(COMPILER),intel) + CC = icpc + source += VectorizedSolver.cpp + CFLAGS += -DINTEL + CFLAGS += -I/opt/intel/composer_xe_2013_sp1.3.174/mkl/include + LDFLAGS += -mkl +endif + +# Clang Compiler +ifeq ($(COMPILER),clang) + CC = clang++ + CFLAGS += -DCLANG +endif + +# BG/Q gcc Cross-Compiler +# Note: make sure to set +mpiwrapper-gcc in your .soft file, +# as we only support the gcc cross-compiler wrapper +ifeq ($(COMPILER),bluegene) + CC = mpic++ + CFLAGS += -DGNU +endif + +# Debug Flags +ifeq ($(DEBUG),yes) + CFLAGS += -g + ifeq ($(COMPILER),intel) + CFLAGS += -vec-report + endif + ifeq ($(OPENMP),yes) + CFLAGS += -openmp-report + endif +endif + +# Profiling Flags +ifeq ($(PROFILE),yes) + CFLAGS += -pg +endif + +# Precision Flags +ifeq ($(PRECISION),single) + CFLAGS += -DFP_PRECISION=float + CFLAGS += -DSINGLE +endif +ifeq ($(PRECISION),double) + CFLAGS += -DFP_PRECISION=double + CFLAGS += -DDOUBLE +endif + +# Vector Flags +CFLAGS += -DVEC_LENGTH=8 +CFLAGS += -DVEC_ALIGNMENT=16 + +# Optimization Flags +ifeq ($(OPTIMIZE),yes) +ifeq ($(COMPILER),gnu) + CFLAGS += -O3 -ffast-math -fpic +endif +ifeq ($(COMPILER),intel) + CFLAGS += -O3 -xhost -fast -ansi-alias -no-prec-div -ipo +endif +ifeq ($(COMPILER),bluegene) + CFLAGS += -O3 -ffast-math -fpic +endif +ifeq ($(COMPILER),clang) + CFLAGS += -O3 -ffast-math -fvectorize -fpic +endif +endif + +# OpenMP +ifeq ($(OPENMP),yes) +ifeq ($(COMPILER), gnu) + CFLAGS += -fopenmp +endif +ifeq ($(COMPILER), bluegene) + CFLAGS += -fopenmp +endif +ifeq ($(COMPILER), intel) + CFLAGS += -openmp +endif +ifeq ($(COMPILER), clang) + CFLAGS += -fopenmp +endif + CFLAGS += -DOPENMP +endif + +#=============================================================================== +# Program Name and Object Files +#=============================================================================== + +obj := $(source:.cpp=.o) + +source := $(addprefix ../src/, $(source)) +headers = $(source:.cpp=.h) + +obj := $(addprefix obj/, $(obj)) +cases := $(addprefix models/, $(cases)) +case := $(addprefix models/, $(case)) + +programs = $(cases:.cpp=) +program = $(case:.cpp=) + +#=============================================================================== +# Targets to Build +#=============================================================================== + +default: folder $(addsuffix .o, $(program)) $(program) + +$(programs): $(obj) $(headers) + $(CC) $(CFLAGS) $(obj) $(addsuffix .o, $@) -o $@ $(LDFLAGS) + +obj/%.o: ../src/%.cpp Makefile + $(CC) $(CFLAGS) -c $< -o $@ + +models/%.o: models/%.cpp Makefile + $(CC) $(CFLAGS) -c $< -o $@ + +folder: + mkdir -p obj + +all: folder $(addsuffix .o, $(programs)) $(programs) + +clean: + rm -rf $(programs) $(obj) $(addsuffix .o, $(programs)) + +edit: + vim -p $(cases) + +run: + ./$(program) diff --git a/profile/models/c5g7/c5g7-cmfd.cpp b/profile/models/c5g7/c5g7-cmfd.cpp new file mode 100644 index 000000000..46b179ebc --- /dev/null +++ b/profile/models/c5g7/c5g7-cmfd.cpp @@ -0,0 +1,491 @@ +#include "../../../src/CPUSolver.h" +#include "../../../src/log.h" +#include +#include + +int main() { + + /* Define simulation parameters */ + #ifdef OPENMP + int num_threads = omp_get_num_procs(); + #else + int num_threads = 1; + #endif + double track_spacing = 0.1; + int num_azim = 4; + double tolerance = 1e-5; + int max_iters = 1000; + + /* Set logging information */ + set_log_level("NORMAL"); + log_printf(TITLE, "Simulating the OECD's C5G7 Benchmark Problem..."); + + /* Define material properties */ + log_printf(NORMAL, "Defining material properties..."); + + const size_t num_groups = 7; + std::map > nu_sigma_f; + std::map > sigma_f; + std::map > sigma_s; + std::map > chi; + std::map > sigma_t; + + /* Define water cross-sections */ + nu_sigma_f["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_f["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_s["Water"] = std::array + {0.0444777, 0.1134, 7.2347E-4, 3.7499E-6, 5.3184E-8, 0.0, 0.0, + 0.0, 0.282334, 0.12994, 6.234E-4, 4.8002E-5, 7.4486E-6, 1.0455E-6, + 0.0, 0.0, 0.345256, 0.22457, 0.016999, 0.0026443, 5.0344E-4, + 0.0, 0.0, 0.0, 0.0910284, 0.41551, 0.063732, 0.012139, + 0.0, 0.0, 0.0, 7.1437E-5, 0.139138, 0.51182, 0.061229, + 0.0, 0.0, 0.0, 0.0, 0.0022157, 0.699913, 0.53732, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.13244, 2.4807}; + chi["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_t["Water"] = std::array {0.159206, 0.41297, + 0.59031, 0.58435, 0.718, 1.25445, 2.65038}; + + /* Define UO2 cross-sections */ + nu_sigma_f["UO2"] = std::array {0.02005998, 0.002027303, + 0.01570599, 0.04518301, 0.04334208, 0.2020901, 0.5257105}; + sigma_f["UO2"] = std::array {0.00721206, 8.19301E-4, + 0.0064532, 0.0185648, 0.0178084, 0.0830348, 0.216004}; + sigma_s["UO2"] = std::array + {0.127537, 0.042378, 9.4374E-6, 5.5163E-9, 0.0, 0.0, 0.0, + 0.0, 0.324456, 0.0016314, 3.1427E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.45094, 0.0026792, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.452565, 0.0055664, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.2525E-4, 0.271401, 0.010255, 1.0021E-8, + 0.0, 0.0, 0.0, 0.0, 0.0012968, 0.265802, 0.016809, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0085458, 0.27308}; + chi["UO2"] = std::array {0.58791, 0.41176, 3.3906E-4, + 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["UO2"] = std::array {0.177949, 0.329805, + 0.480388, 0.554367, 0.311801, 0.395168, 0.564406}; + + /* Define MOX-4.3% cross-sections */ + nu_sigma_f["MOX-4.3%%"] = std::array {0.021753, + 0.002535103, 0.01626799, 0.0654741, 0.03072409, 0.666651, 0.7139904}; + sigma_f["MOX-4.3%%"] = std::array {0.00762704, + 8.76898E-4, 0.00569835, 0.0228872, 0.0107635, 0.232757, 0.248968}; + sigma_s["MOX-4.3%%"] = std::array + {0.128876, 0.041413, 8.229E-6, 5.0405E-9, 0.0, 0.0, 0.0, + 0.0, 0.325452, 0.0016395, 1.5982E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.453188, 0.0026142, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.457173, 0.0055394, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.6046E-4, 0.276814, 0.0093127, 9.1656E-9, + 0.0, 0.0, 0.0, 0.0, 0.0020051, 0.252962, 0.01485, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0084948, 0.265007}; + chi["MOX-4.3%%"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-4.3%%"] = std::array {0.178731, 0.330849, + 0.483772, 0.566922, 0.426227, 0.678997, 0.68285}; + + /* Define MOX-7% cross-sections */ + nu_sigma_f["MOX-7%%"] = std::array {0.02381395, + 0.003858689, 0.024134, 0.09436622, 0.04576988, 0.9281814, 1.0432}; + sigma_f["MOX-7%%"] = std::array {0.00825446, 0.00132565, + 0.00842156, 0.032873, 0.0159636, 0.323794, 0.362803}; + sigma_s["MOX-7%%"] = std::array + {0.130457, 0.041792, 8.5105E-6, 5.1329E-9, 0.0, 0.0, 0.0, + 0.0, 0.328428, 0.0016436, 2.2017E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.458371, 0.0025331, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.463709, 0.0054766, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.7619E-4, 0.282313, 0.0087289, 9.0016E-9, + 0.0, 0.0, 0.0, 0.0, 0.002276, 0.249751, 0.013114, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0088645, 0.259529}; + chi["MOX-7%%"] = std::array {0.58791, 0.41176, 3.3906E-4, + 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-7%%"] = std::array {0.181323, 0.334368, + 0.493785, 0.591216, 0.474198, 0.833601, 0.853603}; + + /* Define MOX-8.7% cross-sections */ + nu_sigma_f["MOX-8.7%%"] = std::array {0.025186, + 0.004739509, 0.02947805, 0.11225, 0.05530301, 1.074999, 1.239298}; + sigma_f["MOX-8.7%%"] = std::array {0.00867209, + 0.00162426, 0.0102716, 0.0390447, 0.0192576, 0.374888, 0.430599}; + sigma_s["MOX-8.7%%"] = std::array + {0.131504, 0.042046, 8.6972E-6, 5.1938E-9, 0.0, 0.0, 0.0, + 0.0, 0.330403, 0.0016463, 2.6006E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.461792, 0.0024749, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.468021, 0.005433, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.8597E-4, 0.285771, 0.0083973, 8.928E-9, + 0.0, 0.0, 0.0, 0.0, 0.0023916, 0.247614, 0.012322, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0089681, 0.256093}; + chi["MOX-8.7%%"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-8.7%%"] = std::array {0.183045, 0.336705, + 0.500507, 0.606174, 0.502754, 0.921028, 0.955231}; + + /* Define fission chamber cross-sections */ + nu_sigma_f["Fission Chamber"] = std::array {1.323401E-8, + 1.4345E-8, 1.128599E-6, 1.276299E-5, 3.538502E-7, 1.740099E-6, + 5.063302E-6}; + sigma_f["Fission Chamber"] = std::array {4.79002E-9, + 5.82564E-9, 4.63719E-7, 5.24406E-6, 1.4539E-7, 7.14972E-7, 2.08041E-6}; + sigma_s["Fission Chamber"] = std::array + {0.0661659, 0.05907, 2.8334E-4, 1.4622E-6, 2.0642E-8, 0.0, 0.0, + 0.0, 0.240377, 0.052435, 2.499E-4, 1.9239E-5, 2.9875E-6, 4.214E-7, + 0.0, 0.0, 0.183425, 0.092288, 0.0069365, 0.001079, 2.0543E-4, + 0.0, 0.0, 0.0, 0.0790769, 0.16999, 0.02586, 0.0049256, + 0.0, 0.0, 0.0, 3.734E-5, 0.099757, 0.20679, 0.024478, + 0.0, 0.0, 0.0, 0.0, 9.1742E-4, 0.316774, 0.23876, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.049793, 1.0991}; + chi["Fission Chamber"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["Fission Chamber"] = std::array {0.126032, + 0.29316, 0.28425, 0.28102, 0.33446, 0.56564, 1.17214}; + + /* Define guide tube cross-sections */ + nu_sigma_f["Guide Tube"] = std::array {0, 0, 0, 0, 0, + 0, 0}; + sigma_f["Guide Tube"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_s["Guide Tube"] = std::array + {0.0661659, 0.05907, 2.8334E-4, 1.4622E-6, 2.0642E-8, 0.0, 0.0, + 0.0, 0.240377, 0.052435, 2.499E-4, 1.9239E-5, 2.9875E-6, 4.214E-7, + 0.0, 0.0, 0.183297, 0.092397, 0.0069446, 0.0010803, 2.0567E-4, + 0.0, 0.0, 0.0, 0.0788511, 0.17014, 0.025881, 0.0049297, + 0.0, 0.0, 0.0, 3.7333E-5, 0.0997372, 0.20679, 0.024478, + 0.0, 0.0, 0.0, 0.0, 9.1726E-4, 0.316765, 0.23877, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.049792, 1.09912}; + chi["Guide Tube"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_t["Guide Tube"] = std::array {0.126032, 0.29316, + 0.28424, 0.28096, 0.33444, 0.56564, 1.17215}; + + /* Create materials */ + log_printf(NORMAL, "Creating materials..."); + std::map materials; + + std::map >::iterator it; + int id_num = 0; + for (it = sigma_t.begin(); it != sigma_t.end(); it++) { + + std::string name = it->first; + materials[name] = new Material(id_num, name.c_str()); + materials[name]->setNumEnergyGroups(num_groups); + id_num++; + + materials[name]->setSigmaF(sigma_f[name].data(), num_groups); + materials[name]->setNuSigmaF(nu_sigma_f[name].data(), num_groups); + materials[name]->setSigmaS(sigma_s[name].data(), num_groups*num_groups); + materials[name]->setChi(chi[name].data(), num_groups); + materials[name]->setSigmaT(sigma_t[name].data(), num_groups); + } + + /* Create surfaces */ + XPlane left(-32.13); + XPlane right(32.13); + YPlane top(32.13); + YPlane bottom(-32.13); + + left.setBoundaryType(REFLECTIVE); + right.setBoundaryType(VACUUM); + top.setBoundaryType(REFLECTIVE); + bottom.setBoundaryType(VACUUM); + + /* Create circles for the fuel as well as to discretize the moderator into + rings */ + ZCylinder fuel_radius(0.0, 0.0, 0.54); + ZCylinder moderator_inner_radius(0.0, 0.0, 0.58); + ZCylinder moderator_outer_radius(0.0, 0.0, 0.62); + + /* Create cells and universes */ + log_printf(NORMAL, "Creating cells..."); + + /* Moderator rings */ + Cell* moderator_ring1 = new Cell(21, "mod1"); + Cell* moderator_ring2 = new Cell(1, "mod2"); + Cell* moderator_ring3 = new Cell(2, "mod3"); + moderator_ring1->setNumSectors(8); + moderator_ring2->setNumSectors(8); + moderator_ring3->setNumSectors(8); + moderator_ring1->setFill(materials["Water"]); + moderator_ring2->setFill(materials["Water"]); + moderator_ring3->setFill(materials["Water"]); + moderator_ring1->addSurface(+1, &fuel_radius); + moderator_ring1->addSurface(-1, &moderator_inner_radius); + moderator_ring2->addSurface(+1, &moderator_inner_radius); + moderator_ring2->addSurface(-1, &moderator_outer_radius); + moderator_ring3->addSurface(+1, &moderator_outer_radius); + + /* UO2 pin cell */ + Cell* uo2_cell = new Cell(3, "uo2"); + uo2_cell->setNumRings(3); + uo2_cell->setNumSectors(8); + uo2_cell->setFill(materials["UO2"]); + uo2_cell->addSurface(-1, &fuel_radius); + + Universe* uo2 = new Universe(); + uo2->addCell(uo2_cell); + uo2->addCell(moderator_ring1); + uo2->addCell(moderator_ring2); + uo2->addCell(moderator_ring3); + + /* 4.3% MOX pin cell */ + Cell* mox43_cell = new Cell(4, "mox43"); + mox43_cell->setNumRings(3); + mox43_cell->setNumSectors(8); + mox43_cell->setFill(materials["MOX-4.3%%"]); + mox43_cell->addSurface(-1, &fuel_radius); + + Universe* mox43 = new Universe(); + mox43->addCell(mox43_cell); + mox43->addCell(moderator_ring1); + mox43->addCell(moderator_ring2); + mox43->addCell(moderator_ring3); + + /* 7% MOX pin cell */ + Cell* mox7_cell = new Cell(5, "mox7"); + mox7_cell->setNumRings(3); + mox7_cell->setNumSectors(8); + mox7_cell->setFill(materials["MOX-7%%"]); + mox7_cell->addSurface(-1, &fuel_radius); + + Universe* mox7 = new Universe(); + mox7->addCell(mox7_cell); + mox7->addCell(moderator_ring1); + mox7->addCell(moderator_ring2); + mox7->addCell(moderator_ring3); + + /* 8.7% MOX pin cell */ + Cell* mox87_cell = new Cell(6, "mox87"); + mox87_cell->setNumRings(3); + mox87_cell->setNumSectors(8); + mox87_cell->setFill(materials["MOX-8.7%%"]); + mox87_cell->addSurface(-1, &fuel_radius); + + Universe* mox87 = new Universe(); + mox87->addCell(mox87_cell); + mox87->addCell(moderator_ring1); + mox87->addCell(moderator_ring2); + mox87->addCell(moderator_ring3); + + /* Fission chamber pin cell */ + Cell* fission_chamber_cell = new Cell(7, "fc"); + fission_chamber_cell->setNumRings(3); + fission_chamber_cell->setNumSectors(8); + fission_chamber_cell->setFill(materials["Fission Chamber"]); + fission_chamber_cell->addSurface(-1, &fuel_radius); + + Universe* fission_chamber = new Universe(); + fission_chamber->addCell(fission_chamber_cell); + fission_chamber->addCell(moderator_ring1); + fission_chamber->addCell(moderator_ring2); + fission_chamber->addCell(moderator_ring3); + + /* Guide tube pin cell */ + Cell* guide_tube_cell = new Cell(8, "gtc"); + guide_tube_cell->setNumRings(3); + guide_tube_cell->setNumSectors(8); + guide_tube_cell->setFill(materials["Guide Tube"]); + guide_tube_cell->addSurface(-1, &fuel_radius); + + Universe* guide_tube = new Universe(); + guide_tube->addCell(guide_tube_cell); + guide_tube->addCell(moderator_ring1); + guide_tube->addCell(moderator_ring2); + guide_tube->addCell(moderator_ring3); + + /* Reflector */ + Cell* reflector_cell = new Cell(9, "rc"); + reflector_cell->setFill(materials["Water"]); + + Universe* reflector = new Universe(); + reflector->addCell(reflector_cell); + + /* Cells */ + Cell* assembly1_cell = new Cell(10, "ac1"); + Cell* assembly2_cell = new Cell(11, "ac2"); + Cell* refined_reflector_cell = new Cell(12, "rrc"); + Cell* right_reflector_cell = new Cell(13,"rrc2"); + Cell* corner_reflector_cell = new Cell(14, "crc"); + Cell* bottom_reflector_cell = new Cell(15, "brc"); + + Universe* assembly1 = new Universe(); + Universe* assembly2 = new Universe(); + Universe* refined_reflector = new Universe(); + Universe* right_reflector = new Universe(); + Universe* corner_reflector = new Universe(); + Universe* bottom_reflector = new Universe(); + + assembly1->addCell(assembly1_cell); + assembly2->addCell(assembly2_cell); + refined_reflector->addCell(refined_reflector_cell); + right_reflector->addCell(right_reflector_cell); + corner_reflector->addCell(corner_reflector_cell); + bottom_reflector->addCell(bottom_reflector_cell); + + /* Root Cell* */ + Cell* root_cell = new Cell(16, "root"); + root_cell->addSurface(+1, &left); + root_cell->addSurface(-1, &right); + root_cell->addSurface(-1, &top); + root_cell->addSurface(+1, &bottom); + + Universe* root_universe = new Universe(); + root_universe->addCell(root_cell); + + /* Create lattices */ + log_printf(NORMAL, "Creating lattices..."); + + /* Top left, bottom right 17 x 17 assemblies */ + Lattice* assembly1_lattice = new Lattice(); + assembly1_lattice->setWidth(1.26, 1.26); + Universe* matrix1[17*17]; + { + int mold[17*17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + std::map names = {{1, uo2}, {2, guide_tube}, + {3, fission_chamber}}; + for (int n=0; n<17*17; n++) + matrix1[n] = names[mold[n]]; + + assembly1_lattice->setUniverses(1, 17, 17, matrix1); + } + assembly1_cell->setFill(assembly1_lattice); + + /* Top right, bottom left 17 x 17 assemblies */ + Lattice* assembly2_lattice = new Lattice(); + assembly2_lattice->setWidth(1.26, 1.26); + Universe* matrix2[17*17]; + { + int mold[17*17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1, + 1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1, + 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, + 1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1, + 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + std::map names = {{1, mox43}, {2, mox7}, {3, mox87}, + {4, guide_tube}, {5, fission_chamber}}; + for (int n=0; n<17*17; n++) + matrix2[n] = names[mold[n]]; + + assembly2_lattice->setUniverses(1, 17, 17, matrix2); + } + assembly2_cell->setFill(assembly2_lattice); + + /* Sliced up water cells - semi finely spaced */ + Lattice* refined_ref_lattice = new Lattice(); + refined_ref_lattice->setWidth(0.126, 0.126); + Universe* refined_ref_matrix[10*10]; + for (int n=0; n<10*10; n++) + refined_ref_matrix[n] = reflector; + refined_ref_lattice->setUniverses(1, 10, 10, refined_ref_matrix); + refined_reflector_cell->setFill(refined_ref_lattice); + + /* Sliced up water cells - right side of geometry */ + Lattice* right_ref_lattice = new Lattice(); + right_ref_lattice->setWidth(1.26, 1.26); + Universe* right_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (i<11) + right_ref_matrix[index] = refined_reflector; + else + right_ref_matrix[index] = reflector; + } + } + right_ref_lattice->setUniverses(1, 17, 17, right_ref_matrix); + right_reflector_cell->setFill(right_ref_lattice); + + /* Sliced up water cells for bottom corner of geometry */ + Lattice* corner_ref_lattice = new Lattice(); + corner_ref_lattice->setWidth(1.26, 1.26); + Universe* corner_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (i<11 && j<11) + corner_ref_matrix[index] = refined_reflector; + else + corner_ref_matrix[index] = reflector; + } + } + corner_ref_lattice->setUniverses(1, 17, 17, corner_ref_matrix); + corner_reflector_cell->setFill(corner_ref_lattice); + + /* Sliced up water cells for bottom of geometry */ + Lattice* bottom_ref_lattice = new Lattice(); + bottom_ref_lattice->setWidth(1.26, 1.26); + Universe* bottom_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (j<11) + bottom_ref_matrix[index] = refined_reflector; + else + bottom_ref_matrix[index] = reflector; + } + } + bottom_ref_lattice->setUniverses(1, 17, 17, bottom_ref_matrix); + bottom_reflector_cell->setFill(bottom_ref_lattice); + + /* 4 x 4 core to represent two bundles and water */ + Lattice* full_geometry = new Lattice(); + full_geometry->setWidth(21.42, 21.42); + Universe* universes[] = { + assembly1, assembly2, right_reflector, + assembly2, assembly1, right_reflector, + bottom_reflector, bottom_reflector, corner_reflector}; + full_geometry->setUniverses(1, 3, 3, universes); + root_cell->setFill(full_geometry); + + /* Create CMFD mesh */ + log_printf(NORMAL, "Creating CMFD mesh..."); + + Cmfd cmfd; + cmfd.setSORRelaxationFactor(1.5); + cmfd.setLatticeStructure(51, 51); + int cmfd_group_structure[3] = {1,4,8}; + cmfd.setGroupStructure(cmfd_group_structure, 3); + + /* Create the geometry */ + log_printf(NORMAL, "Creating geometry..."); + Geometry geometry; + geometry.setRootUniverse(root_universe); + geometry.setCmfd(&cmfd); + + /* Generate tracks */ + log_printf(NORMAL, "Initializing the track generator..."); + TrackGenerator track_generator(&geometry, num_azim, track_spacing); + track_generator.setNumThreads(num_threads); + track_generator.generateTracks(); + + /* Run simulation */ + CPUSolver solver(&track_generator); + solver.setNumThreads(num_threads); + solver.setConvergenceThreshold(tolerance); + solver.computeEigenvalue(max_iters); + solver.printTimerReport(); + + return 0; +} diff --git a/profile/models/c5g7/c5g7.cpp b/profile/models/c5g7/c5g7.cpp new file mode 100644 index 000000000..d0a3559ea --- /dev/null +++ b/profile/models/c5g7/c5g7.cpp @@ -0,0 +1,481 @@ +#include "../../../src/CPUSolver.h" +#include "../../../src/log.h" +#include +#include + +int main() { + + /* Define simulation parameters */ + #ifdef OPENMP + int num_threads = omp_get_num_procs(); + #else + int num_threads = 1; + #endif + double track_spacing = 0.1; + int num_azim = 4; + double tolerance = 1e-5; + int max_iters = 1000; + + /* Set logging information */ + set_log_level("NORMAL"); + log_printf(TITLE, "Simulating the OECD's C5G7 Benchmark Problem..."); + + /* Define material properties */ + log_printf(NORMAL, "Defining material properties..."); + + const size_t num_groups = 7; + std::map > nu_sigma_f; + std::map > sigma_f; + std::map > sigma_s; + std::map > chi; + std::map > sigma_t; + + /* Define water cross-sections */ + nu_sigma_f["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_f["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_s["Water"] = std::array + {0.0444777, 0.1134, 7.2347E-4, 3.7499E-6, 5.3184E-8, 0.0, 0.0, + 0.0, 0.282334, 0.12994, 6.234E-4, 4.8002E-5, 7.4486E-6, 1.0455E-6, + 0.0, 0.0, 0.345256, 0.22457, 0.016999, 0.0026443, 5.0344E-4, + 0.0, 0.0, 0.0, 0.0910284, 0.41551, 0.063732, 0.012139, + 0.0, 0.0, 0.0, 7.1437E-5, 0.139138, 0.51182, 0.061229, + 0.0, 0.0, 0.0, 0.0, 0.0022157, 0.699913, 0.53732, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.13244, 2.4807}; + chi["Water"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_t["Water"] = std::array {0.159206, 0.41297, + 0.59031, 0.58435, 0.718, 1.25445, 2.65038}; + + /* Define UO2 cross-sections */ + nu_sigma_f["UO2"] = std::array {0.02005998, 0.002027303, + 0.01570599, 0.04518301, 0.04334208, 0.2020901, 0.5257105}; + sigma_f["UO2"] = std::array {0.00721206, 8.19301E-4, + 0.0064532, 0.0185648, 0.0178084, 0.0830348, 0.216004}; + sigma_s["UO2"] = std::array + {0.127537, 0.042378, 9.4374E-6, 5.5163E-9, 0.0, 0.0, 0.0, + 0.0, 0.324456, 0.0016314, 3.1427E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.45094, 0.0026792, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.452565, 0.0055664, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.2525E-4, 0.271401, 0.010255, 1.0021E-8, + 0.0, 0.0, 0.0, 0.0, 0.0012968, 0.265802, 0.016809, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0085458, 0.27308}; + chi["UO2"] = std::array {0.58791, 0.41176, 3.3906E-4, + 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["UO2"] = std::array {0.177949, 0.329805, + 0.480388, 0.554367, 0.311801, 0.395168, 0.564406}; + + /* Define MOX-4.3% cross-sections */ + nu_sigma_f["MOX-4.3%%"] = std::array {0.021753, + 0.002535103, 0.01626799, 0.0654741, 0.03072409, 0.666651, 0.7139904}; + sigma_f["MOX-4.3%%"] = std::array {0.00762704, + 8.76898E-4, 0.00569835, 0.0228872, 0.0107635, 0.232757, 0.248968}; + sigma_s["MOX-4.3%%"] = std::array + {0.128876, 0.041413, 8.229E-6, 5.0405E-9, 0.0, 0.0, 0.0, + 0.0, 0.325452, 0.0016395, 1.5982E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.453188, 0.0026142, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.457173, 0.0055394, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.6046E-4, 0.276814, 0.0093127, 9.1656E-9, + 0.0, 0.0, 0.0, 0.0, 0.0020051, 0.252962, 0.01485, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0084948, 0.265007}; + chi["MOX-4.3%%"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-4.3%%"] = std::array {0.178731, 0.330849, + 0.483772, 0.566922, 0.426227, 0.678997, 0.68285}; + + /* Define MOX-7% cross-sections */ + nu_sigma_f["MOX-7%%"] = std::array {0.02381395, + 0.003858689, 0.024134, 0.09436622, 0.04576988, 0.9281814, 1.0432}; + sigma_f["MOX-7%%"] = std::array {0.00825446, 0.00132565, + 0.00842156, 0.032873, 0.0159636, 0.323794, 0.362803}; + sigma_s["MOX-7%%"] = std::array + {0.130457, 0.041792, 8.5105E-6, 5.1329E-9, 0.0, 0.0, 0.0, + 0.0, 0.328428, 0.0016436, 2.2017E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.458371, 0.0025331, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.463709, 0.0054766, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.7619E-4, 0.282313, 0.0087289, 9.0016E-9, + 0.0, 0.0, 0.0, 0.0, 0.002276, 0.249751, 0.013114, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0088645, 0.259529}; + chi["MOX-7%%"] = std::array {0.58791, 0.41176, 3.3906E-4, + 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-7%%"] = std::array {0.181323, 0.334368, + 0.493785, 0.591216, 0.474198, 0.833601, 0.853603}; + + /* Define MOX-8.7% cross-sections */ + nu_sigma_f["MOX-8.7%%"] = std::array {0.025186, + 0.004739509, 0.02947805, 0.11225, 0.05530301, 1.074999, 1.239298}; + sigma_f["MOX-8.7%%"] = std::array {0.00867209, + 0.00162426, 0.0102716, 0.0390447, 0.0192576, 0.374888, 0.430599}; + sigma_s["MOX-8.7%%"] = std::array + {0.131504, 0.042046, 8.6972E-6, 5.1938E-9, 0.0, 0.0, 0.0, + 0.0, 0.330403, 0.0016463, 2.6006E-9, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.461792, 0.0024749, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.468021, 0.005433, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.8597E-4, 0.285771, 0.0083973, 8.928E-9, + 0.0, 0.0, 0.0, 0.0, 0.0023916, 0.247614, 0.012322, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0089681, 0.256093}; + chi["MOX-8.7%%"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["MOX-8.7%%"] = std::array {0.183045, 0.336705, + 0.500507, 0.606174, 0.502754, 0.921028, 0.955231}; + + /* Define fission chamber cross-sections */ + nu_sigma_f["Fission Chamber"] = std::array {1.323401E-8, + 1.4345E-8, 1.128599E-6, 1.276299E-5, 3.538502E-7, 1.740099E-6, + 5.063302E-6}; + sigma_f["Fission Chamber"] = std::array {4.79002E-9, + 5.82564E-9, 4.63719E-7, 5.24406E-6, 1.4539E-7, 7.14972E-7, 2.08041E-6}; + sigma_s["Fission Chamber"] = std::array + {0.0661659, 0.05907, 2.8334E-4, 1.4622E-6, 2.0642E-8, 0.0, 0.0, + 0.0, 0.240377, 0.052435, 2.499E-4, 1.9239E-5, 2.9875E-6, 4.214E-7, + 0.0, 0.0, 0.183425, 0.092288, 0.0069365, 0.001079, 2.0543E-4, + 0.0, 0.0, 0.0, 0.0790769, 0.16999, 0.02586, 0.0049256, + 0.0, 0.0, 0.0, 3.734E-5, 0.099757, 0.20679, 0.024478, + 0.0, 0.0, 0.0, 0.0, 9.1742E-4, 0.316774, 0.23876, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.049793, 1.0991}; + chi["Fission Chamber"] = std::array {0.58791, 0.41176, + 3.3906E-4, 1.1761E-7, 0.0, 0.0, 0.0}; + sigma_t["Fission Chamber"] = std::array {0.126032, + 0.29316, 0.28425, 0.28102, 0.33446, 0.56564, 1.17214}; + + /* Define guide tube cross-sections */ + nu_sigma_f["Guide Tube"] = std::array {0, 0, 0, 0, 0, + 0, 0}; + sigma_f["Guide Tube"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_s["Guide Tube"] = std::array + {0.0661659, 0.05907, 2.8334E-4, 1.4622E-6, 2.0642E-8, 0.0, 0.0, + 0.0, 0.240377, 0.052435, 2.499E-4, 1.9239E-5, 2.9875E-6, 4.214E-7, + 0.0, 0.0, 0.183297, 0.092397, 0.0069446, 0.0010803, 2.0567E-4, + 0.0, 0.0, 0.0, 0.0788511, 0.17014, 0.025881, 0.0049297, + 0.0, 0.0, 0.0, 3.7333E-5, 0.0997372, 0.20679, 0.024478, + 0.0, 0.0, 0.0, 0.0, 9.1726E-4, 0.316765, 0.23877, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.049792, 1.09912}; + chi["Guide Tube"] = std::array {0, 0, 0, 0, 0, 0, 0}; + sigma_t["Guide Tube"] = std::array {0.126032, 0.29316, + 0.28424, 0.28096, 0.33444, 0.56564, 1.17215}; + + /* Create materials */ + log_printf(NORMAL, "Creating materials..."); + std::map materials; + + std::map >::iterator it; + int id_num = 0; + for (it = sigma_t.begin(); it != sigma_t.end(); it++) { + + std::string name = it->first; + materials[name] = new Material(id_num, name.c_str()); + materials[name]->setNumEnergyGroups(num_groups); + id_num++; + + materials[name]->setSigmaF(sigma_f[name].data(), num_groups); + materials[name]->setNuSigmaF(nu_sigma_f[name].data(), num_groups); + materials[name]->setSigmaS(sigma_s[name].data(), num_groups*num_groups); + materials[name]->setChi(chi[name].data(), num_groups); + materials[name]->setSigmaT(sigma_t[name].data(), num_groups); + } + + /* Create surfaces */ + XPlane left(-32.13); + XPlane right(32.13); + YPlane top(32.13); + YPlane bottom(-32.13); + + left.setBoundaryType(REFLECTIVE); + right.setBoundaryType(VACUUM); + top.setBoundaryType(REFLECTIVE); + bottom.setBoundaryType(VACUUM); + + /* Create circles for the fuel as well as to discretize the moderator into + rings */ + ZCylinder fuel_radius(0.0, 0.0, 0.54); + ZCylinder moderator_inner_radius(0.0, 0.0, 0.58); + ZCylinder moderator_outer_radius(0.0, 0.0, 0.62); + + /* Create cells and universes */ + log_printf(NORMAL, "Creating cells..."); + + /* Moderator rings */ + Cell* moderator_ring1 = new Cell(21, "mod1"); + Cell* moderator_ring2 = new Cell(1, "mod2"); + Cell* moderator_ring3 = new Cell(2, "mod3"); + moderator_ring1->setNumSectors(8); + moderator_ring2->setNumSectors(8); + moderator_ring3->setNumSectors(8); + moderator_ring1->setFill(materials["Water"]); + moderator_ring2->setFill(materials["Water"]); + moderator_ring3->setFill(materials["Water"]); + moderator_ring1->addSurface(+1, &fuel_radius); + moderator_ring1->addSurface(-1, &moderator_inner_radius); + moderator_ring2->addSurface(+1, &moderator_inner_radius); + moderator_ring2->addSurface(-1, &moderator_outer_radius); + moderator_ring3->addSurface(+1, &moderator_outer_radius); + + /* UO2 pin cell */ + Cell* uo2_cell = new Cell(3, "uo2"); + uo2_cell->setNumRings(3); + uo2_cell->setNumSectors(8); + uo2_cell->setFill(materials["UO2"]); + uo2_cell->addSurface(-1, &fuel_radius); + + Universe* uo2 = new Universe(); + uo2->addCell(uo2_cell); + uo2->addCell(moderator_ring1); + uo2->addCell(moderator_ring2); + uo2->addCell(moderator_ring3); + + /* 4.3% MOX pin cell */ + Cell* mox43_cell = new Cell(4, "mox43"); + mox43_cell->setNumRings(3); + mox43_cell->setNumSectors(8); + mox43_cell->setFill(materials["MOX-4.3%%"]); + mox43_cell->addSurface(-1, &fuel_radius); + + Universe* mox43 = new Universe(); + mox43->addCell(mox43_cell); + mox43->addCell(moderator_ring1); + mox43->addCell(moderator_ring2); + mox43->addCell(moderator_ring3); + + /* 7% MOX pin cell */ + Cell* mox7_cell = new Cell(5, "mox7"); + mox7_cell->setNumRings(3); + mox7_cell->setNumSectors(8); + mox7_cell->setFill(materials["MOX-7%%"]); + mox7_cell->addSurface(-1, &fuel_radius); + + Universe* mox7 = new Universe(); + mox7->addCell(mox7_cell); + mox7->addCell(moderator_ring1); + mox7->addCell(moderator_ring2); + mox7->addCell(moderator_ring3); + + /* 8.7% MOX pin cell */ + Cell* mox87_cell = new Cell(6, "mox87"); + mox87_cell->setNumRings(3); + mox87_cell->setNumSectors(8); + mox87_cell->setFill(materials["MOX-8.7%%"]); + mox87_cell->addSurface(-1, &fuel_radius); + + Universe* mox87 = new Universe(); + mox87->addCell(mox87_cell); + mox87->addCell(moderator_ring1); + mox87->addCell(moderator_ring2); + mox87->addCell(moderator_ring3); + + /* Fission chamber pin cell */ + Cell* fission_chamber_cell = new Cell(7, "fc"); + fission_chamber_cell->setNumRings(3); + fission_chamber_cell->setNumSectors(8); + fission_chamber_cell->setFill(materials["Fission Chamber"]); + fission_chamber_cell->addSurface(-1, &fuel_radius); + + Universe* fission_chamber = new Universe(); + fission_chamber->addCell(fission_chamber_cell); + fission_chamber->addCell(moderator_ring1); + fission_chamber->addCell(moderator_ring2); + fission_chamber->addCell(moderator_ring3); + + /* Guide tube pin cell */ + Cell* guide_tube_cell = new Cell(8, "gtc"); + guide_tube_cell->setNumRings(3); + guide_tube_cell->setNumSectors(8); + guide_tube_cell->setFill(materials["Guide Tube"]); + guide_tube_cell->addSurface(-1, &fuel_radius); + + Universe* guide_tube = new Universe(); + guide_tube->addCell(guide_tube_cell); + guide_tube->addCell(moderator_ring1); + guide_tube->addCell(moderator_ring2); + guide_tube->addCell(moderator_ring3); + + /* Reflector */ + Cell* reflector_cell = new Cell(9, "rc"); + reflector_cell->setFill(materials["Water"]); + + Universe* reflector = new Universe(); + reflector->addCell(reflector_cell); + + /* Cells */ + Cell* assembly1_cell = new Cell(10, "ac1"); + Cell* assembly2_cell = new Cell(11, "ac2"); + Cell* refined_reflector_cell = new Cell(12, "rrc"); + Cell* right_reflector_cell = new Cell(13,"rrc2"); + Cell* corner_reflector_cell = new Cell(14, "crc"); + Cell* bottom_reflector_cell = new Cell(15, "brc"); + + Universe* assembly1 = new Universe(); + Universe* assembly2 = new Universe(); + Universe* refined_reflector = new Universe(); + Universe* right_reflector = new Universe(); + Universe* corner_reflector = new Universe(); + Universe* bottom_reflector = new Universe(); + + assembly1->addCell(assembly1_cell); + assembly2->addCell(assembly2_cell); + refined_reflector->addCell(refined_reflector_cell); + right_reflector->addCell(right_reflector_cell); + corner_reflector->addCell(corner_reflector_cell); + bottom_reflector->addCell(bottom_reflector_cell); + + /* Root Cell* */ + Cell* root_cell = new Cell(16, "root"); + root_cell->addSurface(+1, &left); + root_cell->addSurface(-1, &right); + root_cell->addSurface(-1, &top); + root_cell->addSurface(+1, &bottom); + + Universe* root_universe = new Universe(); + root_universe->addCell(root_cell); + + /* Create lattices */ + log_printf(NORMAL, "Creating lattices..."); + + /* Top left, bottom right 17 x 17 assemblies */ + Lattice* assembly1_lattice = new Lattice(); + assembly1_lattice->setWidth(1.26, 1.26); + Universe* matrix1[17*17]; + { + int mold[17*17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + std::map names = {{1, uo2}, {2, guide_tube}, + {3, fission_chamber}}; + for (int n=0; n<17*17; n++) + matrix1[n] = names[mold[n]]; + + assembly1_lattice->setUniverses(1, 17, 17, matrix1); + } + assembly1_cell->setFill(assembly1_lattice); + + /* Top right, bottom left 17 x 17 assemblies */ + Lattice* assembly2_lattice = new Lattice(); + assembly2_lattice->setWidth(1.26, 1.26); + Universe* matrix2[17*17]; + { + int mold[17*17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1, + 1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1, + 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, + 1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1, + 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, + 1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1, + 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + std::map names = {{1, mox43}, {2, mox7}, {3, mox87}, + {4, guide_tube}, {5, fission_chamber}}; + for (int n=0; n<17*17; n++) + matrix2[n] = names[mold[n]]; + + assembly2_lattice->setUniverses(1, 17, 17, matrix2); + } + assembly2_cell->setFill(assembly2_lattice); + + /* Sliced up water cells - semi finely spaced */ + Lattice* refined_ref_lattice = new Lattice(); + refined_ref_lattice->setWidth(0.126, 0.126); + Universe* refined_ref_matrix[10*10]; + for (int n=0; n<10*10; n++) + refined_ref_matrix[n] = reflector; + refined_ref_lattice->setUniverses(1, 10, 10, refined_ref_matrix); + refined_reflector_cell->setFill(refined_ref_lattice); + + /* Sliced up water cells - right side of geometry */ + Lattice* right_ref_lattice = new Lattice(); + right_ref_lattice->setWidth(1.26, 1.26); + Universe* right_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (i<11) + right_ref_matrix[index] = refined_reflector; + else + right_ref_matrix[index] = reflector; + } + } + right_ref_lattice->setUniverses(1, 17, 17, right_ref_matrix); + right_reflector_cell->setFill(right_ref_lattice); + + /* Sliced up water cells for bottom corner of geometry */ + Lattice* corner_ref_lattice = new Lattice(); + corner_ref_lattice->setWidth(1.26, 1.26); + Universe* corner_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (i<11 && j<11) + corner_ref_matrix[index] = refined_reflector; + else + corner_ref_matrix[index] = reflector; + } + } + corner_ref_lattice->setUniverses(1, 17, 17, corner_ref_matrix); + corner_reflector_cell->setFill(corner_ref_lattice); + + /* Sliced up water cells for bottom of geometry */ + Lattice* bottom_ref_lattice = new Lattice(); + bottom_ref_lattice->setWidth(1.26, 1.26); + Universe* bottom_ref_matrix[17*17]; + for (int i=0; i<17; i++) { + for (int j=0; j<17; j++) { + int index = 17*j + i; + if (j<11) + bottom_ref_matrix[index] = refined_reflector; + else + bottom_ref_matrix[index] = reflector; + } + } + bottom_ref_lattice->setUniverses(1, 17, 17, bottom_ref_matrix); + bottom_reflector_cell->setFill(bottom_ref_lattice); + + /* 4 x 4 core to represent two bundles and water */ + Lattice* full_geometry = new Lattice(); + full_geometry->setWidth(21.42, 21.42); + Universe* universes[] = { + assembly1, assembly2, right_reflector, + assembly2, assembly1, right_reflector, + bottom_reflector, bottom_reflector, corner_reflector}; + full_geometry->setUniverses(1, 3, 3, universes); + root_cell->setFill(full_geometry); + + /* Create the geometry */ + log_printf(NORMAL, "Creating geometry..."); + Geometry geometry; + geometry.setRootUniverse(root_universe); + + /* Generate tracks */ + log_printf(NORMAL, "Initializing the track generator..."); + TrackGenerator track_generator(&geometry, num_azim, track_spacing); + track_generator.setNumThreads(num_threads); + track_generator.generateTracks(); + + /* Run simulation */ + CPUSolver solver(&track_generator); + solver.setNumThreads(num_threads); + solver.setConvergenceThreshold(tolerance); + solver.computeEigenvalue(max_iters); + solver.printTimerReport(); + + return 0; +} diff --git a/profile/models/gradients/one-directional/one-directional-gradient.cpp b/profile/models/gradients/one-directional/one-directional-gradient.cpp new file mode 100644 index 000000000..8773c8eaf --- /dev/null +++ b/profile/models/gradients/one-directional/one-directional-gradient.cpp @@ -0,0 +1,104 @@ +#include "../../../../src/CPUSolver.h" +#include "../../../../src/log.h" +#include +#include + +int main() { + + /* Define simulation parameters */ + #ifdef OPENMP + int num_threads = omp_get_num_procs(); + #else + int num_threads = 1; + #endif + double track_spacing = 0.1; + int num_azim = 4; + double tolerance = 1e-5; + int max_iters = 2000; + + /* Set logging information */ + set_log_level("NORMAL"); + log_printf(TITLE, "Simulating a one group homogeneous two directional" + " gradient..."); + + /* Create materials */ + log_printf(NORMAL, "Creating materials..."); + Material* basic_material = new Material(); + basic_material->setNumEnergyGroups(1); + double sigmaF[1] = {0.0414198575}; + double nuSigmaF[1] = {0.0994076580}; + double sigmaS[1] = {0.383259177}; + double chi[1] = {1.0}; + double sigmaT[1] = {0.452648699}; + basic_material->setSigmaF(sigmaF, 1); + basic_material->setNuSigmaF(nuSigmaF, 1); + basic_material->setSigmaS(sigmaS, 1); + basic_material->setChi(chi, 1); + basic_material->setSigmaT(sigmaT, 1); + + /* Create surfaces */ + log_printf(NORMAL, "Creating surfaces..."); + double L = 100.0; + XPlane left(-L/2); + XPlane right(L/2); + YPlane top(L/2); + YPlane bottom(-L/2); + + left.setBoundaryType(VACUUM); + right.setBoundaryType(REFLECTIVE); + top.setBoundaryType(REFLECTIVE); + bottom.setBoundaryType(REFLECTIVE); + + /* Create cells */ + log_printf(NORMAL, "Creating cells..."); + Cell* fill = new Cell(); + fill->setFill(basic_material); + + Cell* root_cell = new Cell(); + root_cell->addSurface(+1, &left); + root_cell->addSurface(-1, &right); + root_cell->addSurface(+1, &bottom); + root_cell->addSurface(-1, &top); + + /* Create universes */ + log_printf(NORMAL, "Creating universes..."); + Universe* fill_universe = new Universe(); + fill_universe->addCell(fill); + + Universe* root_universe = new Universe(); + root_universe->addCell(root_cell); + + /* Create lattice */ + log_printf(NORMAL, "Creating 100 x 1 lattice..."); + int num_cells_x = 100; + int num_cells_y = 1; + Lattice* lattice = new Lattice(); + lattice->setWidth(L/num_cells_x, L/num_cells_y); + + Universe** matrix = new Universe*[num_cells_x * num_cells_y]; + for (int j=0; jsetUniverses(1, num_cells_y, num_cells_x, matrix); + root_cell->setFill(lattice); + + /* Create the geometry */ + log_printf(NORMAL, "Creating geometry..."); + Geometry geometry; + geometry.setRootUniverse(root_universe); + + /* Generate tracks */ + log_printf(NORMAL, "Initializing the track generator..."); + TrackGenerator track_generator(&geometry, num_azim, track_spacing); + track_generator.setNumThreads(num_threads); + track_generator.generateTracks(); + + /* Run simulation */ + CPUSolver solver(&track_generator); + solver.setNumThreads(num_threads); + solver.setConvergenceThreshold(tolerance); + solver.computeEigenvalue(max_iters); + solver.printTimerReport(); + + return 0; +} diff --git a/profile/models/gradients/two-directional/two-directional-gradient.cpp b/profile/models/gradients/two-directional/two-directional-gradient.cpp new file mode 100644 index 000000000..68d981133 --- /dev/null +++ b/profile/models/gradients/two-directional/two-directional-gradient.cpp @@ -0,0 +1,104 @@ +#include "../../../../src/CPUSolver.h" +#include "../../../../src/log.h" +#include +#include + +int main() { + + /* Define simulation parameters */ + #ifdef OPENMP + int num_threads = omp_get_num_procs(); + #else + int num_threads = 1; + #endif + double track_spacing = 0.1; + int num_azim = 4; + double tolerance = 1e-5; + int max_iters = 1000; + + /* Set logging information */ + set_log_level("NORMAL"); + log_printf(TITLE, "Simulating a one group homogeneous two directional" + " gradient..."); + + /* Create materials */ + log_printf(NORMAL, "Creating materials..."); + Material* basic_material = new Material(); + basic_material->setNumEnergyGroups(1); + double sigmaF[1] = {0.0414198575}; + double nuSigmaF[1] = {0.0994076580}; + double sigmaS[1] = {0.383259177}; + double chi[1] = {1.0}; + double sigmaT[1] = {0.452648699}; + basic_material->setSigmaF(sigmaF, 1); + basic_material->setNuSigmaF(nuSigmaF, 1); + basic_material->setSigmaS(sigmaS, 1); + basic_material->setChi(chi, 1); + basic_material->setSigmaT(sigmaT, 1); + + /* Create surfaces */ + log_printf(NORMAL, "Creating surfaces..."); + double L = 100.0; + XPlane left(-L/2); + XPlane right(L/2); + YPlane top(L/2); + YPlane bottom(-L/2); + + left.setBoundaryType(VACUUM); + right.setBoundaryType(VACUUM); + top.setBoundaryType(REFLECTIVE); + bottom.setBoundaryType(REFLECTIVE); + + /* Create cells */ + log_printf(NORMAL, "Creating cells..."); + Cell* fill = new Cell(); + fill->setFill(basic_material); + + Cell* root_cell = new Cell(); + root_cell->addSurface(+1, &left); + root_cell->addSurface(-1, &right); + root_cell->addSurface(+1, &bottom); + root_cell->addSurface(-1, &top); + + /* Create universes */ + log_printf(NORMAL, "Creating universes..."); + Universe* fill_universe = new Universe(); + fill_universe->addCell(fill); + + Universe* root_universe = new Universe(); + root_universe->addCell(root_cell); + + /* Create lattice */ + log_printf(NORMAL, "Creating 100 x 1 lattice..."); + int num_cells_x = 100; + int num_cells_y = 1; + Lattice* lattice = new Lattice(); + lattice->setWidth(L/num_cells_x, L/num_cells_y); + + Universe** matrix = new Universe*[num_cells_x * num_cells_y]; + for (int j=0; jsetUniverses(1, num_cells_y, num_cells_x, matrix); + root_cell->setFill(lattice); + + /* Create the geometry */ + log_printf(NORMAL, "Creating geometry..."); + Geometry geometry; + geometry.setRootUniverse(root_universe); + + /* Generate tracks */ + log_printf(NORMAL, "Initializing the track generator..."); + TrackGenerator track_generator(&geometry, num_azim, track_spacing); + track_generator.setNumThreads(num_threads); + track_generator.generateTracks(); + + /* Run simulation */ + CPUSolver solver(&track_generator); + solver.setNumThreads(num_threads); + solver.setConvergenceThreshold(tolerance); + solver.computeEigenvalue(max_iters); + solver.printTimerReport(); + + return 0; +} diff --git a/profile/models/homogeneous/homogeneous-one-group.cpp b/profile/models/homogeneous/homogeneous-one-group.cpp new file mode 100644 index 000000000..85c3e5213 --- /dev/null +++ b/profile/models/homogeneous/homogeneous-one-group.cpp @@ -0,0 +1,87 @@ +#include "../../../src/CPUSolver.h" +#include "../../../src/log.h" +#include +#include + +int main() { + + /* Define simulation parameters */ + #ifdef OPENMP + int num_threads = omp_get_num_procs(); + #else + int num_threads = 1; + #endif + double track_spacing = 0.1; + int num_azim = 4; + double tolerance = 1e-5; + int max_iters = 1000; + + /* Set logging information */ + set_log_level("NORMAL"); + log_printf(TITLE, "Simulating a one group homogeneous infinite medium..."); + log_printf(HEADER, "The reference keff = 1.43..."); + + /* Create materials */ + log_printf(NORMAL, "Creating materials..."); + Material* infinite_medium = new Material(); + infinite_medium->setNumEnergyGroups(1); + double sigmaF[1] = {0.0414198575}; + double nuSigmaF[1] = {0.0994076580}; + double sigmaS[1] = {0.383259177}; + double chi[1] = {1.0}; + double sigmaT[1] = {0.452648699}; + infinite_medium->setSigmaF(sigmaF, 1); + infinite_medium->setNuSigmaF(nuSigmaF, 1); + infinite_medium->setSigmaS(sigmaS, 1); + infinite_medium->setChi(chi, 1); + infinite_medium->setSigmaT(sigmaT, 1); + + /* Create surfaces */ + log_printf(NORMAL, "Creating surfaces..."); + double L = 200.0; + XPlane left(-L/2); + XPlane right(L/2); + YPlane top(L/2); + YPlane bottom(-L/2); + + left.setBoundaryType(REFLECTIVE); + right.setBoundaryType(REFLECTIVE); + top.setBoundaryType(REFLECTIVE); + bottom.setBoundaryType(REFLECTIVE); + + /* Create cells */ + log_printf(NORMAL, "Creating cells..."); + + Cell* cell = new Cell(); + cell->setFill(infinite_medium); + cell->addSurface(+1, &left); + cell->addSurface(-1, &right); + cell->addSurface(+1, &bottom); + cell->addSurface(-1, &top); + + /* Create universes */ + log_printf(NORMAL, "Creating universes..."); + + Universe* root_universe = new Universe(); + root_universe->addCell(cell); + + /* Create the geometry */ + log_printf(NORMAL, "Creating geometry..."); + Geometry geometry; + geometry.setRootUniverse(root_universe); + + /* Generate tracks */ + log_printf(NORMAL, "Initializing the track generator..."); + TrackGenerator track_generator(&geometry, num_azim, track_spacing); + track_generator.setNumThreads(num_threads); + track_generator.generateTracks(); + + /* Run simulation */ + CPUSolver solver(&track_generator); + solver.setNumThreads(num_threads); + solver.setConvergenceThreshold(tolerance); + solver.computeEigenvalue(max_iters); + solver.printTimerReport(); + + return 0; +} diff --git a/sample-input/benchmarks/LRA/LRA-cmfd.py b/sample-input/benchmarks/LRA/LRA-cmfd.py index 5d5cc2972..ce2082a45 100644 --- a/sample-input/benchmarks/LRA/LRA-cmfd.py +++ b/sample-input/benchmarks/LRA/LRA-cmfd.py @@ -1,255 +1,71 @@ -from openmoc import * -import openmoc.log as log +import openmoc import openmoc.plotter as plotter -import openmoc.materialize as materialize from openmoc.options import Options - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating the LRA Benchmark Problem...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Importing materials data from py...') - -materials = materialize.materialize('LRA-materials.py') - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-82.5) -right = XPlane(x=82.5) -bottom = YPlane(y=-82.5) -top = YPlane(y=82.5) -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(VACUUM) -bottom.setBoundaryType(REFLECTIVE) -top.setBoundaryType(VACUUM) - +from lattices import universes ############################################################################### -###################### Creating Cells and Universes ####################### +# Main Simulation Parameters ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') - -# Region 1 -region1_cell = CellBasic(name='region 1') -region1_cell.setMaterial(materials['region_1']) -region1 = Universe(name='region 1') -region1.addCell(region1_cell) - -# Region 2 -region2_cell = CellBasic(name='region 2') -region2_cell.setMaterial(materials['region_2']) -region2 = Universe(name='region 2') -region2.addCell(region2_cell) - -# Region 3 -region3_cell = CellBasic(name='region 3') -region3_cell.setMaterial(materials['region_3']) -region3 = Universe(name='region 3') -region3.addCell(region3_cell) - -# Region 4 -region4_cell = CellBasic(name='region 4') -region4_cell.setMaterial(materials['region_4']) -region4 = Universe(name='region 4') -region4.addCell(region4_cell) - -# Region 5 -region5_cell = CellBasic(name='region 5') -region5_cell.setMaterial(materials['region_5']) -region5 = Universe(name='region 5') -region5.addCell(region5_cell) - -# Region 5 -region6_cell = CellBasic(name='region 6') -region6_cell.setMaterial(materials['region_6']) -region6 = Universe(name='region 6') -region6.addCell(region6_cell) - -# CellFills -assembly1_cell = CellFill(name='assembly 1') -assembly2_cell = CellFill(name='assembly 2') -assembly3_cell = CellFill(name='assembly 3') -assembly4_cell = CellFill(name='assembly 4') -assembly5_cell = CellFill(name='assembly 5') -assembly6_cell = CellFill(name='assembly 6') - -assembly1 = Universe(name='assembly 1') -assembly2 = Universe(name='assembly 2') -assembly3 = Universe(name='assembly 3') -assembly4 = Universe(name='assembly 4') -assembly5 = Universe(name='assembly 5') -assembly6 = Universe(name='assembly 6') - -assembly1.addCell(assembly1_cell) -assembly2.addCell(assembly2_cell) -assembly3.addCell(assembly3_cell) -assembly4.addCell(assembly4_cell) -assembly5.addCell(assembly5_cell) -assembly6.addCell(assembly6_cell) - -# Root cell/universe -root_cell = CellFill(name='root cell') -root_cell.addSurface(halfspace=+1, surface=left) -root_cell.addSurface(halfspace=-1, surface=right) -root_cell.addSurface(halfspace=+1, surface=bottom) -root_cell.addSurface(halfspace=-1, surface=top) - -root_universe = Universe(name='root universe') -root_universe.addCell(root_cell) +opts = Options() +openmoc.log.set_log_level('NORMAL') -############################################################################### -########################### Creating Lattices ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating LRA lattices...') - -# Assembly 1 -assembly1_lattice = Lattice(name='assembly 1') -assembly1_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region1] * 10] * 10 -assembly1_lattice.setUniverses(template) -assembly1_cell.setFill(assembly1_lattice) - -# Assembly 2 -assembly2_lattice = Lattice(name='assembly 2') -assembly2_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region2] * 10] * 10 -assembly2_lattice.setUniverses(template) -assembly2_cell.setFill(assembly2_lattice) - -# Assembly 3 -assembly3_lattice = Lattice(name='assembly 3') -assembly3_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region3] * 10] * 10 -assembly3_lattice.setUniverses(template) -assembly3_cell.setFill(assembly3_lattice) - -# Assembly 4 -assembly4_lattice = Lattice(name='assembly 4') -assembly4_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region4] * 10] * 10 -assembly4_lattice.setUniverses(template) -assembly4_cell.setFill(assembly4_lattice) - -# Assembly 5 -assembly5_lattice = Lattice(name='assembly 5') -assembly5_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region5] * 10] * 10 -assembly5_lattice.setUniverses(template) -assembly5_cell.setFill(assembly5_lattice) - -# Assembly 6 -assembly6_lattice = Lattice(name='assembly 6') -assembly6_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region6] * 10] * 10 -assembly6_lattice.setUniverses(template) -assembly6_cell.setFill(assembly6_lattice) - -# Full core -core_lattice = Lattice(name='core') -core_lattice.setWidth(width_x=15.0, width_y=15.0) - -universes = {7 : assembly1, 8 : assembly2, 9: assembly3, - 10 : assembly4, 11 : assembly5, 12 : assembly6} -template = [[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], - [12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], - [ 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12], - [ 9, 9, 9, 9, 9, 9, 9, 10, 12, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 9, 9, 12, 12]] - -for i in range(11): - for j in range(11): - template[i][j] = universes[template[i][j]] -core_lattice.setUniverses(template) -root_cell.setFill(core_lattice) - +openmoc.log.py_printf('TITLE', 'Simulating the LRA Benchmark Problem...') ############################################################################### ########################## Creating Cmfd mesh ########################## ############################################################################### -log.py_printf('NORMAL', 'Creating Cmfd mesh...') - -cmfd = Cmfd() -cmfd.setLatticeStructure(110,110) +cmfd = openmoc.Cmfd() +cmfd.setSORRelaxationFactor(1.5) +cmfd.setLatticeStructure(110, 110) +cmfd.setCentroidUpdateOn(False) ############################################################################### ########################## Creating the Geometry ########################## ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setCmfd(cmfd) -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() +geometry.setRootUniverse(universes['Root']) ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() + ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setSourceConvergenceThreshold(tolerance) -solver.setNumThreads(num_threads) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') - -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2]) -#plotter.plot_mesh_fluxes(mesh, energy_groups=[1,2]) -#plotter.plot_cmfd_cells(geometry, cmfd, gridsize=500) +openmoc.log.py_printf('NORMAL', 'Plotting data...') -log.py_printf('TITLE', 'Finished') +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2]) +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/LRA/LRA-materials-hdf5.py b/sample-input/benchmarks/LRA/LRA-materials-hdf5.py deleted file mode 100644 index 67e927ce2..000000000 --- a/sample-input/benchmarks/LRA/LRA-materials-hdf5.py +++ /dev/null @@ -1,172 +0,0 @@ -import h5py -import numpy - - -############################################################################### -# This file writes all of the materials data (multi-group nuclear -# cross-sections) for the LRA diffusion -# benchmark problem to an HDF5 file. The script uses the h5py Python package -# to interact with the HDF5 file format. This may be a good example for those -# wishing ot write their nuclear data to an HDF5 file to import using the -# OpenMOC 'materialize' Python module. -############################################################################### - - -# Create the file to store LRA multi-groups cross-sections -f = h5py.File('LRA-materials.h5') -f.attrs["Energy Groups"] = 2 - - -############################################################################### -################################ region 1 ################################ -############################################################################### - -# Create a subgroup for region 1 materials data -region_1 = f.create_group('region_1') - -sigma_t = numpy.array([0.2656, 1.5798]) -sigma_a = numpy.array([0.008252, 0.1003]) -sigma_s = numpy.array([0.2318925, 0.02533, 0.00, 1.4794789]) -sigma_f = numpy.array([0.002, 0.05]) -nu_sigma_f = numpy.array([0.004602, 0.1091]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.255, 0.211]) -buckle = numpy.array([1e-4, 1e-4]) - -region_1.create_dataset('Total XS', data=sigma_t) -region_1.create_dataset('Absorption XS', data=sigma_a) -region_1.create_dataset('Scattering XS', data=sigma_s) -region_1.create_dataset('Fission XS', data=sigma_f) -region_1.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_1.create_dataset('Chi', data=chi) -region_1.create_dataset('Diffusion Coefficient', data=dif_coef) -region_1.create_dataset('Buckling', data=buckle) - - -############################################################################### -################################ region 2 ################################ -############################################################################### - -# Create a subgroup for region 2 materials data -region_2 = f.create_group('region_2') - -sigma_t = numpy.array([0.2629, 1.7525]) -sigma_a = numpy.array([0.007181, 0.07047]) -sigma_s = numpy.array([0.2279222, 0.02767, 0.00, 1.68201098]) -sigma_f = numpy.array([0.002, 0.045]) -nu_sigma_f = numpy.array([0.004609, 0.08675]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.268, 0.1902]) -buckle = numpy.array([1e-4, 1e-4]) - -region_2.create_dataset('Total XS', data=sigma_t) -region_2.create_dataset('Absorption XS', data=sigma_a) -region_2.create_dataset('Scattering XS', data=sigma_s) -region_2.create_dataset('Fission XS', data=sigma_f) -region_2.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_2.create_dataset('Chi', data=chi) -region_2.create_dataset('Diffusion Coefficient', data=dif_coef) -region_2.create_dataset('Buckling', data=buckle) - -############################################################################### -################################ region 3 ################################ -############################################################################### - -# Create a subgroup for region 3 materials data -region_3 = f.create_group('region_3') - -sigma_t = numpy.array([0.2648, 1.5941]) -sigma_a = numpy.array([0.008002, 0.08344]) -sigma_s = numpy.array([0.2305021, 0.02617, 0.00, 1.51063909]) -sigma_f = numpy.array([0.002, 0.045]) -nu_sigma_f = numpy.array([0.004663, 0.1021]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.259, 0.2091]) -buckle = numpy.array([1e-4, 1e-4]) - -region_3.create_dataset('Total XS', data=sigma_t) -region_3.create_dataset('Absorption XS', data=sigma_a) -region_3.create_dataset('Scattering XS', data=sigma_s) -region_3.create_dataset('Fission XS', data=sigma_f) -region_3.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_3.create_dataset('Chi', data=chi) -region_3.create_dataset('Diffusion Coefficient', data=dif_coef) -region_3.create_dataset('Buckling', data=buckle) - -############################################################################### -################################ region 4 ################################ -############################################################################### - -# Create a subgroup for region 4 materials data -region_4 = f.create_group('region_4') - -sigma_t = numpy.array([0.2648, 1.5941]) -sigma_a = numpy.array([0.008002, 0.073324]) -sigma_s = numpy.array([0.230462, 0.02617, 0.00, 1.520789]) -sigma_f = numpy.array([0.002, 0.045]) -nu_sigma_f = numpy.array([0.004663, 0.1021]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.259, 0.2091]) -buckle = numpy.array([1e-4, 1e-4]) - -region_4.create_dataset('Total XS', data=sigma_t) -region_4.create_dataset('Absorption XS', data=sigma_a) -region_4.create_dataset('Scattering XS', data=sigma_s) -region_4.create_dataset('Fission XS', data=sigma_f) -region_4.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_4.create_dataset('Chi', data=chi) -region_4.create_dataset('Diffusion Coefficient', data=dif_coef) -region_4.create_dataset('Buckling', data=buckle) - -############################################################################### -################################ region 5 ################################ -############################################################################### - -# Create a subgroup for region 5 materials data -region_5 = f.create_group('region_5') - -sigma_t = numpy.array([0.2648, 1.5941]) -sigma_a = numpy.array([0.008002, 0.08344]) -sigma_s = numpy.array([0.230462, 0.02617, 0.00, 1.510672]) -sigma_f = numpy.array([0.002, 0.045]) -nu_sigma_f = numpy.array([0.004663, 0.1021]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.259, 0.2091]) -buckle = numpy.array([1e-4, 1e-4]) - -region_5.create_dataset('Total XS', data=sigma_t) -region_5.create_dataset('Absorption XS', data=sigma_a) -region_5.create_dataset('Scattering XS', data=sigma_s) -region_5.create_dataset('Fission XS', data=sigma_f) -region_5.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_5.create_dataset('Chi', data=chi) -region_5.create_dataset('Diffusion Coefficient', data=dif_coef) -region_5.create_dataset('Buckling', data=buckle) - -############################################################################### -################################ region 6 ################################ -############################################################################### - -# Create a subgroup for region 6 materials data -region_6 = f.create_group('region_6') - -sigma_t = numpy.array([0.2652, 2.0938]) -sigma_a = numpy.array([0.0006034, 0.01911]) -sigma_s = numpy.array([0.216931, 0.04754, 0.00, 2.074676]) -sigma_f = numpy.array([0.0, 0.0]) -nu_sigma_f = numpy.array([0.0, 0.0]) -chi = numpy.array([1.0, 0.0]) -dif_coef = numpy.array([1.257, 0.1592]) -buckle = numpy.array([1e-4, 1e-4]) - -region_6.create_dataset('Total XS', data=sigma_t) -region_6.create_dataset('Absorption XS', data=sigma_a) -region_6.create_dataset('Scattering XS', data=sigma_s) -region_6.create_dataset('Fission XS', data=sigma_f) -region_6.create_dataset('Nu Fission XS', data=nu_sigma_f) -region_6.create_dataset('Chi', data=chi) -region_6.create_dataset('Diffusion Coefficient', data=dif_coef) -region_6.create_dataset('Buckling', data=buckle) - -# Close the hdf5 data file -f.close() diff --git a/sample-input/benchmarks/LRA/LRA-materials.h5 b/sample-input/benchmarks/LRA/LRA-materials.h5 deleted file mode 100644 index 4a0265baf..000000000 Binary files a/sample-input/benchmarks/LRA/LRA-materials.h5 and /dev/null differ diff --git a/sample-input/benchmarks/LRA/LRA-materials.py b/sample-input/benchmarks/LRA/LRA-materials.py deleted file mode 100644 index 9e4332aed..000000000 --- a/sample-input/benchmarks/LRA/LRA-materials.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -This file writes all of the materials data (multi-group nuclear -cross-sections) for the LRA diffusion -benchmark problem to an HDF5 file. The script uses the h5py Python package -to interact with the HDF5 file format. This may be a good example for those -wishing ot write their nuclear data to an HDF5 file to import using the -OpenMOC 'materialize' Python module. -""" - - -# Create a Python dictionary to store LRA multi-group cross-sections -dataset = {} - -dataset['Energy Groups'] = 2 -dataset['Materials'] = {} - -lra_materials = dataset['Materials'] - -############################################################################### -################################ region 1 ################################ -############################################################################### - -# Create a subdictionary for region 1 material data -lra_materials['region_1'] = {} - -lra_materials['region_1']['Absorption XS'] = [0.008252, 0.1003] - -lra_materials['region_1']['Total XS'] = [0.2656, 1.5798] - -lra_materials['region_1']['Scattering XS'] = [0.231892, 0.02533, 0.00, 1.47948] - -lra_materials['region_1']['Fission XS'] = [0.002, 0.05] - -lra_materials['region_1']['Nu Fission XS'] = [0.004602, 0.1091] - -lra_materials['region_1']['Chi'] = [1.0, 0.0] - -lra_materials['region_1']['Diffusion Coefficient'] = [1.255, 0.211] - -lra_materials['region_1']['Buckling'] = [1e-4, 1e-4] - -############################################################################### -################################ region 2 ################################ -############################################################################### - -# Create a subdictionary for region 2 material data -lra_materials['region_2'] = {} - -lra_materials['region_2']['Absorption XS'] = [0.007181, 0.07047] - -lra_materials['region_2']['Total XS'] = [0.2629, 1.7525] - -lra_materials['region_2']['Scattering XS'] = [0.22792, 0.02767, 0.00, 1.68201] - -lra_materials['region_2']['Fission XS'] = [0.002, 0.045] - -lra_materials['region_2']['Nu Fission XS'] = [0.004609, 0.08675] - -lra_materials['region_2']['Chi'] = [1.0, 0.0] - -lra_materials['region_2']['Diffusion Coefficient'] = [1.268, 0.1902] - -lra_materials['region_2']['Buckling'] = [1e-4, 1e-4] - -############################################################################### -################################ region 3 ################################ -############################################################################### - -# Create a subdictionary for region 3 material data -lra_materials['region_3'] = {} - -lra_materials['region_3']['Absorption XS'] = [0.008002, 0.08344] - -lra_materials['region_3']['Total XS'] = [0.2648, 1.5941] - -lra_materials['region_3']['Scattering XS'] = [0.230502, 0.02617, 0.00, 1.510639] - -lra_materials['region_3']['Fission XS'] = [0.002, 0.045] - -lra_materials['region_3']['Nu Fission XS'] = [0.004663, 0.1021] - -lra_materials['region_3']['Chi'] = [1.0, 0.0] - -lra_materials['region_3']['Diffusion Coefficient'] = [1.259, 0.2091] - -lra_materials['region_3']['Buckling'] = [1e-4, 1e-4] - - -############################################################################### -################################ region 4 ################################ -############################################################################### - -# Create a subdictionary for region 4 material data -lra_materials['region_4'] = {} - -lra_materials['region_4']['Absorption XS'] = [0.008002, 0.073324] - -lra_materials['region_4']['Total XS'] = [0.2648, 1.5941] - -lra_materials['region_4']['Scattering XS'] = [0.230462, 0.02617, 0.00, 1.520789] - -lra_materials['region_4']['Fission XS'] = [0.002, 0.045] - -lra_materials['region_4']['Nu Fission XS'] = [0.004663, 0.1021] - -lra_materials['region_4']['Chi'] = [1.0, 0.0] - -lra_materials['region_4']['Diffusion Coefficient'] = [1.259, 0.2091] - -lra_materials['region_4']['Buckling'] = [1e-4, 1e-4] - -############################################################################### -################################ region 5 ################################ -############################################################################### - -# Create a subdictionary for region 5 material data -lra_materials['region_5'] = {} - -lra_materials['region_5']['Absorption XS'] = [0.008002, 0.08344] - -lra_materials['region_5']['Total XS'] = [0.2648, 1.5941] - -lra_materials['region_5']['Scattering XS'] = [0.230462, 0.02617, 0.00, 1.510672] - -lra_materials['region_5']['Fission XS'] = [0.002, 0.045] - -lra_materials['region_5']['Nu Fission XS'] = [0.004663, 0.1021] - -lra_materials['region_5']['Chi'] = [1.0, 0.0] - -lra_materials['region_5']['Diffusion Coefficient'] = [1.259, 0.2091] - -lra_materials['region_5']['Buckling'] = [1e-4, 1e-4] - -############################################################################### -################################ region 6 ################################ -############################################################################### - -# Create a subdictionary for region 6 material data -lra_materials['region_6'] = {} - -lra_materials['region_6']['Absorption XS'] = [0.0006034, 0.01911] - -lra_materials['region_6']['Total XS'] = [0.2652, 2.0938] - -lra_materials['region_6']['Scattering XS'] = [0.216931, 0.04754, 0.00, 2.074676] - -lra_materials['region_6']['Fission XS'] = [0.0, 0.0] - -lra_materials['region_6']['Nu Fission XS'] = [0.0, 0.0] - -lra_materials['region_6']['Chi'] = [1.0, 0.0] - -lra_materials['region_6']['Diffusion Coefficient'] = [1.257, 0.1592] - -lra_materials['region_6']['Buckling'] = [1e-4, 1e-4] diff --git a/sample-input/benchmarks/LRA/LRA-mgxs-hdf5.py b/sample-input/benchmarks/LRA/LRA-mgxs-hdf5.py new file mode 100644 index 000000000..c3340c0fe --- /dev/null +++ b/sample-input/benchmarks/LRA/LRA-mgxs-hdf5.py @@ -0,0 +1,125 @@ +import h5py +import numpy + + +############################################################################### +# This file writes all of the materials data (multi-group nuclear +# cross-sections) for the LRA diffusion +# benchmark problem to an HDF5 file. The script uses the h5py Python package +# to interact with the HDF5 file format. This may be a good example for those +# wishing ot write their nuclear data to an HDF5 file to import using the +# OpenMOC 'materialize' Python module. +############################################################################### + + +# Create the file to store LRA multi-groups cross-sections +f = h5py.File('LRA-mgxs.h5') +f.attrs["# groups"] = 2 + +# Create a group to specify that MGXS are split by material (vs. cell) +material_group = f.create_group('material') + +# The neutron multiplication factor for all fissionable materials +nu = 2.43 + +############################################################################### +################################ region 1 ################################ +############################################################################### + +# Create a subgroup for region 1 materials data +region_1 = material_group.create_group('Region 1') + +sigma_t = numpy.array([0.265604, 1.579779]) +sigma_s = numpy.array([0.232022, 0.02533, 0.00, 1.479479]) +sigma_f = numpy.array([0.004602, 0.1091]) / nu +nu_sigma_f = numpy.array([0.004602, 0.1091]) +chi = numpy.array([1.0, 0.0]) + +region_1.create_dataset('total', data=sigma_t) +region_1.create_dataset('scatter matrix', data=sigma_s) +region_1.create_dataset('fission', data=sigma_f) +region_1.create_dataset('nu-fission', data=nu_sigma_f) +region_1.create_dataset('chi', data=chi) + + +############################################################################### +################################ region 2 ################################ +############################################################################### + +# Create a subgroup for region 2 materials data +region_2 = material_group.create_group('Region 2') + +sigma_t = numpy.array([0.262881, 1.752541]) +sigma_s = numpy.array([0.228030, 0.02767, 0.00, 1.682071]) +sigma_f = numpy.array([0.004609, 0.08675]) / nu +nu_sigma_f = numpy.array([0.004609, 0.08675]) +chi = numpy.array([1.0, 0.0]) + +region_2.create_dataset('total', data=sigma_t) +region_2.create_dataset('scatter matrix', data=sigma_s) +region_2.create_dataset('fission', data=sigma_f) +region_2.create_dataset('nu-fission', data=nu_sigma_f) +region_2.create_dataset('chi', data=chi) + + +############################################################################### +################################ region 3 ################################ +############################################################################### + +# Create a subgroup for region 3 materials data +region_3 = material_group.create_group('Region 3') + +sigma_t = numpy.array([0.26476, 1.594134]) +sigma_s = numpy.array([0.230588, 0.02617, 0.00, 1.510694]) +sigma_f = numpy.array([0.004663, 0.1021]) / nu +nu_sigma_f = numpy.array([0.004663, 0.1021]) +chi = numpy.array([1.0, 0.0]) + +region_3.create_dataset('total', data=sigma_t) +region_3.create_dataset('scatter matrix', data=sigma_s) +region_3.create_dataset('fission', data=sigma_f) +region_3.create_dataset('nu-fission', data=nu_sigma_f) +region_3.create_dataset('chi', data=chi) + + +############################################################################### +################################ region 4 ################################ +############################################################################### + +# Create a subgroup for region 4 materials data +region_4 = material_group.create_group('Region 4') + +sigma_t = numpy.array([0.26476, 1.594134]) +sigma_s = numpy.array([0.230588, 0.02617, 0.00, 1.52081]) +sigma_f = numpy.array([0.004663, 0.1021]) / nu +nu_sigma_f = numpy.array([0.004663, 0.1021]) +chi = numpy.array([1.0, 0.0]) + +region_4.create_dataset('total', data=sigma_t) +region_4.create_dataset('scatter matrix', data=sigma_s) +region_4.create_dataset('fission', data=sigma_f) +region_4.create_dataset('nu-fission', data=nu_sigma_f) +region_4.create_dataset('chi', data=chi) + + +############################################################################### +################################ region 5 ################################ +############################################################################### + +# Create a subgroup for region 5 materials data +region_5 = material_group.create_group('Region 5') + +sigma_t = numpy.array([0.265182, 2.093802]) +sigma_s = numpy.array([0.217039, 0.04754, 0.00, 2.074692]) +sigma_f = numpy.array([0.0, 0.0]) +nu_sigma_f = numpy.array([0.0, 0.0]) +chi = numpy.array([1.0, 0.0]) + +region_5.create_dataset('total', data=sigma_t) +region_5.create_dataset('scatter matrix', data=sigma_s) +region_5.create_dataset('fission', data=sigma_f) +region_5.create_dataset('nu-fission', data=nu_sigma_f) +region_5.create_dataset('chi', data=chi) + +# Close the hdf5 data file +f.close() diff --git a/sample-input/benchmarks/LRA/LRA-mgxs.h5 b/sample-input/benchmarks/LRA/LRA-mgxs.h5 new file mode 100644 index 000000000..803f159d9 Binary files /dev/null and b/sample-input/benchmarks/LRA/LRA-mgxs.h5 differ diff --git a/sample-input/benchmarks/LRA/LRA.py b/sample-input/benchmarks/LRA/LRA.py index 49e2ca99c..df046d976 100644 --- a/sample-input/benchmarks/LRA/LRA.py +++ b/sample-input/benchmarks/LRA/LRA.py @@ -1,242 +1,60 @@ -from openmoc import * -import openmoc.log as log +import openmoc import openmoc.plotter as plotter -import openmoc.materialize as materialize from openmoc.options import Options - +from lattices import universes ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating the LRA Benchmark Problem...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Importing materials data from py...') - -materials = materialize.materialize('LRA-materials.py') - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-82.5) -right = XPlane(x=82.5) -bottom = YPlane(y=-82.5) -top = YPlane(y=82.5) -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(VACUUM) -bottom.setBoundaryType(REFLECTIVE) -top.setBoundaryType(VACUUM) - - -############################################################################### -###################### Creating Cells and Universes ####################### -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -# Region 1 -region1_cell = CellBasic(name='region 1') -region1_cell.setMaterial(materials['region_1']) -region1 = Universe(name='region 1') -region1.addCell(region1_cell) - -# Region 2 -region2_cell = CellBasic(name='region 2') -region2_cell.setMaterial(materials['region_2']) -region2 = Universe(name='region 2') -region2.addCell(region2_cell) - -# Region 3 -region3_cell = CellBasic(name='region 3') -region3_cell.setMaterial(materials['region_3']) -region3 = Universe(name='region 3') -region3.addCell(region3_cell) - -# Region 4 -region4_cell = CellBasic(name='region 4') -region4_cell.setMaterial(materials['region_4']) -region4 = Universe(name='region 4') -region4.addCell(region4_cell) - -# Region 5 -region5_cell = CellBasic(name='region 5') -region5_cell.setMaterial(materials['region_5']) -region5 = Universe(name='region 5') -region5.addCell(region5_cell) - -# Region 5 -region6_cell = CellBasic(name='region 6') -region6_cell.setMaterial(materials['region_6']) -region6 = Universe(name='region 6') -region6.addCell(region6_cell) - -# CellFills -assembly1_cell = CellFill(name='assembly 1') -assembly2_cell = CellFill(name='assembly 2') -assembly3_cell = CellFill(name='assembly 3') -assembly4_cell = CellFill(name='assembly 4') -assembly5_cell = CellFill(name='assembly 5') -assembly6_cell = CellFill(name='assembly 6') - -assembly1 = Universe(name='assembly 1') -assembly2 = Universe(name='assembly 2') -assembly3 = Universe(name='assembly 3') -assembly4 = Universe(name='assembly 4') -assembly5 = Universe(name='assembly 5') -assembly6 = Universe(name='assembly 6') - -assembly1.addCell(assembly1_cell) -assembly2.addCell(assembly2_cell) -assembly3.addCell(assembly3_cell) -assembly4.addCell(assembly4_cell) -assembly5.addCell(assembly5_cell) -assembly6.addCell(assembly6_cell) - -# Root cell/universe -root_cell = CellFill(name='root cell') -root_cell.addSurface(halfspace=+1, surface=left) -root_cell.addSurface(halfspace=-1, surface=right) -root_cell.addSurface(halfspace=+1, surface=bottom) -root_cell.addSurface(halfspace=-1, surface=top) - -root_universe = Universe(name='root universe') -root_universe.addCell(root_cell) - - -############################################################################### -########################### Creating Lattices ############################# -############################################################################### +opts = Options() -log.py_printf('NORMAL', 'Creating LRA lattices...') - -# Assembly 1 -assembly1_lattice = Lattice(name='assembly 1') -assembly1_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region1] * 10] * 10 -assembly1_lattice.setUniverses(template) -assembly1_cell.setFill(assembly1_lattice) - -# Assembly 2 -assembly2_lattice = Lattice(name='assembly 2') -assembly2_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region2] * 10] * 10 -assembly2_lattice.setUniverses(template) -assembly2_cell.setFill(assembly2_lattice) - -# Assembly 3 -assembly3_lattice = Lattice(name='assembly 3') -assembly3_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region3] * 10] * 10 -assembly3_lattice.setUniverses(template) -assembly3_cell.setFill(assembly3_lattice) - -# Assembly 4 -assembly4_lattice = Lattice(name='assembly 4') -assembly4_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region4] * 10] * 10 -assembly4_lattice.setUniverses(template) -assembly4_cell.setFill(assembly4_lattice) - -# Assembly 5 -assembly5_lattice = Lattice(name='assembly 5') -assembly5_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region5] * 10] * 10 -assembly5_lattice.setUniverses(template) -assembly5_cell.setFill(assembly5_lattice) - -# Assembly 6 -assembly6_lattice = Lattice(name='assembly 6') -assembly6_lattice.setWidth(width_x=1.5, width_y=1.5) -template = [[region6] * 10] * 10 -assembly6_lattice.setUniverses(template) -assembly6_cell.setFill(assembly6_lattice) - -# Full core -core_lattice = Lattice(name='core') -core_lattice.setWidth(width_x=15.0, width_y=15.0) - -universes = {7 : assembly1, 8 : assembly2, 9: assembly3, - 10 : assembly4, 11 : assembly5, 12 : assembly6} -template = [[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], - [12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], - [ 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12], - [ 9, 9, 9, 9, 9, 9, 9, 10, 12, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], - [ 8, 7, 7, 7, 7, 8, 8, 9, 9, 12, 12]] - -for i in range(11): - for j in range(11): - template[i][j] = universes[template[i][j]] -core_lattice.setUniverses(template) -root_cell.setFill(core_lattice) +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', 'Simulating the LRA Benchmark Problem...') ############################################################################### ########################## Creating the Geometry ########################## ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() +geometry = openmoc.Geometry() +geometry.setRootUniverse(universes['Root']) ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setSourceConvergenceThreshold(tolerance) -solver.setNumThreads(num_threads) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2]) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/LRA/cells.py b/sample-input/benchmarks/LRA/cells.py new file mode 100644 index 000000000..736f7389d --- /dev/null +++ b/sample-input/benchmarks/LRA/cells.py @@ -0,0 +1,41 @@ +import openmoc +from surfaces import surfaces +import openmoc.materialize as materialize + +############################################################################### +# Creating Materials +############################################################################### + +materials = openmoc.materialize.load_from_hdf5('LRA-mgxs.h5', './') + +############################################################################### +# Create dictionary of all cells +############################################################################### + +cells = {} + +# Instantiate Cells +cells['Region 1'] = openmoc.Cell(name='Region 1') +cells['Region 2'] = openmoc.Cell(name='Region 2') +cells['Region 3'] = openmoc.Cell(name='Region 3') +cells['Region 4'] = openmoc.Cell(name='Region 4') +cells['Region 5'] = openmoc.Cell(name='Region 5') +cells['Region 1 Assembly'] = openmoc.Cell(name='Region 1 Assembly') +cells['Region 2 Assembly'] = openmoc.Cell(name='Region 2 Assembly') +cells['Region 3 Assembly'] = openmoc.Cell(name='Region 3 Assembly') +cells['Region 4 Assembly'] = openmoc.Cell(name='Region 4 Assembly') +cells['Region 5 Assembly'] = openmoc.Cell(name='Region 5 Assembly') +cells['Root'] = openmoc.Cell(name='Root') + +# Register Materials with Cells +cells['Region 1'].setFill(materials['Region 1']) +cells['Region 2'].setFill(materials['Region 2']) +cells['Region 3'].setFill(materials['Region 3']) +cells['Region 4'].setFill(materials['Region 4']) +cells['Region 5'].setFill(materials['Region 5']) + +# Add surfaces to root cell +cells['Root'].addSurface(halfspace=+1, surface=surfaces['x-min']) +cells['Root'].addSurface(halfspace=-1, surface=surfaces['x-max']) +cells['Root'].addSurface(halfspace=+1, surface=surfaces['y-min']) +cells['Root'].addSurface(halfspace=-1, surface=surfaces['y-max']) diff --git a/sample-input/benchmarks/LRA/geometry.py b/sample-input/benchmarks/LRA/geometry.py new file mode 100644 index 000000000..c07cf192c --- /dev/null +++ b/sample-input/benchmarks/LRA/geometry.py @@ -0,0 +1,190 @@ +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('LRA-mgxs.h5', '') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-82.5) +right = openmoc.XPlane(x=82.5) +bottom = openmoc.YPlane(y=-82.5) +top = openmoc.YPlane(y=82.5) +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.VACUUM) +bottom.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.VACUUM) + + +############################################################################### +# Creating Cells and Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +# Region 1 +region1_cell = openmoc.Cell(name='region 1') +region1_cell.setFill(materials['region_1']) +region1 = openmoc.Universe(name='region 1') +region1.addCell(region1_cell) + +# Region 2 +region2_cell = openmoc.Cell(name='region 2') +region2_cell.setFill(materials['region_2']) +region2 = openmoc.Universe(name='region 2') +region2.addCell(region2_cell) + +# Region 3 +region3_cell = openmoc.Cell(name='region 3') +region3_cell.setFill(materials['region_3']) +region3 = openmoc.Universe(name='region 3') +region3.addCell(region3_cell) + +# Region 4 +region4_cell = openmoc.Cell(name='region 4') +region4_cell.setFill(materials['region_4']) +region4 = openmoc.Universe(name='region 4') +region4.addCell(region4_cell) + +# Region 5 +region5_cell = openmoc.Cell(name='region 5') +region5_cell.setFill(materials['region_5']) +region5 = openmoc.Universe(name='region 5') +region5.addCell(region5_cell) + +# Region 5 +region6_cell = openmoc.Cell(name='region 6') +region6_cell.setFill(materials['region_6']) +region6 = openmoc.Universe(name='region 6') +region6.addCell(region6_cell) + +# Cells +assembly1_cell = openmoc.Cell(name='assembly 1') +assembly2_cell = openmoc.Cell(name='assembly 2') +assembly3_cell = openmoc.Cell(name='assembly 3') +assembly4_cell = openmoc.Cell(name='assembly 4') +assembly5_cell = openmoc.Cell(name='assembly 5') +assembly6_cell = openmoc.Cell(name='assembly 6') + +assembly1 = openmoc.Universe(name='assembly 1') +assembly2 = openmoc.Universe(name='assembly 2') +assembly3 = openmoc.Universe(name='assembly 3') +assembly4 = openmoc.Universe(name='assembly 4') +assembly5 = openmoc.Universe(name='assembly 5') +assembly6 = openmoc.Universe(name='assembly 6') + +assembly1.addCell(assembly1_cell) +assembly2.addCell(assembly2_cell) +assembly3.addCell(assembly3_cell) +assembly4.addCell(assembly4_cell) +assembly5.addCell(assembly5_cell) +assembly6.addCell(assembly6_cell) + +# Root cell/universe +root_cell = openmoc.Cell(name='root cell') +root_cell.addSurface(halfspace=+1, surface=left) +root_cell.addSurface(halfspace=-1, surface=right) +root_cell.addSurface(halfspace=+1, surface=bottom) +root_cell.addSurface(halfspace=-1, surface=top) + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating LRA lattices...') + +# Assembly 1 +assembly1_lattice = openmoc.Lattice(name='assembly 1') +assembly1_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region1] * 10] * 10 +assembly1_lattice.setUniverses([template]) +assembly1_cell.setFill(assembly1_lattice) + +# Assembly 2 +assembly2_lattice = openmoc.Lattice(name='assembly 2') +assembly2_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region2] * 10] * 10 +assembly2_lattice.setUniverses([template]) +assembly2_cell.setFill(assembly2_lattice) + +# Assembly 3 +assembly3_lattice = openmoc.Lattice(name='assembly 3') +assembly3_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region3] * 10] * 10 +assembly3_lattice.setUniverses([template]) +assembly3_cell.setFill(assembly3_lattice) + +# Assembly 4 +assembly4_lattice = openmoc.Lattice(name='assembly 4') +assembly4_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region4] * 10] * 10 +assembly4_lattice.setUniverses([template]) +assembly4_cell.setFill(assembly4_lattice) + +# Assembly 5 +assembly5_lattice = openmoc.Lattice(name='assembly 5') +assembly5_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region5] * 10] * 10 +assembly5_lattice.setUniverses([template]) +assembly5_cell.setFill(assembly5_lattice) + +# Assembly 6 +assembly6_lattice = openmoc.Lattice(name='assembly 6') +assembly6_lattice.setWidth(width_x=1.5, width_y=1.5) +template = [[region6] * 10] * 10 +assembly6_lattice.setUniverses([template]) +assembly6_cell.setFill(assembly6_lattice) + +# Full core +core_lattice = openmoc.Lattice(name='core') +core_lattice.setWidth(width_x=15.0, width_y=15.0) + +universes = {7 : assembly1, 8 : assembly2, 9: assembly3, + 10 : assembly4, 11 : assembly5, 12 : assembly6} +template = [[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], + [12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12], + [ 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12], + [ 9, 9, 9, 9, 9, 9, 9, 10, 12, 12, 12], + [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], + [ 8, 7, 7, 7, 7, 8, 8, 11, 11, 12, 12], + [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], + [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], + [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], + [ 7, 7, 7, 7, 7, 7, 7, 9, 9, 12, 12], + [ 8, 7, 7, 7, 7, 8, 8, 9, 9, 12, 12]] + +for i in range(11): + for j in range(11): + template[i][j] = universes[template[i][j]] +core_lattice.setUniverses([template]) +root_cell.setFill(core_lattice) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) diff --git a/sample-input/benchmarks/LRA/lattices.py b/sample-input/benchmarks/LRA/lattices.py new file mode 100644 index 000000000..ffbab0182 --- /dev/null +++ b/sample-input/benchmarks/LRA/lattices.py @@ -0,0 +1,63 @@ +import openmoc +from universes import universes, cells + +############################################################################### +########################### Creating Lattices ############################# +############################################################################### + +# The number of uniform refinements to perform on the assembly lattices +refines = 10 + +lattices = {} + +# Instantiate Lattices +lattices['Region 1 Assembly'] = openmoc.Lattice() +lattices['Region 2 Assembly'] = openmoc.Lattice() +lattices['Region 3 Assembly'] = openmoc.Lattice() +lattices['Region 4 Assembly'] = openmoc.Lattice() +lattices['Region 5 Assembly'] = openmoc.Lattice() +lattices['Root'] = openmoc.Lattice() + +u1 = universes['Region 1'] +u2 = universes['Region 2'] +u3 = universes['Region 3'] +u4 = universes['Region 4'] +u5 = universes['Region 5'] + +lattices['Region 1 Assembly'].setWidth(15.0/refines, 15.0/refines) +lattices['Region 1 Assembly'].setUniverses([[[u1] * refines] * refines]) + +lattices['Region 2 Assembly'].setWidth(15.0/refines, 15.0/refines) +lattices['Region 2 Assembly'].setUniverses([[[u2] * refines] * refines]) + +lattices['Region 3 Assembly'].setWidth(15.0/refines, 15.0/refines) +lattices['Region 3 Assembly'].setUniverses([[[u3] * refines] * refines]) + +lattices['Region 4 Assembly'].setWidth(15.0/refines, 15.0/refines) +lattices['Region 4 Assembly'].setUniverses([[[u4] * refines] * refines]) + +lattices['Region 5 Assembly'].setWidth(15.0/refines, 15.0/refines) +lattices['Region 5 Assembly'].setUniverses([[[u5] * refines] * refines]) + +u1 = universes['Region 1 Assembly'] +u2 = universes['Region 2 Assembly'] +u3 = universes['Region 3 Assembly'] +u4 = universes['Region 4 Assembly'] +u5 = universes['Region 5 Assembly'] + +lattices['Root'].setWidth(15.0, 15.0) +template = [[u5] * 11] * 2 + \ + [[u3] * 7 + [u5] * 4] + \ + [[u3] * 7 + [u4] + [u5] * 3] + \ + [[u2] + [u1] * 4 + [u2] * 2 + [u3] * 2 + [u5] * 2] * 2 + \ + [[u1] * 7 + [u3] * 2 + [u5] * 2] * 4 + \ + [[u2] + [u1] * 4 + [u2] * 2 + [u3] * 2 + [u5] * 2] +lattices['Root'].setUniverses([template]) + +# Fill cells with lattices +cells['Region 1 Assembly'].setFill(lattices['Region 1 Assembly']) +cells['Region 2 Assembly'].setFill(lattices['Region 2 Assembly']) +cells['Region 3 Assembly'].setFill(lattices['Region 3 Assembly']) +cells['Region 4 Assembly'].setFill(lattices['Region 4 Assembly']) +cells['Region 5 Assembly'].setFill(lattices['Region 5 Assembly']) +cells['Root'].setFill(lattices['Root']) diff --git a/sample-input/benchmarks/LRA/surfaces.py b/sample-input/benchmarks/LRA/surfaces.py new file mode 100644 index 000000000..0d7376529 --- /dev/null +++ b/sample-input/benchmarks/LRA/surfaces.py @@ -0,0 +1,18 @@ +import openmoc + +############################################################################### +# Create dictionary of common surfaces +############################################################################### + +surfaces = {} + +# Instantiate surfaces +surfaces['x-min'] = openmoc.XPlane(x=-82.5, name='x-min') +surfaces['y-min'] = openmoc.YPlane(y=-82.5, name='y-min') +surfaces['x-max'] = openmoc.XPlane(x= 82.5, name='x-max') +surfaces['y-max'] = openmoc.YPlane(y= 82.5, name='y-max') + +surfaces['x-min'].setBoundaryType(openmoc.REFLECTIVE) +surfaces['y-min'].setBoundaryType(openmoc.REFLECTIVE) +surfaces['x-max'].setBoundaryType(openmoc.VACUUM) +surfaces['y-max'].setBoundaryType(openmoc.VACUUM) diff --git a/sample-input/benchmarks/LRA/universes.py b/sample-input/benchmarks/LRA/universes.py new file mode 100644 index 000000000..772b4e2e1 --- /dev/null +++ b/sample-input/benchmarks/LRA/universes.py @@ -0,0 +1,33 @@ +import openmoc +from cells import cells + +############################################################################### +# Creating Universes +############################################################################### + +universes = {} + +universes['Region 1'] = openmoc.Universe(name='Region 1') +universes['Region 2'] = openmoc.Universe(name='Region 2') +universes['Region 3'] = openmoc.Universe(name='Region 3') +universes['Region 4'] = openmoc.Universe(name='Region 4') +universes['Region 5'] = openmoc.Universe(name='Region 5') +universes['Region 1 Assembly'] = openmoc.Universe(name='Region 1 Assembly') +universes['Region 2 Assembly'] = openmoc.Universe(name='Region 2 Assembly') +universes['Region 3 Assembly'] = openmoc.Universe(name='Region 3 Assembly') +universes['Region 4 Assembly'] = openmoc.Universe(name='Region 4 Assembly') +universes['Region 5 Assembly'] = openmoc.Universe(name='Region 5 Assembly') +universes['Root'] = openmoc.Universe(name='Root') + +# Add cells to universes +universes['Region 1'] .addCell(cells['Region 1']) +universes['Region 2'] .addCell(cells['Region 2']) +universes['Region 3'] .addCell(cells['Region 3']) +universes['Region 4'] .addCell(cells['Region 4']) +universes['Region 5'] .addCell(cells['Region 5']) +universes['Region 1 Assembly'].addCell(cells['Region 1 Assembly']) +universes['Region 2 Assembly'].addCell(cells['Region 2 Assembly']) +universes['Region 3 Assembly'].addCell(cells['Region 3 Assembly']) +universes['Region 4 Assembly'].addCell(cells['Region 4 Assembly']) +universes['Region 5 Assembly'].addCell(cells['Region 5 Assembly']) +universes['Root'] .addCell(cells['Root']) diff --git a/sample-input/benchmarks/c5g7/c5g7-3d-rodded-B.py b/sample-input/benchmarks/c5g7/c5g7-3d-rodded-B.py new file mode 100644 index 000000000..868316e59 --- /dev/null +++ b/sample-input/benchmarks/c5g7/c5g7-3d-rodded-B.py @@ -0,0 +1,505 @@ +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', 'Simulating the OECD\'s C5G7 3D Rodded B' \ + ' Benchmark Problem...') + + +############################################################################### +########################### Creating Materials ############################ +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../../') + + +############################################################################### +########################### Creating Surfaces ############################# +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +xmin = openmoc.XPlane(x=-32.13, name='xmin') +xmax = openmoc.XPlane(x= 32.13, name='xmax') +ymin = openmoc.YPlane(y=-32.13, name='ymin') +ymax = openmoc.YPlane(y= 32.13, name='ymax') +zmin = openmoc.ZPlane(z=-32.13, name='zmin') +zmax = openmoc.ZPlane(z= 32.13, name='zmax') + +xmin.setBoundaryType(openmoc.REFLECTIVE) +xmax.setBoundaryType(openmoc.VACUUM) +ymin.setBoundaryType(openmoc.VACUUM) +ymax.setBoundaryType(openmoc.REFLECTIVE) + +# Create ZCylinders for the fuel as well as to discretize the moderator into +# rings +fuel_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.54) +moderator_inner_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.58) +moderator_outer_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.62) + + +############################################################################### +###################### Creating Cells and Universes ####################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +# Moderator rings +moderator_ring1 = openmoc.Cell() +moderator_ring2 = openmoc.Cell() +moderator_ring3 = openmoc.Cell() +moderator_ring1.setNumSectors(8) +moderator_ring2.setNumSectors(8) +moderator_ring3.setNumSectors(8) +moderator_ring1.setFill(materials['Water']) +moderator_ring2.setFill(materials['Water']) +moderator_ring3.setFill(materials['Water']) +moderator_ring1.addSurface(+1, fuel_radius) +moderator_ring1.addSurface(-1, moderator_inner_radius) +moderator_ring2.addSurface(+1, moderator_inner_radius) +moderator_ring2.addSurface(-1, moderator_outer_radius) +moderator_ring3.addSurface(+1, moderator_outer_radius) + +# UO2 pin cell +uo2_cell = openmoc.Cell() +uo2_cell.setNumRings(3) +uo2_cell.setNumSectors(8) +uo2_cell.setFill(materials['UO2']) +uo2_cell.addSurface(-1, fuel_radius) + +uo2 = openmoc.Universe(name='UO2') +uo2.addCell(uo2_cell) +uo2.addCell(moderator_ring1) +uo2.addCell(moderator_ring2) +uo2.addCell(moderator_ring3) + +# 4.3% MOX pin cell +mox43_cell = openmoc.Cell() +mox43_cell.setNumRings(3) +mox43_cell.setNumSectors(8) +mox43_cell.setFill(materials['MOX-4.3%']) +mox43_cell.addSurface(-1, fuel_radius) + +mox43 = openmoc.Universe(name='MOX-4.3%') +mox43.addCell(mox43_cell) +mox43.addCell(moderator_ring1) +mox43.addCell(moderator_ring2) +mox43.addCell(moderator_ring3) + +# 7% MOX pin cell +mox7_cell = openmoc.Cell() +mox7_cell.setNumRings(3) +mox7_cell.setNumSectors(8) +mox7_cell.setFill(materials['MOX-7%']) +mox7_cell.addSurface(-1, fuel_radius) + +mox7 = openmoc.Universe(name='MOX-7%') +mox7.addCell(mox7_cell) +mox7.addCell(moderator_ring1) +mox7.addCell(moderator_ring2) +mox7.addCell(moderator_ring3) + +# 8.7% MOX pin cell +mox87_cell = openmoc.Cell() +mox87_cell.setNumRings(3) +mox87_cell.setNumSectors(8) +mox87_cell.setFill(materials['MOX-8.7%']) +mox87_cell.addSurface(-1, fuel_radius) + +mox87 = openmoc.Universe(name='MOX-8.7%') +mox87.addCell(mox87_cell) +mox87.addCell(moderator_ring1) +mox87.addCell(moderator_ring2) +mox87.addCell(moderator_ring3) + +# Fission chamber pin cell +fission_chamber_cell = openmoc.Cell() +fission_chamber_cell.setNumRings(3) +fission_chamber_cell.setNumSectors(8) +fission_chamber_cell.setFill(materials['Fission Chamber']) +fission_chamber_cell.addSurface(-1, fuel_radius) + +fission_chamber = openmoc.Universe(name='Fission Chamber') +fission_chamber.addCell(fission_chamber_cell) +fission_chamber.addCell(moderator_ring1) +fission_chamber.addCell(moderator_ring2) +fission_chamber.addCell(moderator_ring3) + +# Guide tube pin cell +guide_tube_cell = openmoc.Cell() +guide_tube_cell.setNumRings(3) +guide_tube_cell.setNumSectors(8) +guide_tube_cell.setFill(materials['Guide Tube']) +guide_tube_cell.addSurface(-1, fuel_radius) + +guide_tube = openmoc.Universe(name='Guide Tube') +guide_tube.addCell(guide_tube_cell) +guide_tube.addCell(moderator_ring1) +guide_tube.addCell(moderator_ring2) +guide_tube.addCell(moderator_ring3) + +# Control rod pin cell +control_rod_cell = openmoc.Cell() +control_rod_cell.setNumRings(3) +control_rod_cell.setNumSectors(8) +control_rod_cell.setFill(materials['Control Rod']) +control_rod_cell.addSurface(-1, fuel_radius) + +control_rod = openmoc.Universe(name='Control Rod') +control_rod.addCell(control_rod_cell) +control_rod.addCell(moderator_ring1) +control_rod.addCell(moderator_ring2) +control_rod.addCell(moderator_ring3) + +# Reflector Cells +reflector_cell = openmoc.Cell(name='moderator') +reflector_cell.setFill(materials['Water']) + +reflector = openmoc.Universe(name='Reflector') +reflector.addCell(reflector_cell) + +refined_reflector_cell = openmoc.Cell(name='Semi-Finely Spaced Reflector') +refined_reflector = openmoc.Universe(name='Semi-Finely Spaced Moderator') +refined_reflector.addCell(refined_reflector_cell) + +# Lattice-filled Cells for the assemblies +assembly_uo2_unrod_cell = openmoc.Cell(name='UO2 Assembly Unrodded') +assembly_mox_unrod_cell = openmoc.Cell(name='MOX Assembly Unrodded') +assembly_rfl_unrod_cell_rgt = openmoc.Cell(name='Reflector Unrodded Right') +assembly_rfl_unrod_cell_btm = openmoc.Cell(name='Reflector Unrodded Bottom') +assembly_rfl_unrod_cell_cnr = openmoc.Cell(name='Reflector Unrodded Corner') +assembly_uo2_rod_cell = openmoc.Cell(name='UO2 Assembly Unrodded') +assembly_mox_rod_cell = openmoc.Cell(name='MOX Assembly Unrodded') +assembly_rfl_rod_cell = openmoc.Cell(name='Reflector Rodded') +assembly_rfl_unrod_cell = openmoc.Cell(name='Reflector Unrodded') + +# Assembly Universes +assembly_uo2_unrod = openmoc.Universe(name='UO2 Assembly Unrodded') +assembly_mox_unrod = openmoc.Universe(name='MOX Assembly Unrodded') +assembly_rfl_unrod_rgt = openmoc.Universe(name='Rfl Assembly Unrodded Right') +assembly_rfl_unrod_btm = openmoc.Universe(name='Rfl Assembly Unrodded Bottom') +assembly_rfl_unrod_cnr = openmoc.Universe(name='Rfl Assembly Unrodded Corner') +assembly_uo2_rod = openmoc.Universe(name='UO2 Assembly Unrodded') +assembly_mox_rod = openmoc.Universe(name='MOX Assembly Unrodded') +assembly_rfl_rod = openmoc.Universe(name='Rfl Assembly Rodded') +assembly_rfl_unrod = openmoc.Universe(name='Rfl Assembly Unrodded') + +assembly_uo2_unrod.addCell(assembly_uo2_unrod_cell) +assembly_mox_unrod.addCell(assembly_mox_unrod_cell) +assembly_rfl_unrod_rgt.addCell(assembly_rfl_unrod_cell_rgt) +assembly_rfl_unrod_btm.addCell(assembly_rfl_unrod_cell_btm) +assembly_rfl_unrod_cnr.addCell(assembly_rfl_unrod_cell_cnr) +assembly_uo2_rod.addCell(assembly_uo2_rod_cell) +assembly_mox_rod.addCell(assembly_mox_rod_cell) +assembly_rfl_rod.addCell(assembly_rfl_rod_cell) +assembly_rfl_unrod.addCell(assembly_rfl_unrod_cell) + +# Root Cell/Universe +root_cell = openmoc.Cell(name='Full Geometry') +root_cell.addSurface(halfspace=+1, surface=xmin) +root_cell.addSurface(halfspace=-1, surface=xmax) +root_cell.addSurface(halfspace=+1, surface=ymin) +root_cell.addSurface(halfspace=-1, surface=ymax) +root_cell.addSurface(halfspace=+1, surface=zmin) +root_cell.addSurface(halfspace=-1, surface=zmax) + +root_universe = openmoc.Universe(name='Root Universe') +root_universe.addCell(root_cell) + + +############################################################################### +########################### Creating Lattices ############################# +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating lattices...') + +lattices = list() + +# Sliced up water cells - semi finely spaced +lattices.append(openmoc.Lattice(name='Semi-Finely Spaced Reflector')) +lattices[-1].setWidth(width_x=0.126, width_y=0.126) +template = [[reflector] * 10] * 10 +lattices[-1].setUniverses([template]) +refined_reflector_cell.setFill(lattices[-1]) + + +# UO2 unrodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly UO2 Unrodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + + +universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + +lattices[-1].setUniverses([template]) +assembly_uo2_unrod_cell.setFill(lattices[-1]) + + +# UO2 rodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly UO2 Rodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + + +universes = {1 : uo2, 2 : control_rod, 3 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + +lattices[-1].setUniverses([template]) +assembly_uo2_rod_cell.setFill(lattices[-1]) + + +# MOX unrodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly MOX Unrodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + +universes = {1 : mox43, 2 : mox7, 3 : mox87, + 4 : guide_tube, 5 : fission_chamber} + +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + +lattices[-1].setUniverses([template]) +assembly_mox_unrod_cell.setFill(lattices[-1]) + + +# MOX rodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly MOX Rodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + +universes = {1 : mox43, 2 : mox7, 3 : mox87, + 4 : control_rod, 5 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + +lattices[-1].setUniverses([template]) +assembly_mox_rod_cell.setFill(lattices[-1]) + + +# Reflector rodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly Reflector Rodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + + +universes = {1 : reflector, 2 : control_rod, 3 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + +lattices[-1].setUniverses([template]) +assembly_rfl_rod_cell.setFill(lattices[-1]) + +# Reflector unrodded 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly Reflector Unrodded')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 17] * 17 +lattices[-1].setUniverses([template]) +assembly_rfl_unrod_cell.setFill(lattices[-1]) + +# Reflector unrodded assembly right +lattices.append(openmoc.Lattice(name='Assembly Reflector Unrodded Right')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 11 + [reflector] * 6] * 17 +lattices[-1].setUniverses([template]) +assembly_rfl_unrod_cell_rgt.setFill(lattices[-1]) + +# Reflector unrodded assembly bottom +lattices.append(openmoc.Lattice(name='Assembly Reflector Unrodded Bottom')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 17] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +assembly_rfl_unrod_cell_btm.setFill(lattices[-1]) + +# Reflector unrodded assembly bottom +lattices.append(openmoc.Lattice(name='Assembly Reflector Unrodded Corner')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 11 + [reflector] * 6] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +assembly_rfl_unrod_cell_cnr.setFill(lattices[-1]) + + +############################################################################### +######################### Creating Core Lattice ########################### +############################################################################### + +# 3 x 3 x 9 core to represent 3D core +lattices.append(openmoc.Lattice(name='Full Geometry')) +lattices[-1].setWidth(width_x=21.42, width_y=21.42, width_z=7.14) +lattices[-1].setUniverses( + [[[assembly_rfl_rod , assembly_rfl_rod , assembly_rfl_unrod_rgt], + [assembly_rfl_rod , assembly_rfl_rod , assembly_rfl_unrod_rgt], + [assembly_rfl_unrod_btm, assembly_rfl_unrod_btm, assembly_rfl_unrod_cnr]]]*3+ + [[[assembly_uo2_rod , assembly_mox_rod , assembly_rfl_unrod_rgt], + [assembly_mox_rod , assembly_uo2_unrod , assembly_rfl_unrod_rgt], + [assembly_rfl_unrod_btm, assembly_rfl_unrod_btm, assembly_rfl_unrod_cnr]]]*2+ + [[[assembly_uo2_rod , assembly_mox_unrod , assembly_rfl_unrod_rgt], + [assembly_mox_unrod , assembly_uo2_unrod , assembly_rfl_unrod_rgt], + [assembly_rfl_unrod_btm, assembly_rfl_unrod_btm, assembly_rfl_unrod_cnr]]]*2+ + [[[assembly_uo2_unrod , assembly_mox_unrod , assembly_rfl_unrod_rgt], + [assembly_mox_unrod , assembly_uo2_unrod , assembly_rfl_unrod_rgt], + [assembly_rfl_unrod_btm, assembly_rfl_unrod_btm, assembly_rfl_unrod_cnr]]]*2) + +# Fill root cell with lattice +root_cell.setFill(lattices[-1]) + + +############################################################################### +########################## Creating Cmfd mesh ########################## +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating Cmfd mesh...') + +cmfd = openmoc.Cmfd() +cmfd.setSORRelaxationFactor(1.0) +cmfd.setLatticeStructure(51,51) +cmfd.setGroupStructure([1,4,8]) + + +############################################################################### +########################## Creating the Geometry ########################## +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) +geometry.setCmfd(cmfd) + + +############################################################################### +######################## Creating the TrackGenerator ###################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setZCoord(-20.0) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +########################### Running a Simulation ########################## +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) +solver.computeEigenvalue(opts.max_iters) +solver.printTimerReport() + + +############################################################################### +############################ Generating Plots ############################# +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry) +openmoc.plotter.plot_cells(geometry) +openmoc.plotter.plot_cmfd_cells(geometry, cmfd) +openmoc.plotter.plot_flat_source_regions(geometry) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_fission_rates(solver) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/c5g7/c5g7-cmfd.py b/sample-input/benchmarks/c5g7/c5g7-cmfd.py index dd371b5a0..b3bcdf896 100644 --- a/sample-input/benchmarks/c5g7/c5g7-cmfd.py +++ b/sample-input/benchmarks/c5g7/c5g7-cmfd.py @@ -1,345 +1,67 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.process as process -import openmoc.materialize as materialize -from openmoc.options import Options -import openmoc.process as process +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() +opts = openmoc.options.Options() -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +openmoc.log.set_log_level('NORMAL') -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating the OECD\'s C5G7 Benchmark Problem...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Importing materials data from py...') - -materials = materialize.materialize('../../c5g7-materials.h5') - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-32.13, name='left') -right = XPlane(x=32.13, name='right') -top = YPlane(y=32.13, name='top') -bottom = YPlane(y=-32.13, name='bottom') -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(VACUUM) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(VACUUM) -boundaries = [left, right, top, bottom] - -# Create Circles for the fuel as well as to discretize the moderator into rings -fuel_radius = Circle(x=0.0, y=0.0, radius=0.54) -moderator_inner_radius = Circle(x=0.0, y=0.0, radius=0.62) -moderator_outer_radius = Circle(x=0.0, y=0.0, radius=0.58) - - -############################################################################### -###################### Creating Cells and Universes ####################### -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -# Moderator rings -moderator_ring1 = CellBasic(sectors=8) -moderator_ring2 = CellBasic(sectors=8) -moderator_ring3 = CellBasic(sectors=8) -moderator_ring1.setMaterial(materials['Water']) -moderator_ring2.setMaterial(materials['Water']) -moderator_ring3.setMaterial(materials['Water']) -moderator_ring1.addSurface(+1, fuel_radius) -moderator_ring1.addSurface(-1, moderator_inner_radius) -moderator_ring2.addSurface(+1, moderator_inner_radius) -moderator_ring2.addSurface(-1, moderator_outer_radius) -moderator_ring3.addSurface(+1, moderator_outer_radius) - -# UO2 pin cell -uo2_cell = CellBasic(rings=3, sectors=8) -uo2_cell.setMaterial(materials['UO2']) -uo2_cell.addSurface(-1, fuel_radius) - -uo2 = Universe(name='UO2') -uo2.addCell(uo2_cell) -uo2.addCell(moderator_ring1) -uo2.addCell(moderator_ring2) -uo2.addCell(moderator_ring3) - -# 4.3% MOX pin cell -mox43_cell = CellBasic(rings=3, sectors=8) -mox43_cell.setMaterial(materials['MOX-4.3%']) -mox43_cell.addSurface(-1, fuel_radius) - -mox43 = Universe(name='MOX-4.3%') -mox43.addCell(mox43_cell) -mox43.addCell(moderator_ring1) -mox43.addCell(moderator_ring2) -mox43.addCell(moderator_ring3) - -# 7% MOX pin cell -mox7_cell = CellBasic(rings=3, sectors=8) -mox7_cell.setMaterial(materials['MOX-7%']) -mox7_cell.addSurface(-1, fuel_radius) - -mox7 = Universe(name='MOX-7%') -mox7.addCell(mox7_cell) -mox7.addCell(moderator_ring1) -mox7.addCell(moderator_ring2) -mox7.addCell(moderator_ring3) - -# 8.7% MOX pin cell -mox87_cell = CellBasic(rings=3, sectors=8) -mox87_cell.setMaterial(materials['MOX-8.7%']) -mox87_cell.addSurface(-1, fuel_radius) - -mox87 = Universe(name='MOX-8.7%') -mox87.addCell(mox87_cell) -mox87.addCell(moderator_ring1) -mox87.addCell(moderator_ring2) -mox87.addCell(moderator_ring3) - -# Fission chamber pin cell -fission_chamber_cell = CellBasic(rings=3, sectors=8) -fission_chamber_cell.setMaterial(materials['Fission Chamber']) -fission_chamber_cell.addSurface(-1, fuel_radius) - -fission_chamber = Universe(name='Fission Chamber') -fission_chamber.addCell(fission_chamber_cell) -fission_chamber.addCell(moderator_ring1) -fission_chamber.addCell(moderator_ring2) -fission_chamber.addCell(moderator_ring3) - -# Guide tube pin cell -guide_tube_cell = CellBasic(rings=3, sectors=8) -guide_tube_cell.setMaterial(materials['Guide Tube']) -guide_tube_cell.addSurface(-1, fuel_radius) - -guide_tube = Universe(name='Guide Tube') -guide_tube.addCell(guide_tube_cell) -guide_tube.addCell(moderator_ring1) -guide_tube.addCell(moderator_ring2) -guide_tube.addCell(moderator_ring3) - -# Reflector -reflector_cell = CellBasic(name='moderator') -reflector_cell.setMaterial(materials['Water']) - -reflector = Universe(name='Reflector') -reflector.addCell(reflector_cell) - -# CellFills -assembly1_cell = CellFill(name='Assembly 1') -assembly2_cell = CellFill(name='Assembly 2') -refined_reflector_cell = CellFill(name='Semi-Finely Spaced Reflector') -right_reflector_cell = CellFill(name='Right Reflector') -corner_reflector_cell = CellFill(name='Bottom Corner Reflector') -bottom_reflector_cell = CellFill(name='Bottom Reflector') - -assembly1 = Universe(name='Assembly 1') -assembly2 = Universe(name='Assembly 2') -refined_reflector = Universe(name='Semi-Finely Spaced Moderator') -right_reflector = Universe(name='Right Reflector') -corner_reflector = Universe(name='Bottom Corner Reflector') -bottom_reflector = Universe(name='Bottom Reflector') - -assembly1.addCell(assembly1_cell) -assembly2.addCell(assembly2_cell) -refined_reflector.addCell(refined_reflector_cell) -right_reflector.addCell(right_reflector_cell) -corner_reflector.addCell(corner_reflector_cell) -bottom_reflector.addCell(bottom_reflector_cell) - -# Root Cell/Universe -root_cell = CellFill(name='Full Geometry') -root_cell.addSurface(+1, boundaries[0]) -root_cell.addSurface(-1, boundaries[1]) -root_cell.addSurface(-1, boundaries[2]) -root_cell.addSurface(+1, boundaries[3]) - -root_universe = Universe(name='Root Universe') -root_universe.addCell(root_cell) - - -############################################################################### -########################### Creating Lattices ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating lattices...') - -lattices = list() - -# Top left, bottom right 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 1')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - -universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly1_cell.setFill(lattices[-1]) - -# Top right, bottom left 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 2')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] -universes = {1 : mox43, 2 : mox7, 3 : mox87, - 4 : guide_tube, 5 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly2_cell.setFill(lattices[-1]) - -# Sliced up water cells - semi finely spaced -lattices.append(Lattice(name='Semi-Finely Spaced Reflector')) -lattices[-1].setWidth(width_x=0.126, width_y=0.126) -template = [[reflector] * 10] * 10 -lattices[-1].setUniverses(template) -refined_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells - right side of geometry -lattices.append(Lattice(name='Right Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 17 -lattices[-1].setUniverses(template) -right_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom corner of geometry -lattices.append(Lattice(name='Bottom Corner Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -corner_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom of geometry -lattices.append(Lattice(name='Bottom Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 17] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -bottom_reflector_cell.setFill(lattices[-1]) - -# 4 x 4 core to represent two bundles and water -lattices.append(Lattice(name='Full Geometry')) -lattices[-1].setWidth(width_x=21.42, width_y=21.42) -lattices[-1].setUniverses([ - [assembly1, assembly2, right_reflector], - [assembly2, assembly1, right_reflector], - [bottom_reflector, bottom_reflector, corner_reflector]]) -root_cell.setFill(lattices[-1]) +openmoc.log.py_printf('TITLE', \ + 'Simulating the OECD\'s C5G7 Benchmark Problem...') ############################################################################### -########################## Creating Cmfd mesh ########################## +# Creating Cmfd mesh ############################################################################### -log.py_printf('NORMAL', 'Creating Cmfd mesh...') +openmoc.log.py_printf('NORMAL', 'Creating Cmfd mesh...') -cmfd = Cmfd() -cmfd.setMOCRelaxationFactor(0.6) +cmfd = openmoc.Cmfd() cmfd.setSORRelaxationFactor(1.5) cmfd.setLatticeStructure(51,51) cmfd.setGroupStructure([1,4,8]) +cmfd.setKNearest(3) - -############################################################################### -########################## Creating the Geometry ########################## -############################################################################### - -log.py_printf('NORMAL', 'Creating geometry...') - -geometry = Geometry() -geometry.setRootUniverse(root_universe) +from geometry import geometry geometry.setCmfd(cmfd) -geometry.initializeFlatSourceRegions() ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() + ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setSourceConvergenceThreshold(tolerance) -solver.setNumThreads(num_threads) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() + ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_materials(geometry, gridsize=250) -#plotter.plot_cells(geometry, gridsize=250) -#plotter.plot_cmfd_cells(geometry, cmfd, gridsize=250) -#plotter.plot_flat_source_regions(geometry, gridsize=250) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) -#plotter.plot_fission_rates(geometry, solver, gridsize=250) +openmoc.plotter.plot_materials(geometry, gridsize=250) +openmoc.plotter.plot_cells(geometry, gridsize=250) +openmoc.plotter.plot_cmfd_cells(geometry, cmfd, gridsize=250) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=250) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_fission_rates(solver, gridsize=250, norm=True) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/c5g7/c5g7-gpu.py b/sample-input/benchmarks/c5g7/c5g7-gpu.py index cb9f6a647..c94f4f8d5 100644 --- a/sample-input/benchmarks/c5g7/c5g7-gpu.py +++ b/sample-input/benchmarks/c5g7/c5g7-gpu.py @@ -1,329 +1,49 @@ -from openmoc import * +import openmoc from openmoc.cuda import GPUSolver -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating the OECD\'s C5G7 Benchmark Problem...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Importing materials data from HDF5...') - -materials = materialize.materialize('../../c5g7-materials.h5') - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-32.13, name='left') -right = XPlane(x=32.13, name='right') -top = YPlane(y=32.13, name='top') -bottom = YPlane(y=-32.13, name='bottom') -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(VACUUM) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(VACUUM) -boundaries = [left, right, top, bottom] - -# Create Circles for the fuel as well as to discretize the moderator into rings -fuel_radius = Circle(x=0.0, y=0.0, radius=0.54) -moderator_inner_radius = Circle(x=0.0, y=0.0, radius=0.62) -moderator_outer_radius = Circle(x=0.0, y=0.0, radius=0.58) - - -############################################################################### -###################### Creating Cells and Universes ####################### -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -# Moderator rings -moderator_ring1 = CellBasic(sectors=8) -moderator_ring2 = CellBasic(sectors=8) -moderator_ring3 = CellBasic(sectors=8) -moderator_ring1.setMaterial(materials['Water']) -moderator_ring2.setMaterial(materials['Water']) -moderator_ring3.setMaterial(materials['Water']) -moderator_ring1.addSurface(+1, fuel_radius) -moderator_ring1.addSurface(-1, moderator_inner_radius) -moderator_ring2.addSurface(+1, moderator_inner_radius) -moderator_ring2.addSurface(-1, moderator_outer_radius) -moderator_ring3.addSurface(+1, moderator_outer_radius) - -# UO2 pin cell -uo2_cell = CellBasic(rings=3, sectors=8) -uo2_cell.setMaterial(materials['UO2']) -uo2_cell.addSurface(-1, fuel_radius) - -uo2 = Universe(name='UO2') -uo2.addCell(uo2_cell) -uo2.addCell(moderator_ring1) -uo2.addCell(moderator_ring2) -uo2.addCell(moderator_ring3) - -# 4.3% MOX pin cell -mox43_cell = CellBasic(rings=3, sectors=8) -mox43_cell.setMaterial(materials['MOX-4.3%']) -mox43_cell.addSurface(-1, fuel_radius) - -mox43 = Universe(name='MOX-4.3%') -mox43.addCell(mox43_cell) -mox43.addCell(moderator_ring1) -mox43.addCell(moderator_ring2) -mox43.addCell(moderator_ring3) - -# 7% MOX pin cell -mox7_cell = CellBasic(rings=3, sectors=8) -mox7_cell.setMaterial(materials['MOX-7%']) -mox7_cell.addSurface(-1, fuel_radius) - -mox7 = Universe(name='MOX-7%') -mox7.addCell(mox7_cell) -mox7.addCell(moderator_ring1) -mox7.addCell(moderator_ring2) -mox7.addCell(moderator_ring3) - -# 8.7% MOX pin cell -mox87_cell = CellBasic(rings=3, sectors=8) -mox87_cell.setMaterial(materials['MOX-8.7%']) -mox87_cell.addSurface(-1, fuel_radius) - -mox87 = Universe(name='MOX-8.7%') -mox87.addCell(mox87_cell) -mox87.addCell(moderator_ring1) -mox87.addCell(moderator_ring2) -mox87.addCell(moderator_ring3) - -# Fission chamber pin cell -fission_chamber_cell = CellBasic(rings=3, sectors=8) -fission_chamber_cell.setMaterial(materials['Fission Chamber']) -fission_chamber_cell.addSurface(-1, fuel_radius) - -fission_chamber = Universe(name='Fission Chamber') -fission_chamber.addCell(fission_chamber_cell) -fission_chamber.addCell(moderator_ring1) -fission_chamber.addCell(moderator_ring2) -fission_chamber.addCell(moderator_ring3) - -# Guide tube pin cell -guide_tube_cell = CellBasic(rings=3, sectors=8) -guide_tube_cell.setMaterial(materials['Guide Tube']) -guide_tube_cell.addSurface(-1, fuel_radius) - -guide_tube = Universe(name='Guide Tube') -guide_tube.addCell(guide_tube_cell) -guide_tube.addCell(moderator_ring1) -guide_tube.addCell(moderator_ring2) -guide_tube.addCell(moderator_ring3) - -# Reflector -reflector_cell = CellBasic(name='moderator') -reflector_cell.setMaterial(materials['Water']) - -reflector = Universe(name='Reflector') -reflector.addCell(reflector_cell) - -# CellFills -assembly1_cell = CellFill(name='Assembly 1') -assembly2_cell = CellFill(name='Assembly 2') -refined_reflector_cell = CellFill(name='Semi-Finely Spaced Reflector') -right_reflector_cell = CellFill(name='Right Reflector') -corner_reflector_cell = CellFill(name='Bottom Corner Reflector') -bottom_reflector_cell = CellFill(name='Bottom Reflector') - -assembly1 = Universe(name='Assembly 1') -assembly2 = Universe(name='Assembly 2') -refined_reflector = Universe(name='Semi-Finely Spaced Moderator') -right_reflector = Universe(name='Right Reflector') -corner_reflector = Universe(name='Bottom Corner Reflector') -bottom_reflector = Universe(name='Bottom Reflector') - -assembly1.addCell(assembly1_cell) -assembly2.addCell(assembly2_cell) -refined_reflector.addCell(refined_reflector_cell) -right_reflector.addCell(right_reflector_cell) -corner_reflector.addCell(corner_reflector_cell) -bottom_reflector.addCell(bottom_reflector_cell) - -# Root Cell/Universe -root_cell = CellFill(name='Full Geometry') -root_cell.addSurface(+1, boundaries[0]) -root_cell.addSurface(-1, boundaries[1]) -root_cell.addSurface(-1, boundaries[2]) -root_cell.addSurface(+1, boundaries[3]) - -root_universe = Universe(name='Root Universe') -root_universe.addCell(root_cell) - ############################################################################### -########################### Creating Lattices ############################# +# Main Simulation Parameters ############################################################################### -log.py_printf('NORMAL', 'Creating lattices...') - -lattices = list() - -# Top left, bottom right 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 1')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - -universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly1_cell.setFill(lattices[-1]) - -# Top right, bottom left 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 2')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] -universes = {1 : mox43, 2 : mox7, 3 : mox87, - 4 : guide_tube, 5 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly2_cell.setFill(lattices[-1]) - -# Sliced up water cells - semi finely spaced -lattices.append(Lattice(name='Semi-Finely Spaced Reflector')) -lattices[-1].setWidth(width_x=0.126, width_y=0.126) -template = [[reflector] * 10] * 10 -lattices[-1].setUniverses(template) -refined_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells - right side of geometry -lattices.append(Lattice(name='Right Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 17 -lattices[-1].setUniverses(template) -right_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom corner of geometry -lattices.append(Lattice(name='Bottom Corner Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -corner_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom of geometry -lattices.append(Lattice(name='Bottom Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 17] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -bottom_reflector_cell.setFill(lattices[-1]) - -# 4 x 4 core to represent two bundles and water -lattices.append(Lattice(name='Full Geometry')) -lattices[-1].setWidth(width_x=21.42, width_y=21.42) -lattices[-1].setUniverses([ - [assembly1, assembly2, right_reflector], - [assembly2, assembly1, right_reflector], - [bottom_reflector, bottom_reflector, corner_reflector]]) -root_cell.setFill(lattices[-1]) - - -############################################################################### -########################## Creating the Geometry ########################## -############################################################################### +opts = openmoc.options.Options() -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.set_log_level('NORMAL') -geometry = Geometry() -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() +openmoc.log.py_printf('TITLE', \ + 'Simulating the OECD\'s C5G7 Benchmark Problem...') ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) +from geometry import geometry +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = GPUSolver(geometry, track_generator) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = GPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/c5g7/c5g7.py b/sample-input/benchmarks/c5g7/c5g7.py index 0d6487b10..7b1af9455 100644 --- a/sample-input/benchmarks/c5g7/c5g7.py +++ b/sample-input/benchmarks/c5g7/c5g7.py @@ -1,329 +1,48 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating the OECD\'s C5G7 Benchmark Problem...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Importing materials data from HDF5...') - -materials = materialize.materialize('../../c5g7-materials.h5') - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-32.13, name='left') -right = XPlane(x=32.13, name='right') -top = YPlane(y=32.13, name='top') -bottom = YPlane(y=-32.13, name='bottom') -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(VACUUM) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(VACUUM) -boundaries = [left, right, top, bottom] - -# Create Circles for the fuel as well as to discretize the moderator into rings -fuel_radius = Circle(x=0.0, y=0.0, radius=0.54) -moderator_inner_radius = Circle(x=0.0, y=0.0, radius=0.62) -moderator_outer_radius = Circle(x=0.0, y=0.0, radius=0.58) - - -############################################################################### -###################### Creating Cells and Universes ####################### -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -# Moderator rings -moderator_ring1 = CellBasic(sectors=8) -moderator_ring2 = CellBasic(sectors=8) -moderator_ring3 = CellBasic(sectors=8) -moderator_ring1.setMaterial(materials['Water']) -moderator_ring2.setMaterial(materials['Water']) -moderator_ring3.setMaterial(materials['Water']) -moderator_ring1.addSurface(+1, fuel_radius) -moderator_ring1.addSurface(-1, moderator_inner_radius) -moderator_ring2.addSurface(+1, moderator_inner_radius) -moderator_ring2.addSurface(-1, moderator_outer_radius) -moderator_ring3.addSurface(+1, moderator_outer_radius) - -# UO2 pin cell -uo2_cell = CellBasic(rings=3, sectors=8) -uo2_cell.setMaterial(materials['UO2']) -uo2_cell.addSurface(-1, fuel_radius) - -uo2 = Universe(name='UO2') -uo2.addCell(uo2_cell) -uo2.addCell(moderator_ring1) -uo2.addCell(moderator_ring2) -uo2.addCell(moderator_ring3) - -# 4.3% MOX pin cell -mox43_cell = CellBasic(rings=3, sectors=8) -mox43_cell.setMaterial(materials['MOX-4.3%']) -mox43_cell.addSurface(-1, fuel_radius) - -mox43 = Universe(name='MOX-4.3%') -mox43.addCell(mox43_cell) -mox43.addCell(moderator_ring1) -mox43.addCell(moderator_ring2) -mox43.addCell(moderator_ring3) - -# 7% MOX pin cell -mox7_cell = CellBasic(rings=3, sectors=8) -mox7_cell.setMaterial(materials['MOX-7%']) -mox7_cell.addSurface(-1, fuel_radius) - -mox7 = Universe(name='MOX-7%') -mox7.addCell(mox7_cell) -mox7.addCell(moderator_ring1) -mox7.addCell(moderator_ring2) -mox7.addCell(moderator_ring3) - -# 8.7% MOX pin cell -mox87_cell = CellBasic(rings=3, sectors=8) -mox87_cell.setMaterial(materials['MOX-8.7%']) -mox87_cell.addSurface(-1, fuel_radius) - -mox87 = Universe(name='MOX-8.7%') -mox87.addCell(mox87_cell) -mox87.addCell(moderator_ring1) -mox87.addCell(moderator_ring2) -mox87.addCell(moderator_ring3) - -# Fission chamber pin cell -fission_chamber_cell = CellBasic(rings=3, sectors=8) -fission_chamber_cell.setMaterial(materials['Fission Chamber']) -fission_chamber_cell.addSurface(-1, fuel_radius) - -fission_chamber = Universe(name='Fission Chamber') -fission_chamber.addCell(fission_chamber_cell) -fission_chamber.addCell(moderator_ring1) -fission_chamber.addCell(moderator_ring2) -fission_chamber.addCell(moderator_ring3) - -# Guide tube pin cell -guide_tube_cell = CellBasic(rings=3, sectors=8) -guide_tube_cell.setMaterial(materials['Guide Tube']) -guide_tube_cell.addSurface(-1, fuel_radius) - -guide_tube = Universe(name='Guide Tube') -guide_tube.addCell(guide_tube_cell) -guide_tube.addCell(moderator_ring1) -guide_tube.addCell(moderator_ring2) -guide_tube.addCell(moderator_ring3) - -# Reflector -reflector_cell = CellBasic(name='moderator') -reflector_cell.setMaterial(materials['Water']) - -reflector = Universe(name='Reflector') -reflector.addCell(reflector_cell) - -# CellFills -assembly1_cell = CellFill(name='Assembly 1') -assembly2_cell = CellFill(name='Assembly 2') -refined_reflector_cell = CellFill(name='Semi-Finely Spaced Reflector') -right_reflector_cell = CellFill(name='Right Reflector') -corner_reflector_cell = CellFill(name='Bottom Corner Reflector') -bottom_reflector_cell = CellFill(name='Bottom Reflector') - -assembly1 = Universe(name='Assembly 1') -assembly2 = Universe(name='Assembly 2') -refined_reflector = Universe(name='Semi-Finely Spaced Moderator') -right_reflector = Universe(name='Right Reflector') -corner_reflector = Universe(name='Bottom Corner Reflector') -bottom_reflector = Universe(name='Bottom Reflector') - -assembly1.addCell(assembly1_cell) -assembly2.addCell(assembly2_cell) -refined_reflector.addCell(refined_reflector_cell) -right_reflector.addCell(right_reflector_cell) -corner_reflector.addCell(corner_reflector_cell) -bottom_reflector.addCell(bottom_reflector_cell) - -# Root Cell/Universe -root_cell = CellFill(name='Full Geometry') -root_cell.addSurface(+1, boundaries[0]) -root_cell.addSurface(-1, boundaries[1]) -root_cell.addSurface(-1, boundaries[2]) -root_cell.addSurface(+1, boundaries[3]) - -root_universe = Universe(name='Root Universe') -root_universe.addCell(root_cell) - +import openmoc ############################################################################### -########################### Creating Lattices ############################# +# Main Simulation Parameters ############################################################################### -log.py_printf('NORMAL', 'Creating lattices...') - -lattices = list() - -# Top left, bottom right 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 1')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], - [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - -universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly1_cell.setFill(lattices[-1]) - -# Top right, bottom left 17 x 17 assemblies -lattices.append(Lattice(name='Assembly 2')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], - [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], - [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], - [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], - [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] -universes = {1 : mox43, 2 : mox7, 3 : mox87, - 4 : guide_tube, 5 : fission_chamber} -for i in range(17): - for j in range(17): - template[i][j] = universes[template[i][j]] -lattices[-1].setUniverses(template) -assembly2_cell.setFill(lattices[-1]) - -# Sliced up water cells - semi finely spaced -lattices.append(Lattice(name='Semi-Finely Spaced Reflector')) -lattices[-1].setWidth(width_x=0.126, width_y=0.126) -template = [[reflector] * 10] * 10 -lattices[-1].setUniverses(template) -refined_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells - right side of geometry -lattices.append(Lattice(name='Right Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 17 -lattices[-1].setUniverses(template) -right_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom corner of geometry -lattices.append(Lattice(name='Bottom Corner Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 11 + [reflector] * 6] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -corner_reflector_cell.setFill(lattices[-1]) - -# Sliced up water cells for bottom of geometry -lattices.append(Lattice(name='Bottom Reflector')) -lattices[-1].setWidth(width_x=1.26, width_y=1.26) -template = [[refined_reflector] * 17] * 11 -template += [[reflector] * 17] * 6 -lattices[-1].setUniverses(template) -bottom_reflector_cell.setFill(lattices[-1]) - -# 4 x 4 core to represent two bundles and water -lattices.append(Lattice(name='Full Geometry')) -lattices[-1].setWidth(width_x=21.42, width_y=21.42) -lattices[-1].setUniverses([ - [assembly1, assembly2, right_reflector], - [assembly2, assembly1, right_reflector], - [bottom_reflector, bottom_reflector, corner_reflector]]) -root_cell.setFill(lattices[-1]) - - -############################################################################### -########################## Creating the Geometry ########################## -############################################################################### +opts = openmoc.options.Options() -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.set_log_level('NORMAL') -geometry = Geometry() -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() +openmoc.log.py_printf('TITLE', 'Simulating the OECD\'s C5G7 Benchmark Problem...') ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +from geometry import geometry +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setSourceConvergenceThreshold(tolerance) -solver.setNumThreads(num_threads) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -plotter.plot_materials(geometry, gridsize=500) -plotter.plot_cells(geometry, gridsize=500) -plotter.plot_flat_source_regions(geometry, gridsize=500) -plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/c5g7/geometry.py b/sample-input/benchmarks/c5g7/geometry.py new file mode 100644 index 000000000..5ff7186b0 --- /dev/null +++ b/sample-input/benchmarks/c5g7/geometry.py @@ -0,0 +1,265 @@ +import openmoc + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../../') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-32.13, name='left') +right = openmoc.XPlane(x=32.13, name='right') +top = openmoc.YPlane(y=32.13, name='top') +bottom = openmoc.YPlane(y=-32.13, name='bottom') +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.VACUUM) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.VACUUM) +boundaries = [left, right, top, bottom] + +# Create ZCylinders for the fuel as well as to discretize the moderator into +# rings +fuel_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.54) +moderator_inner_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.58) +moderator_outer_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.62) + + +############################################################################### +# Creating Cells and Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +# Moderator +moderator = openmoc.Cell(name='moderator') +moderator.setFill(materials['Water']) +moderator.addSurface(+1, fuel_radius) +moderator.setNumRings(2) +moderator.setNumSectors(8) + +# UO2 pin cell +uo2_cell = openmoc.Cell() +uo2_cell.setNumRings(3) +uo2_cell.setNumSectors(8) +uo2_cell.setFill(materials['UO2']) +uo2_cell.addSurface(-1, fuel_radius) + +uo2 = openmoc.Universe(name='UO2') +uo2.addCell(uo2_cell) +uo2.addCell(moderator) + +# 4.3% MOX pin cell +mox43_cell = openmoc.Cell() +mox43_cell.setNumRings(3) +mox43_cell.setNumSectors(8) +mox43_cell.setFill(materials['MOX-4.3%']) +mox43_cell.addSurface(-1, fuel_radius) + +mox43 = openmoc.Universe(name='MOX-4.3%') +mox43.addCell(mox43_cell) +mox43.addCell(moderator) + +# 7% MOX pin cell +mox7_cell = openmoc.Cell() +mox7_cell.setNumRings(3) +mox7_cell.setNumSectors(8) +mox7_cell.setFill(materials['MOX-7%']) +mox7_cell.addSurface(-1, fuel_radius) + +mox7 = openmoc.Universe(name='MOX-7%') +mox7.addCell(mox7_cell) +mox7.addCell(moderator) + +# 8.7% MOX pin cell +mox87_cell = openmoc.Cell() +mox87_cell.setNumRings(3) +mox87_cell.setNumSectors(8) +mox87_cell.setFill(materials['MOX-8.7%']) +mox87_cell.addSurface(-1, fuel_radius) + +mox87 = openmoc.Universe(name='MOX-8.7%') +mox87.addCell(mox87_cell) +mox87.addCell(moderator) + +# Fission chamber pin cell +fission_chamber_cell = openmoc.Cell() +fission_chamber_cell.setNumRings(3) +fission_chamber_cell.setNumSectors(8) +fission_chamber_cell.setFill(materials['Fission Chamber']) +fission_chamber_cell.addSurface(-1, fuel_radius) + +fission_chamber = openmoc.Universe(name='Fission Chamber') +fission_chamber.addCell(fission_chamber_cell) +fission_chamber.addCell(moderator) + +# Guide tube pin cell +guide_tube_cell = openmoc.Cell() +guide_tube_cell.setNumRings(3) +guide_tube_cell.setNumSectors(8) +guide_tube_cell.setFill(materials['Guide Tube']) +guide_tube_cell.addSurface(-1, fuel_radius) + +guide_tube = openmoc.Universe(name='Guide Tube') +guide_tube.addCell(guide_tube_cell) +guide_tube.addCell(moderator) + +# Reflector +reflector_cell = openmoc.Cell(name='moderator') +reflector_cell.setFill(materials['Water']) + +reflector = openmoc.Universe(name='Reflector') +reflector.addCell(reflector_cell) + +# Cells +assembly1_cell = openmoc.Cell(name='Assembly 1') +assembly2_cell = openmoc.Cell(name='Assembly 2') +refined_reflector_cell = openmoc.Cell(name='Semi-Finely Spaced Reflector') +right_reflector_cell = openmoc.Cell(name='Right Reflector') +corner_reflector_cell = openmoc.Cell(name='Bottom Corner Reflector') +bottom_reflector_cell = openmoc.Cell(name='Bottom Reflector') + +assembly1 = openmoc.Universe(name='Assembly 1') +assembly2 = openmoc.Universe(name='Assembly 2') +refined_reflector = openmoc.Universe(name='Semi-Finely Spaced Moderator') +right_reflector = openmoc.Universe(name='Right Reflector') +corner_reflector = openmoc.Universe(name='Bottom Corner Reflector') +bottom_reflector = openmoc.Universe(name='Bottom Reflector') + +assembly1.addCell(assembly1_cell) +assembly2.addCell(assembly2_cell) +refined_reflector.addCell(refined_reflector_cell) +right_reflector.addCell(right_reflector_cell) +corner_reflector.addCell(corner_reflector_cell) +bottom_reflector.addCell(bottom_reflector_cell) + +# Root Cell/Universe +root_cell = openmoc.Cell(name='Full Geometry') +root_cell.addSurface(+1, boundaries[0]) +root_cell.addSurface(-1, boundaries[1]) +root_cell.addSurface(-1, boundaries[2]) +root_cell.addSurface(+1, boundaries[3]) + +root_universe = openmoc.Universe(name='Root Universe') +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating lattices...') + +lattices = list() + +# Top left, bottom right 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly 1')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + +universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] +lattices[-1].setUniverses([template]) +assembly1_cell.setFill(lattices[-1]) + +# Top right, bottom left 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly 2')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] +universes = {1 : mox43, 2 : mox7, 3 : mox87, + 4 : guide_tube, 5 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] +lattices[-1].setUniverses([template]) +assembly2_cell.setFill(lattices[-1]) + +# Sliced up water cells - semi finely spaced +lattices.append(openmoc.Lattice(name='Semi-Finely Spaced Reflector')) +lattices[-1].setWidth(width_x=0.126, width_y=0.126) +template = [[reflector] * 10] * 10 +lattices[-1].setUniverses([template]) +refined_reflector_cell.setFill(lattices[-1]) + +# Sliced up water cells - right side of geometry +lattices.append(openmoc.Lattice(name='Right Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 11 + [reflector] * 6] * 17 +lattices[-1].setUniverses([template]) +right_reflector_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom corner of geometry +lattices.append(openmoc.Lattice(name='Bottom Corner Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 11 + [reflector] * 6] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +corner_reflector_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom of geometry +lattices.append(openmoc.Lattice(name='Bottom Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_reflector] * 17] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +bottom_reflector_cell.setFill(lattices[-1]) + +# 4 x 4 core to represent two bundles and water +lattices.append(openmoc.Lattice(name='Full Geometry')) +lattices[-1].setWidth(width_x=21.42, width_y=21.42) +lattices[-1].setUniverses([[ + [assembly1, assembly2, right_reflector], + [assembly2, assembly1, right_reflector], + [bottom_reflector, bottom_reflector, corner_reflector]]]) +root_cell.setFill(lattices[-1]) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) diff --git a/sample-input/benchmarks/homogeneous-one-group/adjoint-flux.py b/sample-input/benchmarks/homogeneous-one-group/adjoint-flux.py new file mode 100644 index 000000000..4ace194f1 --- /dev/null +++ b/sample-input/benchmarks/homogeneous-one-group/adjoint-flux.py @@ -0,0 +1,135 @@ +import numpy +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous infinite medium...') +openmoc.log.py_printf('HEADER', 'The reference keff = 1.43...') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating materials...') + +sigma_f = numpy.array([0.0414198575]) +nu_sigma_f = numpy.array([0.0994076580]) +sigma_s = numpy.array([0.383259177]) +chi = numpy.array([1.0]) +sigma_t = numpy.array([0.452648699]) + +infinite_medium = openmoc.Material(name='1-group infinite medium') +infinite_medium.setNumEnergyGroups(1) +infinite_medium.setSigmaF(sigma_f) +infinite_medium.setNuSigmaF(nu_sigma_f) +infinite_medium.setSigmaS(sigma_s) +infinite_medium.setChi(chi) +infinite_medium.setSigmaT(sigma_t) + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-100.0, name='left') +right = openmoc.XPlane(x=100.0, name='right') +top = openmoc.YPlane(y=100.0, name='top') +bottom = openmoc.YPlane(y=-100.0, name='bottom') + +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +cell = openmoc.Cell() +cell.setFill(infinite_medium) +cell.addSurface(halfspace=+1, surface=left) +cell.addSurface(halfspace=-1, surface=right) +cell.addSurface(halfspace=+1, surface=bottom) +cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(cell) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Running MOC adjoint eigenvalue simulation...') + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters, mode=openmoc.ADJOINT) +solver.printTimerReport() + + +############################################################################### +# Verify with NumPy +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Verifying with NumPy adjoint eigenvalue...') + +# Compute fission production matrix +fiss_mat = numpy.outer(chi, nu_sigma_f) + +# Create ajoint operator +sigma_s = numpy.transpose(sigma_s) +fiss_mat = numpy.transpose(fiss_mat) +M = numpy.linalg.solve((numpy.diag(sigma_t) - sigma_s), fiss_mat) + +# Solve adjoint eigenvalue problem with NumPy +k, phi = numpy.linalg.eig(M) + +# Select the dominant eigenvalue +k = max(k) + +openmoc.log.py_printf('RESULT', 'Numpy adjoint eigenvalue: {0:.6f}'.format(k)) +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/homogeneous-one-group/forward-flux.py b/sample-input/benchmarks/homogeneous-one-group/forward-flux.py new file mode 100644 index 000000000..264c176d7 --- /dev/null +++ b/sample-input/benchmarks/homogeneous-one-group/forward-flux.py @@ -0,0 +1,133 @@ +import numpy +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous infinite medium...') +openmoc.log.py_printf('HEADER', 'The reference keff = 1.43...') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating materials...') + +sigma_f = numpy.array([0.0414198575]) +nu_sigma_f = numpy.array([0.0994076580]) +sigma_s = numpy.array([0.383259177]) +chi = numpy.array([1.0]) +sigma_t = numpy.array([0.452648699]) + +infinite_medium = openmoc.Material(name='1-group infinite medium') +infinite_medium.setNumEnergyGroups(1) +infinite_medium.setSigmaF(sigma_f) +infinite_medium.setNuSigmaF(nu_sigma_f) +infinite_medium.setSigmaS(sigma_s) +infinite_medium.setChi(chi) +infinite_medium.setSigmaT(sigma_t) + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-100.0, name='left') +right = openmoc.XPlane(x=100.0, name='right') +top = openmoc.YPlane(y=100.0, name='top') +bottom = openmoc.YPlane(y=-100.0, name='bottom') + +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +cell = openmoc.Cell() +cell.setFill(infinite_medium) +cell.addSurface(halfspace=+1, surface=left) +cell.addSurface(halfspace=-1, surface=right) +cell.addSurface(halfspace=+1, surface=bottom) +cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(cell) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Running MOC forward eigenvalue simulation...') + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters, mode=openmoc.FORWARD) +solver.printTimerReport() + + +############################################################################### +# Verify with NumPy +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Verifying with NumPy forward eigenvalue...') + +# Compute fission production matrix +fiss_mat = numpy.outer(chi, nu_sigma_f) + +# Create forward operator +M = numpy.linalg.solve((numpy.diag(sigma_t) - sigma_s), fiss_mat) + +# Solve forward eigenvalue problem with NumPy +k, phi = numpy.linalg.eig(M) + +# Select the dominant eigenvalue +k = max(k) + +openmoc.log.py_printf('RESULT', 'Numpy forward eigenvalue: {0:.6f}'.format(k)) +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/homogeneous-one-group/homogeneous-one-group.py b/sample-input/benchmarks/homogeneous-one-group/homogeneous-one-group.py deleted file mode 100644 index 2f04ca009..000000000 --- a/sample-input/benchmarks/homogeneous-one-group/homogeneous-one-group.py +++ /dev/null @@ -1,115 +0,0 @@ -import numpy -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -from openmoc.options import Options - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating a one group homogeneous infinite medium...') -log.py_printf('HEADER', 'The reference keff = 1.43...') - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -log.py_printf('NORMAL', 'Creating materials...') - -infinite_medium = Material(name='1-group infinite medium') -infinite_medium.setNumEnergyGroups(1) -infinite_medium.setSigmaA(numpy.array([0.069389522])) -infinite_medium.setSigmaF(numpy.array([0.0414198575])) -infinite_medium.setNuSigmaF(numpy.array([0.0994076580])) -infinite_medium.setSigmaS(numpy.array([0.383259177])) -infinite_medium.setChi(numpy.array([1.0])) -infinite_medium.setSigmaT(numpy.array([0.452648699])) - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-100.0, name='left') -right = XPlane(x=100.0, name='right') -top = YPlane(y=100.0, name='top') -bottom = YPlane(y=-100.0, name='bottom') - -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(REFLECTIVE) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(REFLECTIVE) - - -############################################################################### -############################# Creating Cells ############################## -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -cell = CellBasic() -cell.setMaterial(infinite_medium) -cell.addSurface(halfspace=+1, surface=left) -cell.addSurface(halfspace=-1, surface=right) -cell.addSurface(halfspace=+1, surface=bottom) -cell.addSurface(halfspace=-1, surface=top) - - -############################################################################### -# Creating Universes -############################################################################### - -log.py_printf('NORMAL', 'Creating universes...') - -root_universe = Universe(name='root universe') -root_universe.addCell(cell) - - -############################################################################### -########################## Creating the Geometry ########################## -############################################################################### - -log.py_printf('NORMAL', 'Creating geometry...') - -geometry = Geometry() -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() - - -############################################################################### -######################## Creating the TrackGenerator ###################### -############################################################################### - -log.py_printf('NORMAL', 'Initializing the track generator...') - -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) -track_generator.generateTracks() - - -############################################################################### -########################### Running a Simulation ########################## -############################################################################### - -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) -solver.printTimerReport() - -log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/homogeneous-two-group/adjoint-flux.py b/sample-input/benchmarks/homogeneous-two-group/adjoint-flux.py new file mode 100644 index 000000000..e10ae0e68 --- /dev/null +++ b/sample-input/benchmarks/homogeneous-two-group/adjoint-flux.py @@ -0,0 +1,138 @@ +import numpy +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', \ + 'Simulating a two group homogeneous infinite medium...') +openmoc.log.py_printf('HEADER', 'The reference keff = 1.72...') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating materials...') + +sigma_f = numpy.array([0.000625, 0.135416667]) +nu_sigma_f = numpy.array([0.0015, 0.325]) +sigma_s = numpy.array([[0.1, 0.117], [0., 1.42]]) +chi = numpy.array([1.0, 0.0]) +sigma_t = numpy.array([0.2208, 1.604]) + +infinite_medium = openmoc.Material(name='2-group infinite medium') +infinite_medium.setNumEnergyGroups(2) +infinite_medium.setSigmaF(sigma_f) +infinite_medium.setNuSigmaF(nu_sigma_f) +infinite_medium.setSigmaS(sigma_s.flat) +infinite_medium.setChi(chi) +infinite_medium.setSigmaT(sigma_t) + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-100.0, name='left') +right = openmoc.XPlane(x=100.0, name='right') +top = openmoc.YPlane(y=100.0, name='top') +bottom = openmoc.YPlane(y=-100.0, name='bottom') + +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +cell = openmoc.Cell() +cell.setFill(infinite_medium) +cell.addSurface(halfspace=+1, surface=left) +cell.addSurface(halfspace=-1, surface=right) +cell.addSurface(halfspace=+1, surface=bottom) +cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(cell) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Running MOC adjoint eigenvalue simulation...') + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters, mode=openmoc.ADJOINT) +solver.printTimerReport() + + +############################################################################### +# Verify with NumPy +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Verifying with NumPy adjoint eigenvalue...') + +# Compute fission production matrix +fiss_mat = numpy.outer(chi, nu_sigma_f) + +# Tranpose the scattering matrix from OpenMOC's notation +sigma_s = numpy.transpose(sigma_s) + +# Create adjoint operator +sigma_s = numpy.transpose(sigma_s) +fiss_mat = numpy.transpose(fiss_mat) +M = numpy.linalg.solve((numpy.diag(sigma_t) - sigma_s), fiss_mat) + +# Solve eigenvalue problem with NumPy +k, phi = numpy.linalg.eig(M) + +# Select the dominant eigenvalue +k = max(k) + +openmoc.log.py_printf('RESULT', 'Numpy adjoint eigenvalue: {0:.6f}'.format(k)) +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/homogeneous-two-group/forward-flux.py b/sample-input/benchmarks/homogeneous-two-group/forward-flux.py new file mode 100644 index 000000000..af0a94cd6 --- /dev/null +++ b/sample-input/benchmarks/homogeneous-two-group/forward-flux.py @@ -0,0 +1,136 @@ +import numpy +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', \ + 'Simulating a two group homogeneous infinite medium...') +openmoc.log.py_printf('HEADER', 'The reference keff = 1.72...') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating materials...') + +sigma_f = numpy.array([0.000625, 0.135416667]) +nu_sigma_f = numpy.array([0.0015, 0.325]) +sigma_s = numpy.array([[0.1, 0.117], [0., 1.42]]) +chi = numpy.array([1.0, 0.0]) +sigma_t = numpy.array([0.2208, 1.604]) + +infinite_medium = openmoc.Material(name='2-group infinite medium') +infinite_medium.setNumEnergyGroups(2) +infinite_medium.setSigmaF(sigma_f) +infinite_medium.setNuSigmaF(nu_sigma_f) +infinite_medium.setSigmaS(sigma_s.flat) +infinite_medium.setChi(chi) +infinite_medium.setSigmaT(sigma_t) + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-100.0, name='left') +right = openmoc.XPlane(x=100.0, name='right') +top = openmoc.YPlane(y=100.0, name='top') +bottom = openmoc.YPlane(y=-100.0, name='bottom') + +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +cell = openmoc.Cell() +cell.setFill(infinite_medium) +cell.addSurface(halfspace=+1, surface=left) +cell.addSurface(halfspace=-1, surface=right) +cell.addSurface(halfspace=+1, surface=bottom) +cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(cell) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Running MOC forward eigenvalue simulation...') + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters, mode=openmoc.FORWARD) +solver.printTimerReport() + + +############################################################################### +# Verify with NumPy +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Verifying with NumPy forward eigenvalue...') + +# Compute fission production matrix +fiss_mat = numpy.outer(chi, nu_sigma_f) + +# Tranpose the scattering matrix from OpenMOC's notation +sigma_s = numpy.transpose(sigma_s) + +# Create forward operator +M = numpy.linalg.solve((numpy.diag(sigma_t) - sigma_s), fiss_mat) + +# Solve forward eigenvalue problem with NumPy +k, phi = numpy.linalg.eig(M) + +# Select the dominant eigenvalue +k = max(k) + +openmoc.log.py_printf('RESULT', 'Numpy forward eigenvalue: {0:.6f}'.format(k)) +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/homogeneous-two-group/homogeneous-two-groups.py b/sample-input/benchmarks/homogeneous-two-group/homogeneous-two-groups.py deleted file mode 100644 index 957da9c9b..000000000 --- a/sample-input/benchmarks/homogeneous-two-group/homogeneous-two-groups.py +++ /dev/null @@ -1,115 +0,0 @@ -import numpy -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -from openmoc.options import Options - - -############################################################################### -####################### Main Simulation Parameters ######################## -############################################################################### - -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() - -log.set_log_level('NORMAL') - -log.py_printf('TITLE', 'Simulating a two group homogeneous infinite medium...') -log.py_printf('HEADER', 'The reference keff = 1.72...') - - -############################################################################### -########################### Creating Materials ############################ -############################################################################### - -log.py_printf('NORMAL', 'Creating materials...') - -infinite_medium = Material(name='2-group infinite medium') -infinite_medium.setNumEnergyGroups(2) -infinite_medium.setSigmaA(numpy.array([0.0038, 0.184])) -infinite_medium.setSigmaF(numpy.array([0.000625, 0.135416667])) -infinite_medium.setNuSigmaF(numpy.array([0.0015, 0.325])) -infinite_medium.setSigmaS(numpy.array([0.1, 0.117, 0.0, 1.42])) -infinite_medium.setChi(numpy.array([1.0, 0.0])) -infinite_medium.setSigmaT(numpy.array([0.2208, 1.604])) - - -############################################################################### -########################### Creating Surfaces ############################# -############################################################################### - -log.py_printf('NORMAL', 'Creating surfaces...') - -left = XPlane(x=-100.0, name='left') -right = XPlane(x=100.0, name='right') -top = YPlane(y=100.0, name='top') -bottom = YPlane(y=-100.0, name='bottom') - -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(REFLECTIVE) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(REFLECTIVE) - - -############################################################################### -############################# Creating Cells ############################## -############################################################################### - -log.py_printf('NORMAL', 'Creating cells...') - -cell = CellBasic() -cell.setMaterial(infinite_medium) -cell.addSurface(halfspace=+1, surface=left) -cell.addSurface(halfspace=-1, surface=right) -cell.addSurface(halfspace=+1, surface=bottom) -cell.addSurface(halfspace=-1, surface=top) - - -############################################################################### -# Creating Universes -############################################################################### - -log.py_printf('NORMAL', 'Creating universes...') - -root_universe = Universe(name='root universe') -root_universe.addCell(cell) - - -############################################################################### -########################## Creating the Geometry ########################## -############################################################################### - -log.py_printf('NORMAL', 'Creating geometry...') - -geometry = Geometry() -geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() - - -############################################################################### -######################## Creating the TrackGenerator ###################### -############################################################################### - -log.py_printf('NORMAL', 'Initializing the track generator...') - -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) -track_generator.generateTracks() - - -############################################################################### -########################### Running a Simulation ########################## -############################################################################### - -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) -solver.printTimerReport() - -log.py_printf('TITLE', 'Finished') diff --git a/sample-input/benchmarks/romano/romano.py b/sample-input/benchmarks/romano/romano.py index c6ac625d2..aec69c2f7 100644 --- a/sample-input/benchmarks/romano/romano.py +++ b/sample-input/benchmarks/romano/romano.py @@ -1,46 +1,35 @@ import numpy -from openmoc import * -import openmoc.log as log -from openmoc.options import Options - +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') -log.py_printf('TITLE', 'Simulating HW3 from Fall 2010 22.212...') +openmoc.log.py_printf('TITLE', 'Simulating HW3 from Fall 2010 22.212...') ############################################################################### -########################### Creating Materials ############################ +# Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Creating materials...') +openmoc.log.py_printf('NORMAL', 'Creating materials...') -fuel = Material(name='fuel') -moderator = Material(name='moderator') +fuel = openmoc.Material(name='fuel') +moderator = openmoc.Material(name='moderator') fuel.setNumEnergyGroups(1) moderator.setNumEnergyGroups(1) -fuel.setSigmaA(numpy.array([0.069389522])) fuel.setSigmaT(numpy.array([0.452648699])) fuel.setSigmaF(numpy.array([0.0414198575])) fuel.setNuSigmaF(numpy.array([0.0994076580])) fuel.setSigmaS(numpy.array([0.38259177])) fuel.setChi(numpy.array([1.0])) -moderator.setSigmaA(numpy.array([0.003751099])) moderator.setSigmaT(numpy.array([0.841545641])) moderator.setSigmaF(numpy.array([0.0])) moderator.setNuSigmaF(numpy.array([0.0])) @@ -49,36 +38,36 @@ ############################################################################### -########################### Creating Surfaces ############################# +# Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -circle = Circle(x=0.0, y=0.0, radius=0.4) -left = XPlane(x=-0.635) -right = XPlane(x=0.635) -top = YPlane(y=0.635) -bottom = YPlane(y=-0.635) +zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.4) +left = openmoc.XPlane(x=-0.635) +right = openmoc.XPlane(x=0.635) +top = openmoc.YPlane(y=0.635) +bottom = openmoc.YPlane(y=-0.635) -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(REFLECTIVE) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(REFLECTIVE) +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) ############################################################################### -############################# Creating Cells ############################## +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -fuel_cell = CellBasic(name='fuel') -fuel_cell.setMaterial(fuel) -fuel_cell.addSurface(halfspace=-1, surface=circle) +fuel_cell = openmoc.Cell(name='fuel') +fuel_cell.setFill(fuel) +fuel_cell.addSurface(halfspace=-1, surface=zcylinder) -moderator_cell = CellBasic(name='moderator') -moderator_cell.setMaterial(moderator) -moderator_cell.addSurface(halfspace=+1, surface=circle) +moderator_cell = openmoc.Cell(name='moderator') +moderator_cell.setFill(moderator) +moderator_cell.addSurface(halfspace=+1, surface=zcylinder) moderator_cell.addSurface(halfspace=+1, surface=left) moderator_cell.addSurface(halfspace=-1, surface=right) moderator_cell.addSurface(halfspace=+1, surface=bottom) @@ -86,46 +75,46 @@ ############################################################################### -########################### Creating Universes ############################ +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -root_universe = Universe(name='root universe') +root_universe = openmoc.Universe(name='root universe') root_universe.addCell(fuel_cell) root_universe.addCell(moderator_cell) ############################################################################### -########################## Creating the Geometry ########################## +# Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/bundled-lattice/bundled-lattice.py b/sample-input/bundled-lattice/bundled-lattice.py index 4328696ce..d0c35005c 100644 --- a/sample-input/bundled-lattice/bundled-lattice.py +++ b/sample-input/bundled-lattice/bundled-lattice.py @@ -1,92 +1,81 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') ############################################################################### -########################### Creating Materials ############################ +# Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Importing materials data from HDF5...') +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') -materials = materialize.materialize('../c5g7-materials.h5') +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') ############################################################################### -########################### Creating Surfaces ############################# +# Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -left = XPlane(x=-34.0, name='left') -right = XPlane(x=34.0, name='right') -top = YPlane(y=-34.0, name='top') -bottom = YPlane(y=34.0, name='bottom') +left = openmoc.XPlane(x=-34.0, name='left') +right = openmoc.XPlane(x=34.0, name='right') +top = openmoc.YPlane(y=-34.0, name='top') +bottom = openmoc.YPlane(y=34.0, name='bottom') boundaries = [left, right, top, bottom] -for boundary in boundaries: boundary.setBoundaryType(REFLECTIVE) +for boundary in boundaries: boundary.setBoundaryType(openmoc.REFLECTIVE) -circles = list() +zcylinders = list() radii = [0.15, 0.2, 0.25, 0.3, 0.35, 0.4] -for r in radii: circles.append(Circle(x=0.0, y=0.0, radius=r)) +for r in radii: zcylinders.append(openmoc.ZCylinder(x=0.0, y=0.0, radius=r)) ############################################################################### -############################# Creating Cells ############################## +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -# Create a list of 10 CellBasic instances -cells = [CellBasic() for i in range(12)] +# Create a list of 12 Cell instances +cells = [openmoc.Cell() for i in range(12)] # Append 3 CellFills for the assemblies and full core -assembly1 = CellFill(name='assembly 1') -assembly2 = CellFill(name='assembly 2') -root_cell = CellFill(name='full core') +assembly1 = openmoc.Cell(name='assembly 1') +assembly2 = openmoc.Cell(name='assembly 2') +root_cell = openmoc.Cell(name='full core') # Create fuel/moderator by adding the appropriate Surfaces and Materials -cells[0].addSurface(halfspace=-1, surface=circles[0]) -cells[1].addSurface(halfspace=+1, surface=circles[0]) -cells[2].addSurface(halfspace=-1, surface=circles[1]) -cells[3].addSurface(halfspace=+1, surface=circles[1]) -cells[4].addSurface(halfspace=-1, surface=circles[2]) -cells[5].addSurface(halfspace=+1, surface=circles[2]) -cells[6].addSurface(halfspace=-1, surface=circles[3]) -cells[7].addSurface(halfspace=+1, surface=circles[3]) -cells[8].addSurface(halfspace=-1, surface=circles[4]) -cells[9].addSurface(halfspace=+1, surface=circles[4]) -cells[10].addSurface(halfspace=-1, surface=circles[5]) -cells[11].addSurface(halfspace=+1, surface=circles[5]) - -cells[0].setMaterial(materials['UO2']) -cells[1].setMaterial(materials['Water']) -cells[2].setMaterial(materials['UO2']) -cells[3].setMaterial(materials['Water']) -cells[4].setMaterial(materials['UO2']) -cells[5].setMaterial(materials['Water']) -cells[6].setMaterial(materials['UO2']) -cells[7].setMaterial(materials['Water']) -cells[8].setMaterial(materials['UO2']) -cells[9].setMaterial(materials['Water']) -cells[10].setMaterial(materials['UO2']) -cells[11].setMaterial(materials['Water']) +cells[0].addSurface(halfspace=-1, surface=zcylinders[0]) +cells[1].addSurface(halfspace=+1, surface=zcylinders[0]) +cells[2].addSurface(halfspace=-1, surface=zcylinders[1]) +cells[3].addSurface(halfspace=+1, surface=zcylinders[1]) +cells[4].addSurface(halfspace=-1, surface=zcylinders[2]) +cells[5].addSurface(halfspace=+1, surface=zcylinders[2]) +cells[6].addSurface(halfspace=-1, surface=zcylinders[3]) +cells[7].addSurface(halfspace=+1, surface=zcylinders[3]) +cells[8].addSurface(halfspace=-1, surface=zcylinders[4]) +cells[9].addSurface(halfspace=+1, surface=zcylinders[4]) +cells[10].addSurface(halfspace=-1, surface=zcylinders[5]) +cells[11].addSurface(halfspace=+1, surface=zcylinders[5]) + +cells[0].setFill(materials['UO2']) +cells[1].setFill(materials['Water']) +cells[2].setFill(materials['UO2']) +cells[3].setFill(materials['Water']) +cells[4].setFill(materials['UO2']) +cells[5].setFill(materials['Water']) +cells[6].setFill(materials['UO2']) +cells[7].setFill(materials['Water']) +cells[8].setFill(materials['UO2']) +cells[9].setFill(materials['Water']) +cells[10].setFill(materials['UO2']) +cells[11].setFill(materials['Water']) # Add the boundary Planes to the "root" Cell root_cell.addSurface(halfspace=+1, surface=boundaries[0]) @@ -99,17 +88,17 @@ # Creating Universes ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -u1 = Universe(name='pin 1') -u2 = Universe(name='pin 2') -u3 = Universe(name='pin 3') -u4 = Universe(name='pin 4') -u5 = Universe(name='pin 5') -u6 = Universe(name='pin 6') -u7 = Universe(name='2x2 lattice') -u8 = Universe(name='2x2 lattice') -root_universe = Universe(name='root universe') +u1 = openmoc.Universe(name='pin 1') +u2 = openmoc.Universe(name='pin 2') +u3 = openmoc.Universe(name='pin 3') +u4 = openmoc.Universe(name='pin 4') +u5 = openmoc.Universe(name='pin 5') +u6 = openmoc.Universe(name='pin 6') +u7 = openmoc.Universe(name='2x2 lattice') +u8 = openmoc.Universe(name='2x2 lattice') +root_universe = openmoc.Universe(name='root universe') # Add the appropriate Cells to each Universe u1.addCell(cells[0]) @@ -130,15 +119,15 @@ ############################################################################### -########################### Creating Lattices ############################# +# Creating Lattices ############################################################################### -log.py_printf('NORMAL', 'Creating 4 x 4 core of 17 x 17 assemblies...') +openmoc.log.py_printf('NORMAL', 'Creating 4 x 4 core of 17 x 17 assemblies...') # 1st 17x17 assembly -a1 = Lattice(name='assembly 1') +a1 = openmoc.Lattice(name='assembly 1') a1.setWidth(width_x=1.0, width_y=1.0) -a1.setUniverses([ +a1.setUniverses([[ [u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1], [u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2], [u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1], @@ -155,12 +144,12 @@ [u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2], [u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1], [u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2, u3, u2], - [u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1]]) + [u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1, u2, u1]]]) # 2nd 17x17 assembly -a2 = Lattice(name='assembly 2') +a2 = openmoc.Lattice(name='assembly 2') a2.setWidth(width_x=1.0, width_y=1.0) -a2.setUniverses([ +a2.setUniverses([[ [u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4], [u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5], [u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4], @@ -177,15 +166,15 @@ [u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5], [u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4], [u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5, u6, u5], - [u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4]]) + [u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4, u5, u4]]]) # 4x4 core -core = Lattice(name='full core') +core = openmoc.Lattice(name='full core') core.setWidth(width_x=17.0, width_y=17.0) -core.setUniverses([[u7, u8, u7, u8], - [u8, u7, u8, u7], - [u7, u8, u7, u8], - [u8, u7, u8, u7]]) +core.setUniverses([[[u7, u8, u7, u8], + [u8, u7, u8, u7], + [u7, u8, u7, u8], + [u8, u7, u8, u7]]]) assembly1.setFill(a1) assembly2.setFill(a2) @@ -193,49 +182,47 @@ ############################################################################### -########################## Creating the Geometry ########################## +# Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_segments(track_generator) -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/c5g7-materials.h5 b/sample-input/c5g7-materials.h5 deleted file mode 100644 index 680c77b1c..000000000 Binary files a/sample-input/c5g7-materials.h5 and /dev/null differ diff --git a/sample-input/c5g7-materials.py b/sample-input/c5g7-materials.py deleted file mode 100644 index 34e6923c1..000000000 --- a/sample-input/c5g7-materials.py +++ /dev/null @@ -1,282 +0,0 @@ -""" -This file writes all of the materials data (multi-group nuclear -cross-sections) for the OECD's C5G7 deterministic neutron transport -benchmark problem to an HDF5 file. The script uses the h5py Python package -to interact with the HDF5 file format. This may be a good example for those -wishing ot write their nuclear data to an HDF5 file to import using the -OpenMOC 'materialize' Python module. -""" - - -# Create a Python dictionary to store C5G7 multi-group cross-sections -dataset = {} - -dataset['Energy Groups'] = 7 -dataset['Materials'] = {} - -c5g7_dataset = dataset['Materials'] - -############################################################################### -################################ UO2 ################################ -############################################################################### - -# Create a subdictionary for UO2 materials data -c5g7_dataset['UO2'] = {} - -c5g7_dataset['UO2']['Total XS'] = [1.779490E-01, 3.298050E-01, 4.803880E-01, - 5.543670E-01, 3.118010E-01, 3.951680E-01, - 5.644060E-01] - -c5g7_dataset['UO2']['Absorption XS'] = [8.024800E-03, 3.717400E-03, 2.676900E-02, - 9.623600E-02, 3.002000E-02, 1.112600E-01, - 2.827800E-01] - -c5g7_dataset['UO2']['Scattering XS'] = [1.275370E-01, 4.237800E-02, 9.437400E-06, - 5.516300E-09, 0., 0., 0., 0., 3.244560E-01, - 1.631400E-03, 3.142700E-09, 0., 0., 0., 0., - 0., 4.509400E-01, 2.679200E-03, 0., 0., 0., - 0., 0., 0., 4.525650E-01, 5.566400E-03, 0., - 0., 0., 0., 0., 1.252500E-04, 2.714010E-01, - 1.025500E-02, 1.002100E-08, 0., 0., 0., 0., - 1.296800E-03, 2.658020E-01, 1.680900E-02, - 0., 0., 0., 0., 0., 8.545800E-03, 2.730800E-01] - -c5g7_dataset['UO2']['Fission XS'] = [7.212060E-03, 8.193010E-04, 6.453200E-03, - 1.856480E-02, 1.780840E-02, 8.303480E-02, - 2.160040E-01] - -c5g7_dataset['UO2']['Nu Fission XS'] = [2.005998E-02, 2.027303E-03, 1.570599E-02, - 4.518301E-02, 4.334208E-02, 2.020901E-01, - 5.257105E-01] - -c5g7_dataset['UO2']['Chi'] = [5.87910E-01, 4.11760E-01, 3.39060E-04, - 1.17610E-07, 0., 0., 0.] - - - -############################################################################### -############################## MOX (4.3%) ############################ -############################################################################### - -# Create a subdictionary for MOX-4.3% materials data -c5g7_dataset['MOX-4.3%'] = {} - -c5g7_dataset['MOX-4.3%']['Total XS'] = [1.787310E-01, 3.308490E-01, 4.837720E-01, - 5.669220E-01, 4.262270E-01, 6.789970E-01, - 6.828520E-01] -c5g7_dataset['MOX-4.3%']['Absorption XS'] = [8.433900E-03, 3.757700E-03, 2.797000E-02, - 1.042100E-01, 1.399400E-01, 4.091800E-01, - 4.093500E-01] -c5g7_dataset['MOX-4.3%']['Scattering XS'] = [1.288760E-01, 4.141300E-02, 8.229000E-06, - 5.040500E-09, 0., 0., 0., 0., 3.254520E-01, - 1.639500E-03, 1.598200E-09, 0., 0., 0., 0., 0., - 4.531880E-01, 2.614200E-03, 0., 0., 0., 0., 0., 0., - 4.571730E-01, 5.539400E-03, 0., 0., 0., 0., 0., - 1.604600E-04, 2.768140E-01, 9.312700E-03, 9.165600E-09, - 0., 0., 0., 0., 2.005100E-03, 2.529620E-01, - 1.485000E-02, 0., 0., 0., 0., 0., - 8.494800E-03, 2.650070E-01] -c5g7_dataset['MOX-4.3%']['Fission XS'] = [7.62704E-03, 8.76898E-04, 5.69835E-03, - 2.28872E-02, 1.07635E-02, 2.32757E-01, - 2.48968E-01] -c5g7_dataset['MOX-4.3%']['Nu Fission XS'] = [2.175300E-02, 2.535103E-03, 1.626799E-02, - 6.547410E-02, 3.072409E-02, 6.666510E-01, - 7.139904E-01] -c5g7_dataset['MOX-4.3%']['Chi'] = [5.87910E-01, 4.11760E-01, 3.39060E-04, - 1.17610E-07, 0., 0., 0.] - - - -############################################################################### -############################## MOX (7%) ############################## -############################################################################### - -# Create a subdictionary for MOX-7% materials data -c5g7_dataset['MOX-7%'] = {} - -c5g7_dataset['MOX-7%']['Absorption XS'] = [9.065700E-03, 4.296700E-03, 3.288100E-02, - 1.220300E-01, 1.829800E-01, 5.684600E-01, - 5.852100E-01] -c5g7_dataset['MOX-7%']['Total XS'] = [1.813230E-01, 3.343680E-01, 4.937850E-01, - 5.912160E-01, 4.741980E-01, 8.336010E-01, - 8.536030E-01] -c5g7_dataset['MOX-7%']['Scattering XS'] = [1.304570E-01, 4.179200E-02, 8.510500E-06, - 5.132900E-09, 0., 0., 0., 0., 3.284280E-01, 1.643600E-03, - 2.201700E-09, 0., 0., 0., 0., 0., 4.583710E-01, - 2.533100E-03, 0., 0., 0., 0., 0., 0., 4.637090E-01, - 5.476600E-03, 0., 0., 0., 0., 0., 1.761900E-04, - 2.823130E-01, 8.728900E-03, 9.001600E-09, 0., 0., 0., - 0., 2.276000E-03, 2.497510E-01, 1.311400E-02, 0., 0., - 0., 0., 0., 8.864500E-03, 2.595290E-01] -c5g7_dataset['MOX-7%']['Fission XS'] = [8.25446E-03, 1.32565E-03, 8.42156E-03, - 3.28730E-02, 1.59636E-02, 3.23794E-01, 3.62803E-01] -c5g7_dataset['MOX-7%']['Nu Fission XS'] = [2.381395E-02, 3.858689E-03, 2.413400E-02, - 9.436622E-02, 4.576988E-02, 9.281814E-01, - 1.043200E+00] -c5g7_dataset['MOX-7%']['Chi'] = [5.87910E-01, 4.11760E-01, 3.39060E-04, - 1.17610E-07, 0., 0., 0.] - - - -############################################################################### -############################## MOX (8.7%) ############################ -############################################################################### - -# Create a subdictionary for MOX-8.7% materials data -c5g7_dataset['MOX-8.7%'] = {} - -# Create a subgroup for MOX-8.7% materials data -c5g7_dataset['MOX-8.7%']['Absorption XS'] = [9.486200E-03, 4.655600E-03, 3.624000E-02, - 1.327200E-01, 2.084000E-01, 6.587000E-01, - 6.901700E-01] -c5g7_dataset['MOX-8.7%']['Total XS'] = [1.830450E-01, 3.367050E-01, 5.005070E-01, - 6.061740E-01, 5.027540E-01, 9.210280E-01, - 9.552310E-01] -c5g7_dataset['MOX-8.7%']['Scattering XS'] = [1.315040E-01, 4.204600E-02, 8.697200E-06, - 5.193800E-09, 0., 0., 0., 0., 3.304030E-01, - 1.646300E-03, 2.600600E-09, 0., 0., 0., 0., 0., - 4.617920E-01, 2.474900E-03, 0., 0., 0., 0., 0., 0., - 4.680210E-01, 5.433000E-03, 0., 0., 0., 0., 0., - 1.859700E-04, 2.857710E-01, 8.397300E-03, 8.928000E-09, - 0., 0., 0., 0., 2.391600E-03, 2.476140E-01, - 1.232200E-02, 0., 0., 0., 0., 0., - 8.968100E-03, 2.560930E-01] -c5g7_dataset['MOX-8.7%']['Fission XS'] = [8.67209E-03, 1.62426E-03, 1.02716E-02, - 3.90447E-02, 1.92576E-02, 3.74888E-01, - 4.30599E-01] -c5g7_dataset['MOX-8.7%']['Nu Fission XS'] = [2.518600E-02, 4.739509E-03, 2.947805E-02, - 1.122500E-01, 5.530301E-02, 1.074999E+00, - 1.239298E+00] -c5g7_dataset['MOX-8.7%']['Chi'] = [5.87910E-01, 4.11760E-01, 3.39060E-04, - 1.17610E-07, 0., 0., 0.] - - - -############################################################################### -############################ Fission Chamber ######################### -############################################################################### - -# Create a subdictionary for fission chamber materials data -c5g7_dataset['Fission Chamber'] = {} - -c5g7_dataset['Fission Chamber']['Absorption XS'] = [5.113200E-04, 7.581300E-05, 3.164300E-04, - 1.167500E-03, 3.397700E-03, 9.188600E-03, - 2.324400E-02] -c5g7_dataset['Fission Chamber']['Total XS'] = [1.260320E-01, 2.931600E-01, 2.842500E-01, - 2.810200E-01, 3.344600E-01, 5.656400E-01, - 1.172140E+00] -c5g7_dataset['Fission Chamber']['Scattering XS'] = [6.616590E-02, 5.907000E-02, 2.833400E-04, - 1.462200E-06, 2.064200E-08, 0., 0., 0., - 2.403770E-01, 5.243500E-02, 2.499000E-04, - 1.923900E-05, 2.987500E-06, 4.214000E-07, - 0., 0., 1.834250E-01, 9.228800E-02, 6.936500E-03, - 1.079000E-03, 2.054300E-04, 0., 0., 0., - 7.907690E-02, 1.699900E-01, 2.586000E-02, - 4.925600E-03, 0., 0., 0., 3.734000E-05, - 9.975700E-02, 2.067900E-01, 2.447800E-02, 0., - 0., 0., 0., 9.174200E-04, 3.167740E-01, - 2.387600E-01, 0., 0., 0., 0., 0., 4.979300E-02, - 1.09910E+00] -c5g7_dataset['Fission Chamber']['Fission XS'] = [4.79002E-09, 5.82564E-09, 4.63719E-07, - 5.24406E-06, 1.45390E-07, 7.14972E-07, - 2.08041E-06] -c5g7_dataset['Fission Chamber']['Nu Fission XS'] = [1.323401E-08, 1.434500E-08, 1.128599E-06, - 1.276299E-05, 3.538502E-07, 1.740099E-06, - 5.063302E-06] -c5g7_dataset['Fission Chamber']['Chi'] = [5.87910E-01, 4.11760E-01, 3.39060E-04, - 1.17610E-07, 0., 0., 0.] - - - -############################################################################### -############################## Guide Tube ########################### -############################################################################### - -# Create a subdictionary for guide tube materials data -c5g7_dataset['Guide Tube'] = {} - -c5g7_dataset['Guide Tube']['Absorption XS'] = [5.113200E-04, 7.580100E-05, 3.157200E-04, - 1.158200E-03, 3.397500E-03, 9.187800E-03, - 2.324200E-02] - -c5g7_dataset['Guide Tube']['Total XS'] = [1.260320E-01, 2.931600E-01, 2.842400E-01, - 2.809600E-01, 3.344400E-01, 5.656400E-01, - 1.172150E+00] - -c5g7_dataset['Guide Tube']['Scattering XS'] = [6.616590E-02, 5.907000E-02, 2.833400E-04, - 1.462200E-06, 2.064200E-08, 0., 0., 0., 2.403770E-01, - 5.243500E-02, 2.499000E-04, 1.923900E-05, - 2.987500E-06, 4.214000E-07, 0., 0., 1.832970E-01, - 9.239700E-02, 6.944600E-03, 1.0803000E-03, - 2.056700E-04, 0., 0., 0., 7.885110E-02, 1.701400E-01, - 2.588100E-02, 4.929700E-03, 0., 0., 0., 3.733300E-05, - 9.973720E-02, 2.067900E-01, 2.447800E-02, 0., 0., 0., - 0., 9.172600E-04, 3.167650E-01, 2.387700E-01, 0., 0., - 0., 0., 0., 4.979200E-02, 1.099120E+00] - -c5g7_dataset['Guide Tube']['Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Guide Tube']['Nu Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Guide Tube']['Chi'] = [0., 0., 0., 0., 0., 0., 0.] - - - -############################################################################### -################################ Water ############################## -############################################################################### - -# Create a subdictionary for water materials data -c5g7_dataset['Water'] = {} - -c5g7_dataset['Water']['Absorption XS'] = [6.010500E-04, 1.579300E-05, 3.371600E-04, - 1.940600E-03, 5.741600E-03, 1.500100E-02, - 3.723900E-02] -c5g7_dataset['Water']['Total XS'] = [1.592060E-01, 4.129700E-01, 5.903100E-01, - 5.843500E-01, 7.180000E-01, 1.254450E+00, - 2.650380E+00] -c5g7_dataset['Water']['Scattering XS'] = [4.447770E-02, 1.134000E-01, 7.234700E-04, - 3.749900E-06, 5.318400E-08, 0., 0., 0., 2.823340E-01, - 1.299400E-01, 6.234000E-04, 4.800200E-05, 7.448600E-06, - 1.045500E-06, 0., 0., 3.452560E-01, 2.245700E-01, - 1.699900E-02, 2.644300E-03, 5.034400E-04, 0., 0., 0., - 9.102840E-02, 4.155100E-01, 6.373200E-02, 1.213900E-02, - 0., 0., 0., 7.143700E-05, 1.391380E-01, 5.118200E-01, - 6.122900E-02, 0., 0., 0., 0., 2.215700E-03, 6.999130E-01, - 5.373200E-01, 0., 0., 0., 0., 0., 1.324400E-01, - 2.480700E+00] -c5g7_dataset['Water']['Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Water']['Nu Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Water']['Chi'] = [0., 0., 0., 0., 0., 0., 0.] - - -############################################################################### -################################ Control Rod ############################## -############################################################################### - -# Create a subdictionary for water materials data -c5g7_dataset['Control Rod'] = {} - -c5g7_dataset['Control Rod']['Absorption XS'] = [1.70490E-03, 8.36224E-03,8.37901E-02, - 3.97797E-01, 6.98763E-01, 9.29508E-01, - 1.17836E+00] -c5g7_dataset['Control Rod']['Total XS'] = [2.16768E-01, 4.80098E-01, 8.86369E-01, - 9.70009E-01, 9.10482E-01, 1.13775E+00, - 1.84048E+00] -c5g7_dataset['Control Rod']['Scattering XS'] = [1.70563E-01, 4.44012E-02, 9.83670E-05, - 1.27786E-07, 0., 0., 0., 0., 4.71050E-01, - 6.85480E-04, 3.91395E-10, 0., 0., - 0., 0., 0., 8.01859E-01, 7.20132E-04, - 0., 0., 0., 0., 0., 0., - 5.70752E-01, 1.46015E-03, 0., 0., - 0., 0., 0., 6.55562E-05, 2.07838E-01, 3.81486E-03, - 3.69760E-09, 0., 0., 0., 0., 1.02427E-03, 2.02465E-01, - 4.75290E-03, 0., 0., 0., 0., 0., 3.53043E-03, - 6.58597E-01] -c5g7_dataset['Control Rod']['Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Control Rod']['Nu Fission XS'] = [0., 0., 0., 0., 0., 0., 0.] - -c5g7_dataset['Control Rod']['Chi'] = [0., 0., 0., 0., 0., 0., 0.] diff --git a/sample-input/c5g7-materials-hdf5.py b/sample-input/c5g7-mgxs-hdf5.py similarity index 72% rename from sample-input/c5g7-materials-hdf5.py rename to sample-input/c5g7-mgxs-hdf5.py index bbb358877..4dfcdec68 100644 --- a/sample-input/c5g7-materials-hdf5.py +++ b/sample-input/c5g7-mgxs-hdf5.py @@ -13,9 +13,11 @@ # Create the file to store C5G7 multi-groups cross-sections -f = h5py.File('c5g7-materials.h5') -f.attrs["Energy Groups"] = 7 +f = h5py.File('c5g7-mgxs.h5') +f.attrs["# groups"] = 7 +# Create a group to specify that MGXS are split by material (vs. cell) +material_group = f.create_group('material') ############################################################################### @@ -23,12 +25,10 @@ ############################################################################### # Create a subgroup for UO2 materials data -uo2 = f.create_group('UO2') +uo2 = material_group.create_group('UO2') sigma_t = numpy.array([1.779490E-01, 3.298050E-01, 4.803880E-01, 5.543670E-01, 3.118010E-01, 3.951680E-01, 5.644060E-01]) -sigma_a = numpy.array([8.024800E-03, 3.717400E-03, 2.676900E-02, - 9.623600E-02, 3.002000E-02, 1.112600E-01, 2.827800E-01]) sigma_s = numpy.array([1.275370E-01, 4.237800E-02, 9.437400E-06, 5.516300E-09, 0., 0., 0., 0., 3.244560E-01, 1.631400E-03, 3.142700E-09, 0., 0., 0., 0., @@ -48,12 +48,11 @@ 1.17610E-07, 0., 0., 0.]) # Create datasets for each cross-section type -uo2.create_dataset('Total XS', data=sigma_t) -uo2.create_dataset('Absorption XS', data=sigma_a) -uo2.create_dataset('Scattering XS', data=sigma_s) -uo2.create_dataset('Fission XS', data=sigma_f) -uo2.create_dataset('Nu Fission XS', data=nu_sigma_f) -uo2.create_dataset('Chi', data=chi) +uo2.create_dataset('total', data=sigma_t) +uo2.create_dataset('scatter matrix', data=sigma_s) +uo2.create_dataset('fission', data=sigma_f) +uo2.create_dataset('nu-fission', data=nu_sigma_f) +uo2.create_dataset('chi', data=chi) @@ -62,10 +61,8 @@ ############################################################################### # Create a subgroup for MOX-4.3% materials data -mox43 = f.create_group('MOX-4.3%') +mox43 = material_group.create_group('MOX-4.3%') -sigma_a = numpy.array([8.433900E-03, 3.757700E-03, 2.797000E-02, - 1.042100E-01, 1.399400E-01, 4.091800E-01, 4.093500E-01]) sigma_t = numpy.array([1.787310E-01, 3.308490E-01, 4.837720E-01, 5.669220E-01, 4.262270E-01, 6.789970E-01, 6.828520E-01]) sigma_s = numpy.array([1.288760E-01, 4.141300E-02, 8.229000E-06, @@ -85,13 +82,11 @@ 0., 0., 0.]) # Create datasets for each cross-section type -mox43.create_dataset('Total XS', data=sigma_t) -mox43.create_dataset('Absorption XS', data=sigma_a) -mox43.create_dataset('Scattering XS', data=sigma_s) -mox43.create_dataset('Fission XS', data=sigma_f) -mox43.create_dataset('Nu Fission XS', data=nu_sigma_f) -mox43.create_dataset('Chi', data=chi) - +mox43.create_dataset('total', data=sigma_t) +mox43.create_dataset('scatter matrix', data=sigma_s) +mox43.create_dataset('fission', data=sigma_f) +mox43.create_dataset('nu-fission', data=nu_sigma_f) +mox43.create_dataset('chi', data=chi) ############################################################################### @@ -99,10 +94,8 @@ ############################################################################### # Create a subgroup for MOX-7% materials data -mox7 = f.create_group('MOX-7%') +mox7 = material_group.create_group('MOX-7%') -sigma_a = numpy.array([9.065700E-03, 4.296700E-03, 3.288100E-02, - 1.220300E-01, 1.829800E-01, 5.684600E-01, 5.852100E-01]) sigma_t = numpy.array([1.813230E-01, 3.343680E-01, 4.937850E-01, 5.912160E-01, 4.741980E-01, 8.336010E-01, 8.536030E-01]) sigma_s = numpy.array([1.304570E-01, 4.179200E-02, 8.510500E-06, @@ -122,13 +115,11 @@ 0., 0., 0.]) # Create datasets for each cross-section type -mox7.create_dataset('Total XS', data=sigma_t) -mox7.create_dataset('Absorption XS', data=sigma_a) -mox7.create_dataset('Scattering XS', data=sigma_s) -mox7.create_dataset('Fission XS', data=sigma_f) -mox7.create_dataset('Nu Fission XS', data=nu_sigma_f) -mox7.create_dataset('Chi', data=chi) - +mox7.create_dataset('total', data=sigma_t) +mox7.create_dataset('scatter matrix', data=sigma_s) +mox7.create_dataset('fission', data=sigma_f) +mox7.create_dataset('nu-fission', data=nu_sigma_f) +mox7.create_dataset('chi', data=chi) ############################################################################### @@ -136,10 +127,8 @@ ############################################################################### # Create a subgroup for MOX-8.7% materials data -mox87 = f.create_group('MOX-8.7%') +mox87 = material_group.create_group('MOX-8.7%') -sigma_a = numpy.array([9.486200E-03, 4.655600E-03, 3.624000E-02, - 1.327200E-01, 2.084000E-01, 6.587000E-01, 6.901700E-01]) sigma_t = numpy.array([1.830450E-01, 3.367050E-01, 5.005070E-01, 6.061740E-01, 5.027540E-01, 9.210280E-01, 9.552310E-01]) sigma_s = numpy.array([1.315040E-01, 4.204600E-02, 8.697200E-06, @@ -159,13 +148,11 @@ 0., 0., 0.]) # Create datasets for each cross-section type -mox87.create_dataset('Total XS', data=sigma_t) -mox87.create_dataset('Absorption XS', data=sigma_a) -mox87.create_dataset('Scattering XS', data=sigma_s) -mox87.create_dataset('Fission XS', data=sigma_f) -mox87.create_dataset('Nu Fission XS', data=nu_sigma_f) -mox87.create_dataset('Chi', data=chi) - +mox87.create_dataset('total', data=sigma_t) +mox87.create_dataset('scatter matrix', data=sigma_s) +mox87.create_dataset('fission', data=sigma_f) +mox87.create_dataset('nu-fission', data=nu_sigma_f) +mox87.create_dataset('chi', data=chi) ############################################################################### @@ -173,25 +160,22 @@ ############################################################################### # Create a subgroup for fission chamber materials data -fiss_chamber = f.create_group('Fission Chamber') +fiss_chamber = material_group.create_group('Fission Chamber') -sigma_a = numpy.array([5.113200E-04, 7.581300E-05, 3.164300E-04, - 1.167500E-03, 3.397700E-03, 9.188600E-03, - 2.324400E-02]) -sigma_t = numpy.array([1.260320E-01, 2.931600E-01, 2.842500E-01, - 2.810200E-01, 3.344600E-01, 5.656400E-01, +sigma_t = numpy.array([1.260320E-01, 2.931600E-01, 2.842500E-01, + 2.810200E-01, 3.344600E-01, 5.656400E-01, 1.172140E+00]) -sigma_s = numpy.array([6.616590E-02, 5.907000E-02, 2.833400E-04, - 1.462200E-06, 2.064200E-08, 0., 0., 0., - 2.403770E-01, 5.243500E-02, 2.499000E-04, - 1.923900E-05, 2.987500E-06, 4.214000E-07, +sigma_s = numpy.array([6.616590E-02, 5.907000E-02, 2.833400E-04, + 1.462200E-06, 2.064200E-08, 0., 0., 0., + 2.403770E-01, 5.243500E-02, 2.499000E-04, + 1.923900E-05, 2.987500E-06, 4.214000E-07, 0., 0., 1.834250E-01, 9.228800E-02, 6.936500E-03, - 1.079000E-03, 2.054300E-04, 0., 0., 0., - 7.907690E-02, 1.699900E-01, 2.586000E-02, - 4.925600E-03, 0., 0., 0., 3.734000E-05, - 9.975700E-02, 2.067900E-01, 2.447800E-02, 0., - 0., 0., 0., 9.174200E-04, 3.167740E-01, - 2.387600E-01, 0., 0., 0., 0., 0., 4.979300E-02, + 1.079000E-03, 2.054300E-04, 0., 0., 0., + 7.907690E-02, 1.699900E-01, 2.586000E-02, + 4.925600E-03, 0., 0., 0., 3.734000E-05, + 9.975700E-02, 2.067900E-01, 2.447800E-02, 0., + 0., 0., 0., 9.174200E-04, 3.167740E-01, + 2.387600E-01, 0., 0., 0., 0., 0., 4.979300E-02, 1.09910E+00]) sigma_f = numpy.array([4.79002E-09, 5.82564E-09, 4.63719E-07, 5.24406E-06, 1.45390E-07, 7.14972E-07, 2.08041E-06]) @@ -202,13 +186,11 @@ 1.17610E-07, 0., 0., 0.]) # Create datasets for each cross-section type -fiss_chamber.create_dataset('Total XS', data=sigma_t) -fiss_chamber.create_dataset('Absorption XS', data=sigma_a) -fiss_chamber.create_dataset('Scattering XS', data=sigma_s) -fiss_chamber.create_dataset('Fission XS', data=sigma_f) -fiss_chamber.create_dataset('Nu Fission XS', data=nu_sigma_f) -fiss_chamber.create_dataset('Chi', data=chi) - +fiss_chamber.create_dataset('total', data=sigma_t) +fiss_chamber.create_dataset('scatter matrix', data=sigma_s) +fiss_chamber.create_dataset('fission', data=sigma_f) +fiss_chamber.create_dataset('nu-fission', data=nu_sigma_f) +fiss_chamber.create_dataset('chi', data=chi) ############################################################################### @@ -216,20 +198,17 @@ ############################################################################### # Create a subgroup for guide tube materials data -guide_tube = f.create_group('Guide Tube') +guide_tube = material_group.create_group('Guide Tube') -sigma_a = numpy.array([5.113200E-04, 7.580100E-05, 3.157200E-04, - 1.158200E-03, 3.397500E-03, 9.187800E-03, - 2.324200E-02]) -sigma_t = numpy.array([1.260320E-01, 2.931600E-01, 2.842400E-01, - 2.809600E-01, 3.344400E-01, 5.656400E-01, +sigma_t = numpy.array([1.260320E-01, 2.931600E-01, 2.842400E-01, + 2.809600E-01, 3.344400E-01, 5.656400E-01, 1.172150E+00]) -sigma_s = numpy.array([6.616590E-02, 5.907000E-02, 2.833400E-04, +sigma_s = numpy.array([6.616590E-02, 5.907000E-02, 2.833400E-04, 1.462200E-06, 2.064200E-08, 0., 0., 0., 2.403770E-01, - 5.243500E-02, 2.499000E-04, 1.923900E-05, - 2.987500E-06, 4.214000E-07, 0., 0., 1.832970E-01, - 9.239700E-02, 6.944600E-03, 1.0803000E-03, - 2.056700E-04, 0., 0., 0., 7.885110E-02, 1.701400E-01, + 5.243500E-02, 2.499000E-04, 1.923900E-05, + 2.987500E-06, 4.214000E-07, 0., 0., 1.832970E-01, + 9.239700E-02, 6.944600E-03, 1.0803000E-03, + 2.056700E-04, 0., 0., 0., 7.885110E-02, 1.701400E-01, 2.588100E-02, 4.929700E-03, 0., 0., 0., 3.733300E-05, 9.973720E-02, 2.067900E-01, 2.447800E-02, 0., 0., 0., 0., 9.172600E-04, 3.167650E-01, 2.387700E-01, 0., 0., @@ -240,13 +219,11 @@ chi = numpy.zeros(7) # Create datasets for each cross-section type -guide_tube.create_dataset('Total XS', data=sigma_t) -guide_tube.create_dataset('Absorption XS', data=sigma_a) -guide_tube.create_dataset('Scattering XS', data=sigma_s) -guide_tube.create_dataset('Fission XS', data=sigma_f) -guide_tube.create_dataset('Nu Fission XS', data=nu_sigma_f) -guide_tube.create_dataset('Chi', data=chi) - +guide_tube.create_dataset('total', data=sigma_t) +guide_tube.create_dataset('scatter matrix', data=sigma_s) +guide_tube.create_dataset('fission', data=sigma_f) +guide_tube.create_dataset('nu-fission', data=nu_sigma_f) +guide_tube.create_dataset('chi', data=chi) ############################################################################### @@ -254,10 +231,8 @@ ############################################################################### # Create a subgroup for water materials data -water = f.create_group('Water') +water = material_group.create_group('Water') -sigma_a = numpy.array([6.010500E-04, 1.579300E-05, 3.371600E-04, - 1.940600E-03, 5.741600E-03, 1.500100E-02, 3.723900E-02]) sigma_t = numpy.array([1.592060E-01, 4.129700E-01, 5.903100E-01, 5.843500E-01, 7.180000E-01, 1.254450E+00, 2.650380E+00]) sigma_s = numpy.array([4.447770E-02, 1.134000E-01, 7.234700E-04, @@ -275,13 +250,43 @@ chi = numpy.zeros(7) # Create datasets for each cross-section type -water.create_dataset('Total XS', data=sigma_t) -water.create_dataset('Absorption XS', data=sigma_a) -water.create_dataset('Scattering XS', data=sigma_s) -water.create_dataset('Fission XS', data=sigma_f) -water.create_dataset('Nu Fission XS', data=nu_sigma_f) -water.create_dataset('Chi', data=chi) +water.create_dataset('total', data=sigma_t) +water.create_dataset('scatter matrix', data=sigma_s) +water.create_dataset('fission', data=sigma_f) +water.create_dataset('nu-fission', data=nu_sigma_f) +water.create_dataset('chi', data=chi) + + +############################################################################### +################################ Control Rod ############################## +############################################################################### +# Create a subdictionary for water materials data +control_rod = material_group.create_group('Control Rod') + +sigma_t = numpy.array([2.16768E-01, 4.80098E-01, 8.86369E-01, + 9.70009E-01, 9.10482E-01, 1.13775E+00, + 1.84048E+00]) +sigma_s = numpy.array([1.70563E-01, 4.44012E-02, 9.83670E-05, + 1.27786E-07, 0., 0., 0., 0., 4.71050E-01, + 6.85480E-04, 3.91395E-10, 0., 0., + 0., 0., 0., 8.01859E-01, 7.20132E-04, + 0., 0., 0., 0., 0., 0., + 5.70752E-01, 1.46015E-03, 0., 0., + 0., 0., 0., 6.55562E-05, 2.07838E-01, 3.81486E-03, + 3.69760E-09, 0., 0., 0., 0., 1.02427E-03, 2.02465E-01, + 4.75290E-03, 0., 0., 0., 0., 0., 3.53043E-03, + 6.58597E-01]) +sigma_f = numpy.zeros(7) +nu_sigma_f = numpy.zeros(7) +chi = numpy.zeros(7) + +# Create datasets for each cross-section type +control_rod.create_dataset('total', data=sigma_t) +control_rod.create_dataset('scatter matrix', data=sigma_s) +control_rod.create_dataset('fission', data=sigma_f) +control_rod.create_dataset('nu-fission', data=nu_sigma_f) +control_rod.create_dataset('chi', data=chi) # Close the hdf5 data file f.close() diff --git a/sample-input/c5g7-mgxs.h5 b/sample-input/c5g7-mgxs.h5 new file mode 100644 index 000000000..659091116 Binary files /dev/null and b/sample-input/c5g7-mgxs.h5 differ diff --git a/sample-input/cosine-source/cosine-source.py b/sample-input/cosine-source/cosine-source.py new file mode 100644 index 000000000..c5521a73b --- /dev/null +++ b/sample-input/cosine-source/cosine-source.py @@ -0,0 +1,160 @@ +import openmoc +import math + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-20.0, name='left') +right = openmoc.XPlane(x=20.0, name='right') +top = openmoc.YPlane(y=20.0, name='top') +bottom = openmoc.YPlane(y=-20.0, name='bottom') +boundaries = [left, right, top, bottom] + +for boundary in boundaries: boundary.setBoundaryType(openmoc.VACUUM) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +water_cell = openmoc.Cell(name='water') +water_cell.setFill(materials['Water']) + +root_cell = openmoc.Cell(name='root cell') +root_cell.addSurface(halfspace=+1, surface=left) +root_cell.addSurface(halfspace=-1, surface=right) +root_cell.addSurface(halfspace=+1, surface=bottom) +root_cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +water_univ = openmoc.Universe(name='water') +root_universe = openmoc.Universe(name='root universe') + +water_univ.addCell(water_cell) +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +# Number of lattice cells +num_x = 200 +num_y = 200 + +# Compute widths of each lattice cell +width_x = (root_universe.getMaxX() - root_universe.getMinX()) / num_y +width_y = (root_universe.getMaxY() - root_universe.getMinY()) / num_x + +# Create 2D array of Universes in each lattice cell +universes = [[[water_univ]*num_x for _ in range(num_y)]] + +openmoc.log.py_printf('NORMAL', \ + 'Creating a {0}x{0} lattice...'.format(num_x, num_y)) + +lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) +lattice.setWidth(width_x=width_x, width_y=width_y) +lattice.setUniverses(universes) +root_cell.setFill(lattice) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +# initialize the solver +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) + +# Set the source in every cell to a cosine distribution +for fsr_id in xrange(solver.getGeometry().getNumFSRs()): + + # Get the coordinates of some point within the FSR + pt = solver.getGeometry().getFSRPoint(fsr_id) + x_pt = pt.getX() + y_pt = pt.getY() + + # Set the FSR source for every group + L = num_x * width_x / 2 + H = num_y * width_y / 2 + for g in range(materials['Water'].getNumEnergyGroups()): + group = g + 1 + source_value = math.cos(x_pt/L) * math.cos(y_pt/H) + solver.setFixedSourceByFSR(fsr_id, group, source_value) + + # NOTE: A more precise definition of the source would calculate the same + # source values for all points within each flat source region. In this + # example that is not the case. However, since the FSR discretization is + # reasonably fine in this case, the slight error introduced from defining the + # source based on one point in the FSR does not have a large impact on the + # resulting flux shapes. + +# Run the solver for the provided source +solver.computeFlux(opts.max_iters) +solver.printTimerReport() + + +############################################################################### +# Generating Plots +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=250) +openmoc.plotter.plot_cells(geometry, gridsize=250) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=250) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/gradients/cube.py b/sample-input/gradients/cube.py new file mode 100644 index 000000000..dbe6488dc --- /dev/null +++ b/sample-input/gradients/cube.py @@ -0,0 +1,74 @@ +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +length = 10.0 +num_cells_x = 100 +num_cells_y = 1 + +############################################################################### +####################### Define Material Properties ######################## +############################################################################### + +basic_material = openmoc.Material(name='1-group infinite medium') +basic_material.setNumEnergyGroups(1) +basic_material.setSigmaF([0.0414198575]) +basic_material.setNuSigmaF([0.0994076580]) +basic_material.setSigmaS([0.383259177]) +basic_material.setChi([1.0]) +basic_material.setSigmaT([0.452648699]) + +############################################################################# +########################## Creating Surfaces ############################ +############################################################################# + +left = openmoc.XPlane(x=-length/2, name='left') +right = openmoc.XPlane(x=length/2, name='right') +top = openmoc.YPlane(y=length/2, name='top') +bottom = openmoc.YPlane(y=-length/2, name='bottom') + +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + +############################################################################# +############################ Creating Cells ############################# +############################################################################# + +fill = openmoc.Cell(name='fill') +fill.setFill(basic_material) + +root_cell = openmoc.Cell(name='root cell') +root_cell.addSurface(halfspace=+1, surface=left) +root_cell.addSurface(halfspace=-1, surface=right) +root_cell.addSurface(halfspace=+1, surface=bottom) +root_cell.addSurface(halfspace=-1, surface=top) + +############################################################################# +########################## Creating Universes ########################## +############################################################################# + +fill_universe = openmoc.Universe(name='homogeneous fill cell') +fill_universe.addCell(fill) + +root_universe = openmoc.Universe(name='root universe') +root_universe.addCell(root_cell) + +############################################################################# +########################### Creating Lattices ########################## +############################################################################# + +lattice = openmoc.Lattice(name='MxN lattice') +lattice.setWidth(width_x=length/num_cells_x, width_y=length/num_cells_y) +lattice.setUniverses([[[fill_universe] * num_cells_x]*num_cells_y]) +root_cell.setFill(lattice) + +############################################################################# +######################### Creating the Geometry ######################### +############################################################################# + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) diff --git a/sample-input/gradients/one-directional/one-directional-cmfd.py b/sample-input/gradients/one-directional/one-directional-cmfd.py new file mode 100644 index 000000000..1d7c07b0b --- /dev/null +++ b/sample-input/gradients/one-directional/one-directional-cmfd.py @@ -0,0 +1,70 @@ +import sys +sys.path.append('..') +from cube import geometry, root_cell, left, right, top, bottom +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous, one directional gradient...') + +############################################################################### +########################### Creating CMFD Mesh ########################### +############################################################################### +openmoc.log.py_printf('NORMAL', 'Creating Cmfd mesh...') + +cmfd = openmoc.Cmfd() +cmfd.setSORRelaxationFactor(1.5) +cmfd.setLatticeStructure(25,1) + +############################################################################### +######################### Load the Cubic Geometry ######################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing cubic geometry...') + +left.setBoundaryType(openmoc.VACUUM) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + +geometry.setCmfd(cmfd) + +############################################################################### +######################## Creating the TrackGenerator ###################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + +############################################################################### +########################### Running a Simulation ########################## +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) +solver.printTimerReport() + +############################################################################### +############################ Generating Plots ############################ +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=100) +openmoc.plotter.plot_cells(geometry, gridsize=100) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=100) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/gradients/one-directional/one-directional.py b/sample-input/gradients/one-directional/one-directional.py new file mode 100644 index 000000000..f62f137f9 --- /dev/null +++ b/sample-input/gradients/one-directional/one-directional.py @@ -0,0 +1,59 @@ +import sys +sys.path.append('..') +from cube import geometry, root_cell, left, right, top, bottom +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous, one directional gradient...') + +############################################################################### +######################### Load the Cubic Geometry ######################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing cubic geometry...') + +left.setBoundaryType(openmoc.VACUUM) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + +############################################################################### +######################## Creating the TrackGenerator ###################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + +############################################################################### +########################### Running a Simulation ########################## +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) +solver.printTimerReport() + +############################################################################### +############################ Generating Plots ############################ +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=100) +openmoc.plotter.plot_cells(geometry, gridsize=100) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=100) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/gradients/two-directional/two-directional-cmfd.py b/sample-input/gradients/two-directional/two-directional-cmfd.py new file mode 100644 index 000000000..5f2e7057a --- /dev/null +++ b/sample-input/gradients/two-directional/two-directional-cmfd.py @@ -0,0 +1,70 @@ +import sys +sys.path.append('..') +from cube import geometry, root_cell, left, right, top, bottom +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous, two directional gradient...') + +############################################################################### +########################### Creating CMFD Mesh ########################### +############################################################################### +openmoc.log.py_printf('NORMAL', 'Creating Cmfd mesh...') + +cmfd = openmoc.Cmfd() +cmfd.setSORRelaxationFactor(1.5) +cmfd.setLatticeStructure(25,1) + +############################################################################### +######################### Load the Cubic Geometry ######################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing cubic geometry...') + +left.setBoundaryType(openmoc.VACUUM) +right.setBoundaryType(openmoc.VACUUM) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + +geometry.setCmfd(cmfd) + +############################################################################### +######################## Creating the TrackGenerator ###################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + +############################################################################### +########################### Running a Simulation ########################## +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) +solver.printTimerReport() + +############################################################################### +############################ Generating Plots ############################ +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=100) +openmoc.plotter.plot_cells(geometry, gridsize=100) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=100) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/gradients/two-directional/two-directional.py b/sample-input/gradients/two-directional/two-directional.py new file mode 100644 index 000000000..b6dcd8ce2 --- /dev/null +++ b/sample-input/gradients/two-directional/two-directional.py @@ -0,0 +1,59 @@ +import sys +sys.path.append('..') +from cube import geometry, root_cell, left, right, top, bottom +import openmoc + +############################################################################### +####################### Main Simulation Parameters ######################## +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', \ + 'Simulating a one group homogeneous, two directional gradient...') + +############################################################################### +######################### Load the Cubic Geometry ######################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing cubic geometry...') + +left.setBoundaryType(openmoc.VACUUM) +right.setBoundaryType(openmoc.VACUUM) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) + +############################################################################### +######################## Creating the TrackGenerator ###################### +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + +############################################################################### +########################### Running a Simulation ########################## +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) +solver.printTimerReport() + +############################################################################### +############################ Generating Plots ############################ +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=100) +openmoc.plotter.plot_cells(geometry, gridsize=100) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=100) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/ipython-notebook/mox-assembly.ipynb b/sample-input/ipython-notebook/mox-assembly.ipynb new file mode 100644 index 000000000..da4f12470 --- /dev/null +++ b/sample-input/ipython-notebook/mox-assembly.ipynb @@ -0,0 +1,715 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/lib/pymodules/python2.7/matplotlib/__init__.py:1173: UserWarning: This call to matplotlib.use() has no effect\n", + "because the backend has already been chosen;\n", + "matplotlib.use() must be called *before* pylab, matplotlib.pyplot,\n", + "or matplotlib.backends is imported for the first time.\n", + "\n", + " warnings.warn(_use_error_msg)\n" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "import openmoc\n", + "import openmoc.plotter as plotter\n", + "import openmoc.process as process\n", + "from openmoc.materialize import load_from_hdf5\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulation Runtime Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "num_threads = 4\n", + "track_spacing = 0.05\n", + "num_azim = 16\n", + "tolerance = 1E-5\n", + "max_iters = 50" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize Materials" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['UO2', 'MOX-8.7%', 'Fission Chamber', 'MOX-4.3%', 'Water', 'MOX-7%', 'Control Rod', 'Guide Tube']\n" + ] + } + ], + "source": [ + "materials = load_from_hdf5(filename='c5g7-mgxs.h5', directory='..')\n", + "print materials.keys()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Bounding Surfaces" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create ZCylinder for the fuel\n", + "fuel_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.54)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create planes to bound the entire geometry\n", + "left = openmoc.XPlane(x=-10.71, name='left')\n", + "right = openmoc.XPlane(x=10.71, name='right')\n", + "top = openmoc.YPlane(y=10.71, name='top')\n", + "bottom = openmoc.YPlane(y=-10.71, name='bottom')\n", + "\n", + "left.setBoundaryType(openmoc.REFLECTIVE)\n", + "right.setBoundaryType(openmoc.REFLECTIVE)\n", + "top.setBoundaryType(openmoc.REFLECTIVE)\n", + "bottom.setBoundaryType(openmoc.REFLECTIVE)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Fuel Pins" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 4.3% MOX pin cell\n", + "mox43_cell = openmoc.Cell()\n", + "mox43_cell.setFill(materials['MOX-4.3%'])\n", + "mox43_cell.setNumRings(3)\n", + "mox43_cell.setNumSectors(8)\n", + "mox43_cell.addSurface(-1, fuel_radius)\n", + "\n", + "mox43 = openmoc.Universe(name='MOX-4.3%')\n", + "mox43.addCell(mox43_cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 7% MOX pin cell\n", + "mox7_cell = openmoc.Cell()\n", + "mox7_cell.setFill(materials['MOX-7%'])\n", + "mox7_cell.setNumRings(3)\n", + "mox7_cell.setNumSectors(8)\n", + "mox7_cell.addSurface(-1, fuel_radius)\n", + "\n", + "mox7 = openmoc.Universe(name='MOX-7%')\n", + "mox7.addCell(mox7_cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 8.7% MOX pin cell\n", + "mox87_cell = openmoc.Cell()\n", + "mox87_cell.setFill(materials['MOX-8.7%'])\n", + "mox87_cell.setNumRings(3)\n", + "mox87_cell.setNumSectors(8)\n", + "mox87_cell.addSurface(-1, fuel_radius)\n", + "\n", + "mox87 = openmoc.Universe(name='MOX-8.7%')\n", + "mox87.addCell(mox87_cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Fission chamber pin cell\n", + "fission_chamber_cell = openmoc.Cell()\n", + "fission_chamber_cell.setFill(materials['Fission Chamber'])\n", + "fission_chamber_cell.setNumRings(3)\n", + "fission_chamber_cell.setNumSectors(8)\n", + "fission_chamber_cell.addSurface(-1, fuel_radius)\n", + "\n", + "fission_chamber = openmoc.Universe(name='Fission Chamber')\n", + "fission_chamber.addCell(fission_chamber_cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Guide tube pin cell\n", + "guide_tube_cell = openmoc.Cell()\n", + "guide_tube_cell.setFill(materials['Guide Tube'])\n", + "guide_tube_cell.setNumRings(3)\n", + "guide_tube_cell.setNumSectors(8)\n", + "guide_tube_cell.addSurface(-1, fuel_radius)\n", + "\n", + "guide_tube = openmoc.Universe(name='Guide Tube')\n", + "guide_tube.addCell(guide_tube_cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Moderator rings\n", + "moderator = openmoc.Cell()\n", + "moderator.setFill(materials['Water'])\n", + "moderator.addSurface(+1, fuel_radius)\n", + "moderator.setNumRings(3)\n", + "moderator.setNumSectors(8)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Add moderator rings to each pin cell\n", + "pins = [mox43, mox7, mox87, fission_chamber, guide_tube]\n", + "for pin in pins:\n", + " pin.addCell(moderator)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# CellFills for the assembly\n", + "assembly1_cell = openmoc.Cell(name='Assembly 1')\n", + "\n", + "assembly1 = openmoc.Universe(name='Assembly 1')\n", + "assembly1.addCell(assembly1_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Fuel Assembly" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# A mixed enrichment PWR MOX fuel assembly\n", + "assembly = openmoc.Lattice(name='MOX Assembly')\n", + "assembly.setWidth(width_x=1.26, width_y=1.26)\n", + "\n", + "# Create a template to map to pin cell types\n", + "template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],\n", + " [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1],\n", + " [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1],\n", + " [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1],\n", + " [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1],\n", + " [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1],\n", + " [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1],\n", + " [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1],\n", + " [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1],\n", + " [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1],\n", + " [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1],\n", + " [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1],\n", + " [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1],\n", + " [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1],\n", + " [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],\n", + " [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]\n", + "\n", + "universes = {1 : mox43, 2 : mox7, 3 : mox87,\n", + " 4 : guide_tube, 5 : fission_chamber}\n", + "\n", + "for i in range(17):\n", + " for j in range(17):\n", + " template[i][j] = universes[template[i][j]]\n", + "\n", + "assembly.setUniverses([template])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Root Cell/Universe\n", + "root_cell = openmoc.Cell(name='Full Geometry')\n", + "root_cell.setFill(assembly)\n", + "root_cell.addSurface(+1, left)\n", + "root_cell.addSurface(-1, right)\n", + "root_cell.addSurface(-1, top)\n", + "root_cell.addSurface(+1, bottom)\n", + "\n", + "root_universe = openmoc.Universe(name='Root Universe')\n", + "root_universe.addCell(root_cell)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize CMFD" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cmfd = openmoc.Cmfd()\n", + "cmfd.setSORRelaxationFactor(1.5)\n", + "cmfd.setLatticeStructure(17,17)\n", + "cmfd.setGroupStructure([1,4,8])\n", + "cmfd.setKNearest(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize Geometry" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "geometry = openmoc.Geometry()\n", + "geometry.setRootUniverse(root_universe)\n", + "geometry.setCmfd(cmfd)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the materials...\n" + ] + }, + { + "data": { + "image/png": "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\njuM4tfL/6zpSWFkStI8AAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the geometry color-coded by materials\n", + "fig = plotter.plot_materials(geometry, gridsize=500, get_figure=True)\n", + "fig.set_figheight(4)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the cells...\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the geometry color-coded by cells\n", + "fig = plotter.plot_cells(geometry, gridsize=500, get_figure=True)\n", + "fig.set_figheight(4)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize TrackGenerator" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Importing ray tracing data from file...\n" + ] + } + ], + "source": [ + "track_generator = openmoc.TrackGenerator(geometry, num_azim, track_spacing)\n", + "track_generator.setNumThreads(num_threads)\n", + "track_generator.generateTracks()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the flat source regions...\n" + ] + }, + { + "data": { + "image/png": "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\nYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the geometry color-coded by flat source region\n", + "fig = plotter.plot_flat_source_regions(geometry, gridsize=500, get_figure=True)\n", + "fig.set_figheight(4)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the CMFD cells...\n" + ] + }, + { + "data": { + "image/png": "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\nhqRodR18Vrolvaih4fvJNVNPysvFY699Z1bd6O8fkVwz6fFbs3pd9FT69ZUB9hg2K7nmf6oOTG7d\n0NlXpxf94aisXpz/fFbZxaSPrLtgcvNrX8fZ5pt5o/j+j3HJNbeT/n2ZzNng4DNJ7WVgSIpmYEiK\nZmBIimZgSIpmYEiKZmBIimZgSIpmYEiKZmBIimZgSIpmYEiKZmBIilbX0aqsy6i6PuM2c+f8PaMR\n8PywvLpnM2p+n36rPgDemJpVdtFpE9NrrvtRVq9F459Krjm71z9l9foh92TVjZx9Q3rR0FOyeq0f\nlVVGn5npNY9OSK8pL56jVSW1j4EhKZqBISmagSEpmoEhKZqBISmagSEpmoEhKZqBISmagSEpmoEh\nKZqBISmagSEpWn1Hqx6UPvJ06kPvSa75xu+SS4J3ZdbteXtyyfw3j89qdejkjNG7AENfTC5Z+S8H\nZLUanHEL0oZTl2X1YsjQrLJSxsjpj33qxKxe96zKu4/uWYOvTa75wU9PT2/0ScDRqpLay8CQFM3A\nkBStR8HvvwJ4BdgIvAmMKbifpAIVHRgl4HAgfQ+bpE6nIzZJ6nkkRlINFR0YJWAe0AicUXAvSQUr\nepPkYGAN0B+YCywB5r/16sorN8+5w4HQ96CCF0fSVp4oPyIUHRhryj+fA24j7PTcHBhDvlBwe0lt\nGlF+NPlF9VmL3CTpBfQp/94bOApYVGA/SQUrcg1jAGGtoqnPTcB9BfaTVLAiA+NpYN8C319SByt6\nH0arPv7w/LZnauZTGQdpN3B5ehHwiX+YnFW3O+kDyfpPyRtE9tyX0wfjAazdKb0mc1wXLz+UXrP9\nQ/tk9Xohqwr2IX1g3ePT7s/q9czgrDJ2m3JEelGPnP/3v1T1FU8NlxTNwJAUzcCQFM3AkBTNwJAU\nzcCQFM3AkBTNwJAUzcCQFM3AkBTNwJAUzcCQFM3AkBStrqNV75yRPtLyzh3T+6zft/rou9b0WZlV\nBu9ML1k+Om/U6S4rssrof1nG6Njlp2b1epb0UcmvP/J6Vq8zDzwvq+7xmUcl15T6HZnVq4GfZ9U9\nel76/yOj7rwpq1c1rmFIimZgSIpmYEiKZmBIimZgSIpmYEiKZmBIimZgSIpmYEiKZmBIimZgSIpm\nYEiKZmBIipZxp9KaKT2wMb3oiAfSaxofvCC9CNj/xxdn1TU8vyC55k/sn9Vr93VZZZyXMer3z3mt\nuOWn9ybXzPjksVm9Jl6TVQa95yaXbJqQN1p1m8vz7qO7w7npo1Vf2Tmj14vvgSrZ4BqGpGgGhqRo\nBoakaAaGpGgGhqRoBoakaAaGpGgGhqRoBoakaAaGpGgGhqRoBoakaHW9VeIR2z6SXNP4vs8k14w+\nL28Q2ZLns8pg9n3JJQNHZPbKHBH23X6L04sGZ9wDEmBF+qCpibkj3TbkDewq7Zq+jA2zL8/q9dRJ\nebfF3CujpuGqq9KLTq7+kmsYkqIZGJKiFRkYxwBLgGXApAL7SOogRQXGtsAPCaExgrBVNLygXpI6\nSFGBMQZYDqwA3gRuBo4vqJekDlJUYAwCVlY8X1WeJqkLKyowSgW9r6Q6Kuo8jNXAkIrnQwhrGc1M\nq/h9P8i8EK6kdnhiZXhEKCowGoGhwB7AM8A4Wjwd5IyC2kuKNmJIeDT5+cNVZy0qMP4O/Dswh3DE\nZDrwZEG9JHWQIk8Nv7f8kNRNeKanpGgGhqRodb1VIt/KGFk4L6PTf+eNDmRs3sjHNTel9xs49/qs\nXt866fWsuvWsT66Z+ljeGf6XfiC95hsNd2f1avxe3q6y0llfTq4Zt91NWb0msDarbsotQ9qeqbm7\n9kuvudFbJUqqAQNDUjQDQ1I0A0NSNANDUjQDQ1I0A0NSNANDUjQDQ1I0A0NSNANDUjQDQ1K0+g4+\n47H0opv2Se+0R3oJQMMueXUMm5NcUppzdFarhsy7Fy7LGJN0SZ/pWb2uuz79PpClPT+Y1eu4w67P\nqrtww6nJNQe8L29w4iXL5mbVnc9nk2teezq9T+89AQefSWovA0NSNANDUjQDQ1I0A0NSNANDUjQD\nQ1I0A0NSNANDUjQDQ1I0A0NSNANDUjQDQ1K0Iu/e3qbSeekjTxtylnh13ijL0qc+k1dH+sjThsa8\nkY8Lvp53G8ih12YUzd6Y1YteGSNPH8xr9Sqzs+pG980oWpf33/78l7LKmDRwWnJN741n5DWrwjUM\nSdEMDEnRDAxJ0QwMSdEMDEnRDAxJ0QwMSdEMDEnRDAxJ0QwMSdEMDEnRDAxJ0QwMSdHqem/Vh/6W\nXvTFd9yYXHMNn05vBOxzQ979Tjeckn5v1e1ufCCr17hPr8iqu+XV05JrGj87IavX6OP2T675/onn\nZPX60P3zsupu++jC5JrXWJ/V62ObvplV1y/jn/cx3JJcs4lx4L1VJbVXUYFxEbAKeLT8OKagPpI6\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the geometry color-coded by CMFD cells\n", + "fig = plotter.plot_cmfd_cells(geometry, cmfd, gridsize=500, get_figure=True)\n", + "fig.set_figheight(4)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run Simulation" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Computing the eigenvalue...\n", + "[ NORMAL ] Iteration 0:\tk_eff = 1.463820\tres = 0.000E+00\n", + "[ NORMAL ] Iteration 1:\tk_eff = 1.378956\tres = 2.531E-01\n", + "[ NORMAL ] Iteration 2:\tk_eff = 1.300903\tres = 1.234E-01\n", + "[ NORMAL ] Iteration 3:\tk_eff = 1.249353\tres = 1.039E-01\n", + "[ NORMAL ] Iteration 4:\tk_eff = 1.219282\tres = 5.247E-02\n", + "[ NORMAL ] Iteration 5:\tk_eff = 1.202671\tres = 2.703E-02\n", + "[ NORMAL ] Iteration 6:\tk_eff = 1.193514\tres = 1.250E-02\n", + "[ NORMAL ] Iteration 7:\tk_eff = 1.188467\tres = 5.650E-03\n", + "[ NORMAL ] Iteration 8:\tk_eff = 1.185685\tres = 2.749E-03\n", + "[ NORMAL ] Iteration 9:\tk_eff = 1.184159\tres = 1.789E-03\n", + "[ NORMAL ] Iteration 10:\tk_eff = 1.183329\tres = 1.365E-03\n", + "[ NORMAL ] Iteration 11:\tk_eff = 1.182881\tres = 1.026E-03\n", + "[ NORMAL ] Iteration 12:\tk_eff = 1.182642\tres = 7.313E-04\n", + "[ NORMAL ] Iteration 13:\tk_eff = 1.182513\tres = 4.946E-04\n", + "[ NORMAL ] Iteration 14:\tk_eff = 1.182441\tres = 3.188E-04\n", + "[ NORMAL ] Iteration 15:\tk_eff = 1.182400\tres = 1.972E-04\n", + "[ NORMAL ] Iteration 16:\tk_eff = 1.182375\tres = 1.190E-04\n", + "[ NORMAL ] Iteration 17:\tk_eff = 1.182357\tres = 7.286E-05\n", + "[ NORMAL ] Iteration 18:\tk_eff = 1.182344\tres = 4.860E-05\n", + "[ NORMAL ] Iteration 19:\tk_eff = 1.182334\tres = 3.665E-05\n", + "[ NORMAL ] Iteration 20:\tk_eff = 1.182326\tres = 2.981E-05\n", + "[ NORMAL ] Iteration 21:\tk_eff = 1.182319\tres = 2.456E-05\n", + "[ NORMAL ] Iteration 22:\tk_eff = 1.182314\tres = 1.989E-05\n", + "[ NORMAL ] Iteration 23:\tk_eff = 1.182310\tres = 1.570E-05\n", + "[ NORMAL ] Iteration 24:\tk_eff = 1.182307\tres = 1.210E-05\n" + ] + } + ], + "source": [ + "solver = openmoc.CPUSolver(track_generator)\n", + "solver.setConvergenceThreshold(tolerance)\n", + "solver.setNumThreads(num_threads)\n", + "solver.computeEigenvalue(max_iters)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the FSR scalar fluxes...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/lib/pymodules/python2.7/matplotlib/collections.py:548: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", + " if self._edgecolors == 'face':\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\nEq47/i+KLytR3HUOAwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot fast, epithermal and thermal flux\n", + "figures = plotter.plot_spatial_fluxes(solver, energy_groups=[1,3,7],\n", + " gridsize=500, get_figure=True)\n", + "map(lambda fig: fig.set_figheight(4), figures)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ NORMAL ] Plotting the flat source region fission rates...\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plots FSR fission rates\n", + "fig = plotter.plot_fission_rates(solver, gridsize=250,\n", + " norm=True, get_figure=True)\n", + "fig.set_figheight(4)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/sample-input/krylov/adjoint-eigenmodes.py b/sample-input/krylov/adjoint-eigenmodes.py new file mode 100644 index 000000000..b138b3017 --- /dev/null +++ b/sample-input/krylov/adjoint-eigenmodes.py @@ -0,0 +1,57 @@ +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +options = openmoc.options.Options() +num_modes = 5 + +openmoc.log.set_log_level('NORMAL') + +openmoc.log.py_printf('TITLE', 'Computing %d adjoint eigenmodes', num_modes) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +from geometry import geometry +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +# Initialize a CPUSolver to perform adjoint fixed source calculations +cpu_solver = openmoc.CPUSolver(track_generator) +cpu_solver.setNumThreads(opts.num_omp_threads) + +# Initialize IRAMSolver to perform adjoint eigenmode calculation +iram_solver = openmoc.krylov.IRAMSolver(cpu_solver) +iram_solver.computeEigenmodes(num_modes=num_modes, solver_mode=openmoc.ADJOINT) + +# Report the adjoint eigenvalues to the user +eigenvalues = iram_solver._eigenvalues +openmoc.log.py_printf('RESULT', 'Adjoint eigenvalues: %s', str(eigenvalues)) + + +############################################################################### +# Generating Plots +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_eigenmode_fluxes(iram_solver, gridsize=250, + energy_groups=[1,2,3,4,5,6,7]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/krylov/forward-eigenmodes.py b/sample-input/krylov/forward-eigenmodes.py new file mode 100644 index 000000000..15763cdf9 --- /dev/null +++ b/sample-input/krylov/forward-eigenmodes.py @@ -0,0 +1,56 @@ +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() +num_modes = 5 + +openmoc.log.set_log_level('NORMAL') +openmoc.log.py_printf('TITLE', 'Computing %d forward eigenmodes', num_modes) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +from geometry import geometry +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +# Initialize a CPUSolver to perform forward fixed source calculations +cpu_solver = openmoc.CPUSolver(track_generator) +cpu_solver.setNumThreads(opts.num_omp_threads) + +# Initialize IRAMSolver to perform forward eigenmode calculation +iram_solver = openmoc.krylov.IRAMSolver(cpu_solver) +iram_solver.computeEigenmodes(num_modes=num_modes, solver_mode=openmoc.FORWARD) + +# Report the forward eigenvalues to the user +eigenvalues = iram_solver._eigenvalues +openmoc.log.py_printf('RESULT', 'Forward eigenvalues: %s', str(eigenvalues)) + + +############################################################################### +# Generating Plots +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_eigenmode_fluxes(iram_solver, gridsize=250, + energy_groups=[1,2,3,4,5,6,7]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/krylov/geometry.py b/sample-input/krylov/geometry.py new file mode 100644 index 000000000..c08441c51 --- /dev/null +++ b/sample-input/krylov/geometry.py @@ -0,0 +1,345 @@ +import numpy as np +import openmoc + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-64.26, name='left') +right = openmoc.XPlane(x=64.26, name='right') +top = openmoc.YPlane(y=64.26, name='top') +bottom = openmoc.YPlane(y=-64.26, name='bottom') +left.setBoundaryType(openmoc.VACUUM) +right.setBoundaryType(openmoc.VACUUM) +top.setBoundaryType(openmoc.VACUUM) +bottom.setBoundaryType(openmoc.VACUUM) +boundaries = [left, right, top, bottom] + +# Create ZCylinders for the fuel as well as to discretize the moderator into +# rings +fuel_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.54) +moderator_inner_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.58) +moderator_outer_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.62) + + +############################################################################### +# Creating Cells and Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +# Moderator rings +moderator_ring1 = openmoc.Cell() +moderator_ring2 = openmoc.Cell() +moderator_ring3 = openmoc.Cell() +moderator_ring1.setNumSectors(8) +moderator_ring2.setNumSectors(8) +moderator_ring3.setNumSectors(8) +moderator_ring1.setFill(materials['Water']) +moderator_ring2.setFill(materials['Water']) +moderator_ring3.setFill(materials['Water']) +moderator_ring1.addSurface(+1, fuel_radius) +moderator_ring1.addSurface(-1, moderator_inner_radius) +moderator_ring2.addSurface(+1, moderator_inner_radius) +moderator_ring2.addSurface(-1, moderator_outer_radius) +moderator_ring3.addSurface(+1, moderator_outer_radius) + +# UO2 pin cell +uo2_cell = openmoc.Cell() +uo2_cell.setNumRings(3) +uo2_cell.setNumSectors(8) +uo2_cell.setFill(materials['UO2']) +uo2_cell.addSurface(-1, fuel_radius) + +uo2 = openmoc.Universe(name='UO2') +uo2.addCell(uo2_cell) +uo2.addCell(moderator_ring1) +uo2.addCell(moderator_ring2) +uo2.addCell(moderator_ring3) + +# 4.3% MOX pin cell +mox43_cell = openmoc.Cell() +mox43_cell.setNumRings(3) +mox43_cell.setNumSectors(8) +mox43_cell.setFill(materials['MOX-4.3%']) +mox43_cell.addSurface(-1, fuel_radius) + +mox43 = openmoc.Universe(name='MOX-4.3%') +mox43.addCell(mox43_cell) +mox43.addCell(moderator_ring1) +mox43.addCell(moderator_ring2) +mox43.addCell(moderator_ring3) + +# 7% MOX pin cell +mox7_cell = openmoc.Cell() +mox7_cell.setNumRings(3) +mox7_cell.setNumSectors(8) +mox7_cell.setFill(materials['MOX-7%']) +mox7_cell.addSurface(-1, fuel_radius) + +mox7 = openmoc.Universe(name='MOX-7%') +mox7.addCell(mox7_cell) +mox7.addCell(moderator_ring1) +mox7.addCell(moderator_ring2) +mox7.addCell(moderator_ring3) + +# 8.7% MOX pin cell +mox87_cell = openmoc.Cell() +mox87_cell.setNumRings(3) +mox87_cell.setNumSectors(8) +mox87_cell.setFill(materials['MOX-8.7%']) +mox87_cell.addSurface(-1, fuel_radius) + +mox87 = openmoc.Universe(name='MOX-8.7%') +mox87.addCell(mox87_cell) +mox87.addCell(moderator_ring1) +mox87.addCell(moderator_ring2) +mox87.addCell(moderator_ring3) + +# Fission chamber pin cell +fission_chamber_cell = openmoc.Cell() +fission_chamber_cell.setNumRings(3) +fission_chamber_cell.setNumSectors(8) +fission_chamber_cell.setFill(materials['Fission Chamber']) +fission_chamber_cell.addSurface(-1, fuel_radius) + +fission_chamber = openmoc.Universe(name='Fission Chamber') +fission_chamber.addCell(fission_chamber_cell) +fission_chamber.addCell(moderator_ring1) +fission_chamber.addCell(moderator_ring2) +fission_chamber.addCell(moderator_ring3) + +# Guide tube pin cell +guide_tube_cell = openmoc.Cell() +guide_tube_cell.setNumRings(3) +guide_tube_cell.setNumSectors(8) +guide_tube_cell.setFill(materials['Guide Tube']) +guide_tube_cell.addSurface(-1, fuel_radius) + +guide_tube = openmoc.Universe(name='Guide Tube') +guide_tube.addCell(guide_tube_cell) +guide_tube.addCell(moderator_ring1) +guide_tube.addCell(moderator_ring2) +guide_tube.addCell(moderator_ring3) + +# Reflector +refl_cell = openmoc.Cell(name='moderator') +refl_cell.setFill(materials['Water']) + +reflector = openmoc.Universe(name='Reflector') +reflector.addCell(refl_cell) + +# Cells +assembly1_cell = openmoc.Cell(name='Assembly 1') +assembly2_cell = openmoc.Cell(name='Assembly 2') +refined_refl_cell = openmoc.Cell(name='Semi-Finely Spaced Reflector') +right_refl_cell = openmoc.Cell(name='Right Reflector') +left_refl_cell = openmoc.Cell(name='Left Reflector') +bot_right_refl_cell = openmoc.Cell(name='Bottom Right Corner Reflector') +top_right_refl_cell = openmoc.Cell(name='Top Right Corner Reflector') +bot_left_refl_cell = openmoc.Cell(name='Bottom Left Corner Reflector') +top_left_refl_cell = openmoc.Cell(name='Top Left Corner Reflector') +bot_refl_cell = openmoc.Cell(name='Bottom Reflector') +top_refl_cell = openmoc.Cell(name='Top Reflector') + +assembly1 = openmoc.Universe(name='Assembly 1') +assembly2 = openmoc.Universe(name='Assembly 2') +refined_refl = openmoc.Universe(name='Semi-Finely Spaced Moderator') +right_refl = openmoc.Universe(name='Right Reflector') +left_refl = openmoc.Universe(name='Left Reflector') +bot_right_refl = openmoc.Universe(name='Bottom Right Corner Reflector') +top_right_refl = openmoc.Universe(name='Top Right Corner Reflector') +bot_left_refl = openmoc.Universe(name='Bottom Left Corner Reflector') +top_left_refl = openmoc.Universe(name='Top Left Corner Reflector') +bot_refl = openmoc.Universe(name='Bottom Reflector') +top_refl = openmoc.Universe(name='Top Reflector') + +assembly1.addCell(assembly1_cell) +assembly2.addCell(assembly2_cell) +refined_refl.addCell(refined_refl_cell) +right_refl.addCell(right_refl_cell) +left_refl.addCell(left_refl_cell) +bot_right_refl.addCell(bot_right_refl_cell) +top_right_refl.addCell(top_right_refl_cell) +bot_left_refl.addCell(bot_left_refl_cell) +top_left_refl.addCell(top_left_refl_cell) +bot_refl.addCell(bot_refl_cell) +top_refl.addCell(top_refl_cell) + +# Root Cell/Universe +root_cell = openmoc.Cell(name='Full Geometry') +root_cell.addSurface(+1, boundaries[0]) +root_cell.addSurface(-1, boundaries[1]) +root_cell.addSurface(-1, boundaries[2]) +root_cell.addSurface(+1, boundaries[3]) + +root_universe = openmoc.Universe(name='Root Universe') +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating lattices...') + +lattices = list() + +# Top left, bottom right 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly 1')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1], + [1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + +universes = {1 : uo2, 2 : guide_tube, 3 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] +lattices[-1].setUniverses([template]) +assembly1_cell.setFill(lattices[-1]) + +# Top right, bottom left 17 x 17 assemblies +lattices.append(openmoc.Lattice(name='Assembly 2')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] +universes = {1 : mox43, 2 : mox7, 3 : mox87, + 4 : guide_tube, 5 : fission_chamber} +for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] +lattices[-1].setUniverses([template]) +assembly2_cell.setFill(lattices[-1]) + +# Sliced up water cells - semi finely spaced +lattices.append(openmoc.Lattice(name='Semi-Finely Spaced Reflector')) +lattices[-1].setWidth(width_x=0.126, width_y=0.126) +template = [[reflector] * 10] * 10 +lattices[-1].setUniverses([template]) +refined_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells - right side of geometry +lattices.append(openmoc.Lattice(name='Right Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_refl] * 11 + [reflector] * 6] * 17 +lattices[-1].setUniverses([template]) +right_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells - right side of geometry +lattices.append(openmoc.Lattice(name='Left Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[reflector] * 6 + [refined_refl] * 11] * 17 +lattices[-1].setUniverses([template]) +left_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom corner of geometry +lattices.append(openmoc.Lattice(name='Bottom Right Corner Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_refl] * 11 + [reflector] * 6] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +bot_right_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom corner of geometry +lattices.append(openmoc.Lattice(name='Top Right Corner Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[reflector] * 17] * 6 +template += [[refined_refl] * 11 + [reflector] * 6] * 11 +lattices[-1].setUniverses([template]) +top_right_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom corner of geometry +lattices.append(openmoc.Lattice(name='Bottom Left Corner Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[reflector] * 6 + [refined_refl] * 11] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +bot_left_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom corner of geometry +lattices.append(openmoc.Lattice(name='Top Left Corner Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[reflector] * 17] * 6 +template += [[reflector] * 6 + [refined_refl] * 11] * 11 +lattices[-1].setUniverses([template]) +top_left_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for bottom of geometry +lattices.append(openmoc.Lattice(name='Bottom Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[refined_refl] * 17] * 11 +template += [[reflector] * 17] * 6 +lattices[-1].setUniverses([template]) +bot_refl_cell.setFill(lattices[-1]) + +# Sliced up water cells for top of geometry +lattices.append(openmoc.Lattice(name='Top Reflector')) +lattices[-1].setWidth(width_x=1.26, width_y=1.26) +template = [[reflector] * 17] * 6 +template += [[refined_refl] * 17] * 11 +lattices[-1].setUniverses([template]) +top_refl_cell.setFill(lattices[-1]) + +# 4 x 4 core to represent two bundles and water +lattices.append(openmoc.Lattice(name='Full Geometry')) +lattices[-1].setWidth(width_x=21.42, width_y=21.42) + +lattices[-1].setUniverses([[ + [top_left_refl, top_refl, top_refl, top_refl, top_refl, top_right_refl], + [left_refl, assembly1, assembly2, assembly2, assembly1, right_refl ], + [left_refl, assembly2, assembly1, assembly1, assembly2, right_refl ], + [left_refl, assembly2, assembly1, assembly1, assembly2, right_refl ], + [left_refl, assembly1, assembly2, assembly2, assembly1, right_refl ], + [bot_left_refl, bot_refl, bot_refl, bot_refl, bot_refl, bot_right_refl]]]) +root_cell.setFill(lattices[-1]) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) diff --git a/sample-input/nested-lattice/nested-lattice.py b/sample-input/nested-lattice/nested-lattice.py index 5a0814688..4e9953a0f 100644 --- a/sample-input/nested-lattice/nested-lattice.py +++ b/sample-input/nested-lattice/nested-lattice.py @@ -1,87 +1,84 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') ############################################################################### -########################### Creating Materials ############################ +# Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Importing materials data from HDF5...') - -materials = materialize.materialize('../c5g7-materials.h5') +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') ############################################################################### -########################### Creating Surfaces ############################# +# Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -left = XPlane(x=-2.0, name='left') -right = XPlane(x=2.0, name='right') -top = YPlane(y=-2.0, name='top') -bottom = YPlane(y=2.0, name='bottom') +left = openmoc.XPlane(x=-2.0, name='left') +right = openmoc.XPlane(x=2.0, name='right') +top = openmoc.YPlane(y=-2.0, name='top') +bottom = openmoc.YPlane(y=2.0, name='bottom') boundaries = [left, right, top, bottom] -large_circle = Circle(x=0.0, y=0.0, radius=0.4, name='large pin') -medium_circle = Circle(x=0.0, y=0.0, radius=0.3, name='medium pin') -small_circle = Circle(x=0.0, y=0.0, radius=0.2, name='small pin') +large_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.4, name='large pin') +medium_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.3, name='medium pin') +small_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.2, name='small pin') -for boundary in boundaries: boundary.setBoundaryType(REFLECTIVE) +for boundary in boundaries: boundary.setBoundaryType(openmoc.REFLECTIVE) ############################################################################### -############################# Creating Cells ############################## +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -large_fuel = CellBasic(name='large pin fuel', rings=3, sectors=8) -large_fuel.setMaterial(materials['UO2']) -large_fuel.addSurface(halfspace=-1, surface=large_circle) +large_fuel = openmoc.Cell(name='large pin fuel') +large_fuel.setNumRings(3) +large_fuel.setNumSectors(8) +large_fuel.setFill(materials['UO2']) +large_fuel.addSurface(halfspace=-1, surface=large_zcylinder) -large_moderator = CellBasic(name='large pin moderator', sectors=8) -large_moderator.setMaterial(materials['Water']) -large_moderator.addSurface(halfspace=+1, surface=large_circle) +large_moderator = openmoc.Cell(name='large pin moderator') +large_moderator.setNumSectors(8) +large_moderator.setFill(materials['Water']) +large_moderator.addSurface(halfspace=+1, surface=large_zcylinder) -medium_fuel = CellBasic(name='medium pin fuel', rings=3, sectors=8) -medium_fuel.setMaterial(materials['UO2']) -medium_fuel.addSurface(halfspace=-1, surface=medium_circle) +medium_fuel = openmoc.Cell(name='medium pin fuel') +medium_fuel.setNumRings(3) +medium_fuel.setNumSectors(8) +medium_fuel.setFill(materials['UO2']) +medium_fuel.addSurface(halfspace=-1, surface=medium_zcylinder) -medium_moderator = CellBasic(name='medium pin moderator', sectors=8) -medium_moderator.setMaterial(materials['Water']) -medium_moderator.addSurface(halfspace=+1, surface=medium_circle) +medium_moderator = openmoc.Cell(name='medium pin moderator') +medium_moderator.setNumSectors(8) +medium_moderator.setFill(materials['Water']) +medium_moderator.addSurface(halfspace=+1, surface=medium_zcylinder) -small_fuel = CellBasic(name='small pin fuel', rings=3, sectors=8) -small_fuel.setMaterial(materials['UO2']) -small_fuel.addSurface(halfspace=-1, surface=small_circle) +small_fuel = openmoc.Cell(name='small pin fuel') +small_fuel.setNumRings(3) +small_fuel.setNumSectors(8) +small_fuel.setFill(materials['UO2']) +small_fuel.addSurface(halfspace=-1, surface=small_zcylinder) -small_moderator = CellBasic(name='small pin moderator', sectors=8) -small_moderator.setMaterial(materials['Water']) -small_moderator.addSurface(halfspace=+1, surface=small_circle) +small_moderator = openmoc.Cell(name='small pin moderator') +small_moderator.setNumSectors(8) +small_moderator.setFill(materials['Water']) +small_moderator.addSurface(halfspace=+1, surface=small_zcylinder) -lattice_cell = CellFill(name='lattice cell') +lattice_cell = openmoc.Cell(name='lattice cell') -root_cell = CellFill(name='root cell') +root_cell = openmoc.Cell(name='root cell') root_cell.addSurface(halfspace=+1, surface=boundaries[0]) root_cell.addSurface(halfspace=-1, surface=boundaries[1]) root_cell.addSurface(halfspace=+1, surface=boundaries[2]) @@ -92,13 +89,13 @@ # Creating Universes ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -pin1 = Universe(name='large pin cell') -pin2 = Universe(name='medium pin cell') -pin3 = Universe(name='small pin cell') -assembly = Universe(name='2x2 lattice') -root_universe = Universe(name='root universe') +pin1 = openmoc.Universe(name='large pin cell') +pin2 = openmoc.Universe(name='medium pin cell') +pin3 = openmoc.Universe(name='small pin cell') +assembly = openmoc.Universe(name='2x2 lattice') +root_universe = openmoc.Universe(name='root universe') pin1.addCell(large_fuel) pin1.addCell(large_moderator) @@ -111,68 +108,66 @@ ############################################################################### -########################### Creating Lattices ############################# +# Creating Lattices ############################################################################### -log.py_printf('NORMAL', 'Creating nested 2 x 2 lattices...') +openmoc.log.py_printf('NORMAL', 'Creating nested 2 x 2 lattices...') # 2x2 assembly -lattice = Lattice(name='2x2 lattice') +lattice = openmoc.Lattice(name='2x2 lattice') lattice.setWidth(width_x=1.0, width_y=1.0) -lattice.setUniverses([[pin1, pin2], [pin1, pin3]]) +lattice.setUniverses([[[pin1, pin2], [pin1, pin3]]]) lattice_cell.setFill(lattice) # 2x2 core -core = Lattice(name='2x2 core') +core = openmoc.Lattice(name='2x2 core') core.setWidth(width_x=2.0, width_y=2.0) -core.setUniverses([[assembly, assembly], [assembly, assembly]]) +core.setUniverses([[[assembly, assembly], [assembly, assembly]]]) root_cell.setFill(core) ############################################################################### -########################## Creating the Geometry ########################## +# Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_segments(track_generator) -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/pin-cell/pin-cell.py b/sample-input/pin-cell/pin-cell.py index 811b169b3..a1d41b2c7 100644 --- a/sample-input/pin-cell/pin-cell.py +++ b/sample-input/pin-cell/pin-cell.py @@ -1,65 +1,54 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') ############################################################################### -########################### Creating Materials ############################ +# Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Importing materials data from HDF5...') +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') -materials = materialize.materialize('../c5g7-materials.h5') +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') ############################################################################### -########################### Creating Surfaces ############################# +# Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -circle = Circle(x=0.0, y=0.0, radius=1.0, name='pin') -left = XPlane(x=-2.0, name='left') -right = XPlane(x=2.0, name='right') -top = YPlane(y=2.0, name='top') -bottom = YPlane(y=-2.0, name='bottom') +zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=1.0, name='pin') +left = openmoc.XPlane(x=-2.0, name='left') +right = openmoc.XPlane(x=2.0, name='right') +top = openmoc.YPlane(y=2.0, name='top') +bottom = openmoc.YPlane(y=-2.0, name='bottom') -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(REFLECTIVE) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(REFLECTIVE) +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) ############################################################################### -############################# Creating Cells ############################## +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -fuel = CellBasic(name='fuel') -fuel.setMaterial(materials['UO2']) -fuel.addSurface(halfspace=-1, surface=circle) +fuel = openmoc.Cell(name='fuel') +fuel.setFill(materials['UO2']) +fuel.addSurface(halfspace=-1, surface=zcylinder) -moderator = CellBasic(name='moderator') -moderator.setMaterial(materials['Water']) -moderator.addSurface(halfspace=+1, surface=circle) +moderator = openmoc.Cell(name='moderator') +moderator.setFill(materials['Water']) +moderator.addSurface(halfspace=+1, surface=zcylinder) moderator.addSurface(halfspace=+1, surface=left) moderator.addSurface(halfspace=-1, surface=right) moderator.addSurface(halfspace=+1, surface=bottom) @@ -67,60 +56,63 @@ ############################################################################### -########################### Creating Universes ############################ +# Creating Universes ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -root_universe = Universe(name='root universe') +root_universe = openmoc.Universe(name='root universe') root_universe.addCell(fuel) root_universe.addCell(moderator) ############################################################################### -########################## Creating the Geometry ########################## +# Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_segments(track_generator) -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_quadrature(solver) +openmoc.plotter.plot_tracks(track_generator) +openmoc.plotter.plot_segments(track_generator) +openmoc.plotter.plot_materials(geometry) +openmoc.plotter.plot_cells(geometry) +openmoc.plotter.plot_flat_source_regions(geometry) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_energy_fluxes(solver, fsrs=range(geometry.getNumFSRs())) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/point-source/point-source.py b/sample-input/point-source/point-source.py new file mode 100644 index 000000000..6dc80e951 --- /dev/null +++ b/sample-input/point-source/point-source.py @@ -0,0 +1,146 @@ +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left = openmoc.XPlane(x=-20.0, name='left') +right = openmoc.XPlane(x=20.0, name='right') +top = openmoc.YPlane(y=20.0, name='top') +bottom = openmoc.YPlane(y=-20.0, name='bottom') +boundaries = [left, right, top, bottom] + +for boundary in boundaries: boundary.setBoundaryType(openmoc.VACUUM) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +water_cell = openmoc.Cell(name='water') +water_cell.setFill(materials['Water']) + +source_cell = openmoc.Cell(name='source') +source_cell.setFill(materials['Water']) + +root_cell = openmoc.Cell(name='root cell') +root_cell.addSurface(halfspace=+1, surface=left) +root_cell.addSurface(halfspace=-1, surface=right) +root_cell.addSurface(halfspace=+1, surface=bottom) +root_cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +water_univ = openmoc.Universe(name='water') +source_univ = openmoc.Universe(name='source') +root_universe = openmoc.Universe(name='root universe') + +water_univ.addCell(water_cell) +source_univ.addCell(source_cell) +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +# Number of lattice cells +num_x = 200 +num_y = 200 + +# Compute widths of each lattice cell +width_x = (root_universe.getMaxX() - root_universe.getMinX()) / num_y +width_y = (root_universe.getMaxY() - root_universe.getMinY()) / num_x + +# Create 2D array of Universes in each lattice cell +universes = [[[water_univ]*num_x for _ in range(num_y)]] + +# Place fixed source Universe at (x=10, y=10) +source_x = 10 +source_y = 10 +lat_x = (root_universe.getMaxX() - source_x) / width_x +lat_y = (root_universe.getMaxY() - source_y) / width_y +universes[0][int(lat_x)][int(lat_y)] = source_univ + +openmoc.log.py_printf('NORMAL', \ + 'Creating a {0}x{0} lattice...'.format(num_x, num_y)) + +lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) +lattice.setWidth(width_x=width_x, width_y=width_y) +lattice.setUniverses(universes) +root_cell.setFill(lattice) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.setFixedSourceByCell(source_cell, 1, 1.0) +solver.computeSource(opts.max_iters) +solver.printTimerReport() + + +############################################################################### +# Generating Plots +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=250) +openmoc.plotter.plot_cells(geometry, gridsize=250) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=250) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/simple-lattice/simple-lattice.py b/sample-input/simple-lattice/simple-lattice.py index cd564b90b..e4ac3f3ea 100644 --- a/sample-input/simple-lattice/simple-lattice.py +++ b/sample-input/simple-lattice/simple-lattice.py @@ -1,84 +1,82 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - +import openmoc ############################################################################### -####################### Main Simulation Parameters ######################## +# Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') ############################################################################### -########################### Creating Materials ############################ +# Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Importing materials data from HDF5...') +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') -materials = materialize.materialize('../c5g7-materials.h5') +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') ############################################################################### -########################### Creating Surfaces ############################# +# Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -left = XPlane(x=-2.0, name='left') -right = XPlane(x=2.0, name='right') -top = YPlane(y=-2.0, name='top') -bottom = YPlane(y=2.0, name='bottom') -boundaries = [left, right, top, bottom] +left = openmoc.XPlane(x=-2.0, name='left') +right = openmoc.XPlane(x=2.0, name='right') +bottom = openmoc.YPlane(y=-2.0, name='bottom') +top = openmoc.YPlane(y=2.0, name='top') +boundaries = [left, right, bottom, top] -large_circle = Circle(x=0.0, y=0.0, radius=0.4, name='large pin') -medium_circle = Circle(x=0.0, y=0.0, radius=0.3, name='medium pin') -small_circle = Circle(x=0.0, y=0.0, radius=0.2, name='small pin') +large_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.4, name='large pin') +medium_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.3, name='medium pin') +small_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.2, name='small pin') -for boundary in boundaries: boundary.setBoundaryType(REFLECTIVE) +for boundary in boundaries: boundary.setBoundaryType(openmoc.PERIODIC) ############################################################################### -############################# Creating Cells ############################## +# Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -large_fuel = CellBasic(name='large pin fuel', rings=3, sectors=8) -large_fuel.setMaterial(materials['UO2']) -large_fuel.addSurface(halfspace=-1, surface=large_circle) +large_fuel = openmoc.Cell(name='large pin fuel') +large_fuel.setNumRings(3) +large_fuel.setNumSectors(8) +large_fuel.setFill(materials['UO2']) +large_fuel.addSurface(halfspace=-1, surface=large_zcylinder) -large_moderator = CellBasic(name='large pin moderator', sectors=8) -large_moderator.setMaterial(materials['Water']) -large_moderator.addSurface(halfspace=+1, surface=large_circle) +large_moderator = openmoc.Cell(name='large pin moderator') +large_fuel.setNumSectors(8) +large_moderator.setFill(materials['Water']) +large_moderator.addSurface(halfspace=+1, surface=large_zcylinder) -medium_fuel = CellBasic(name='medium pin fuel', rings=3, sectors=8) -medium_fuel.setMaterial(materials['UO2']) -medium_fuel.addSurface(halfspace=-1, surface=medium_circle) +medium_fuel = openmoc.Cell(name='medium pin fuel') +medium_fuel.setNumRings(3) +medium_fuel.setNumSectors(8) +medium_fuel.setFill(materials['UO2']) +medium_fuel.addSurface(halfspace=-1, surface=medium_zcylinder) -medium_moderator = CellBasic(name='medium pin moderator', sectors=8) -medium_moderator.setMaterial(materials['Water']) -medium_moderator.addSurface(halfspace=+1, surface=medium_circle) +medium_moderator = openmoc.Cell(name='medium pin moderator') +medium_moderator.setNumSectors(8) +medium_moderator.setFill(materials['Water']) +medium_moderator.addSurface(halfspace=+1, surface=medium_zcylinder) -small_fuel = CellBasic(name='small pin fuel', rings=3, sectors=8) -small_fuel.setMaterial(materials['UO2']) -small_fuel.addSurface(halfspace=-1, surface=small_circle) +small_fuel = openmoc.Cell(name='small pin fuel') +small_fuel.setNumRings(3) +small_fuel.setNumSectors(8) +small_fuel.setFill(materials['UO2']) +small_fuel.addSurface(halfspace=-1, surface=small_zcylinder) -small_moderator = CellBasic(name='small pin moderator', sectors=8) -small_moderator.setMaterial(materials['Water']) -small_moderator.addSurface(halfspace=+1, surface=small_circle) +small_moderator = openmoc.Cell(name='small pin moderator') +small_moderator.setNumSectors(8) +small_moderator.setFill(materials['Water']) +small_moderator.addSurface(halfspace=+1, surface=small_zcylinder) -root_cell = CellFill(name='root cell') +root_cell = openmoc.Cell(name='root cell') root_cell.addSurface(halfspace=+1, surface=boundaries[0]) root_cell.addSurface(halfspace=-1, surface=boundaries[1]) root_cell.addSurface(halfspace=+1, surface=boundaries[2]) @@ -89,12 +87,12 @@ # Creating Universes ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -pin1 = Universe(name='large pin cell') -pin2 = Universe(name='medium pin cell') -pin3 = Universe(name='small pin cell') -root_universe = Universe(name='root universe') +pin1 = openmoc.Universe(name='large pin cell') +pin2 = openmoc.Universe(name='medium pin cell') +pin3 = openmoc.Universe(name='small pin cell') +root_universe = openmoc.Universe(name='root universe') pin1.addCell(large_fuel) pin1.addCell(large_moderator) @@ -106,62 +104,63 @@ ############################################################################### -########################### Creating Lattices ############################# +# Creating Lattices ############################################################################### -log.py_printf('NORMAL', 'Creating simple 4 x 4 lattice...') +openmoc.log.py_printf('NORMAL', 'Creating simple 4 x 4 lattice...') -lattice = Lattice(name='4x4 lattice') +lattice = openmoc.Lattice(name='4x4 lattice') lattice.setWidth(width_x=1.0, width_y=1.0) -lattice.setUniverses([[pin1, pin2, pin1, pin2], - [pin2, pin3, pin2, pin3], - [pin1, pin2, pin1, pin2], - [pin2, pin3, pin2, pin3]]) +lattice.setUniverses([[[pin1, pin2, pin1, pin2], + [pin2, pin3, pin2, pin3], + [pin1, pin2, pin1, pin2], + [pin2, pin3, pin2, pin3]]]) root_cell.setFill(lattice) ############################################################################### -########################## Creating the Geometry ########################## +# Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() + ############################################################################### -######################## Creating the TrackGenerator ###################### +# Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() + ############################################################################### -########################### Running a Simulation ########################## +# Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### -############################ Generating Plots ############################# +# Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_segments(track_generator) -#plotter.plot_materials(geometry, gridsize=500) -#plotter.plot_cells(geometry, gridsize=500) -#plotter.plot_flat_source_regions(geometry, gridsize=500) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_segments(track_generator) +openmoc.plotter.plot_materials(geometry, gridsize=500) +openmoc.plotter.plot_cells(geometry, gridsize=500) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=500, centroids=True) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/sph-factors/pin-cell/compute-mgxs.py b/sample-input/sph-factors/pin-cell/compute-mgxs.py new file mode 100644 index 000000000..5e7df7cf4 --- /dev/null +++ b/sample-input/sph-factors/pin-cell/compute-mgxs.py @@ -0,0 +1,25 @@ +import openmc +import openmc.mgxs + +# Load the last statepoint file +sp = openmc.StatePoint('statepoint.100.h5') +su = openmc.Summary('summary.h5') +sp.link_with_summary(su) + +# Instantiate a 16-group EnergyGroups object +groups = openmc.mgxs.EnergyGroups() +groups.group_edges = [0., 0.03e-6, 0.058e-6, 0.14e-6, 0.28e-6, 0.35e-6, + 0.625e-6, 0.85e-6, 0.972e-6, 1.02e-6, 1.097e-6, + 1.15e-6, 1.3e-6, 4.e-6, 5.53e-3, 821.e-3, 20.] + +# Initialize an 2-group MGXS Library for OpenMOC +mgxs_lib = openmc.mgxs.Library(su.openmc_geometry) +mgxs_lib.energy_groups = groups +mgxs_lib.mgxs_types = ['total', 'nu-fission', 'nu-scatter matrix', 'chi'] +mgxs_lib.domain_type = 'cell' +mgxs_lib.correction = None +mgxs_lib.build_library() +mgxs_lib.load_from_statepoint(sp) + +# Store library and its MGXS objects in a pickled binary file +mgxs_lib.dump_to_file(filename='mgxs', directory='.') \ No newline at end of file diff --git a/sample-input/sph-factors/pin-cell/mgxs.pkl b/sample-input/sph-factors/pin-cell/mgxs.pkl new file mode 100644 index 000000000..a83dc00c4 --- /dev/null +++ b/sample-input/sph-factors/pin-cell/mgxs.pkl @@ -0,0 +1,7699 @@ +ccopy_reg +_reconstructor +p0 +(copenmc.mgxs.library +Library +p1 +c__builtin__ +object +p2 +Ntp3 +Rp4 +(dp5 +S'_all_mgxs' +p6 +ccollections +OrderedDict +p7 +((lp8 +(lp9 +I10000 +ag7 +((lp10 +(lp11 +S'total' +p12 +ag0 +(copenmc.mgxs.mgxs +TotalXS +p13 +g2 +Ntp14 +Rp15 +(dp16 +S'_domain' +p17 +g0 +(copenmc.universe +Cell +p18 +g2 +Ntp19 +Rp20 +(dp21 +S'_translation' +p22 +NsS'_type' +p23 +S'normal' +p24 +sS'_rotation' +p25 +NsS'_fill' +p26 +g0 +(copenmc.material +Material +p27 +g2 +Ntp28 +Rp29 +(dp30 +S'_density_units' +p31 +S'atom/b-cm' +p32 +sS'_density' +p33 +cnumpy.core.multiarray +scalar +p34 +(cnumpy +dtype +p35 +(S'f8' +p36 +I0 +I1 +tp37 +Rp38 +(I3 +S'<' +p39 +NNNI-1 +I-1 +I0 +tp40 +bS'\x91kq\xc8\xb4\x9e\xb1?' +p41 +tp42 +Rp43 +sS'_sab' +p44 +(lp45 +sS'_name' +p46 +VUO2 Fuel +p47 +sS'_nuclides' +p48 +g7 +((lp49 +(lp50 +VU-235 +p51 +a(g0 +(copenmc.nuclide +Nuclide +p52 +g2 +Ntp53 +Rp54 +(dp55 +S'_xs' +p56 +V71c +p57 +sS'_scattering' +p58 +NsS'_zaid' +p59 +Nsg46 +g51 +sbg34 +(g38 +S'sA3\xd9TLB?' +p60 +tp61 +Rp62 +S'ao' +p63 +tp64 +aa(lp65 +VU-238 +p66 +a(g0 +(g52 +g2 +Ntp67 +Rp68 +(dp69 +g56 +V71c +p70 +sg58 +Nsg59 +Nsg46 +g66 +sbg34 +(g38 +S'\x9e>\xb3\x9b\xeb\xf4\x96?' +p71 +tp72 +Rp73 +g63 +tp74 +aa(lp75 +VO-16 +p76 +a(g0 +(g52 +g2 +Ntp77 +Rp78 +(dp79 +g56 +V71c +p80 +sg58 +Nsg59 +Nsg46 +g76 +sbg34 +(g38 +S'\xcej\xa4o\xc2y\xa7?' +p81 +tp82 +Rp83 +g63 +tp84 +aatp85 +Rp86 +sS'_elements' +p87 +g7 +((lp88 +tp89 +Rp90 +sS'_convert_to_distrib_comps' +p91 +I00 +sS'_distrib_otf_file' +p92 +NsS'_id' +p93 +I10000 +sbsS'_distribcell_index' +p94 +Nsg46 +Vfuel +p95 +sS'_region' +p96 +g0 +(copenmc.surface +Halfspace +p97 +g2 +Ntp98 +Rp99 +(dp100 +S'_surface' +p101 +g0 +(copenmc.surface +ZCylinder +p102 +g2 +Ntp103 +Rp104 +(dp105 +g23 +S'z-cylinder' +p106 +sS'_coeffs' +p107 +(dp108 +S'y0' +p109 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p110 +tp111 +Rp112 +sS'x0' +p113 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p114 +tp115 +Rp116 +sS'R' +p117 +g34 +(g38 +S'DL\x89$z\x19\xd9?' +p118 +tp119 +Rp120 +ssg46 +VFuel OR +p121 +sS'_boundary_type' +p122 +Vtransmission +p123 +sg93 +I10000 +sS'_coeff_keys' +p124 +(lp125 +g113 +ag109 +ag117 +asbsS'_side' +p126 +S'-' +p127 +sbsS'_offsets' +p128 +Nsg93 +I10000 +sbsS'_sparse' +p129 +I00 +sS'_domain_type' +p130 +S'cell' +p131 +sS'_tally_trigger' +p132 +NsS'_rxn_type' +p133 +g12 +sg46 +S'' +p134 +sg48 +NsS'_energy_groups' +p135 +g0 +(copenmc.mgxs.groups +EnergyGroups +p136 +g2 +Ntp137 +Rp138 +(dp139 +S'_group_edges' +p140 +cnumpy.core.multiarray +_reconstruct +p141 +(cnumpy +ndarray +p142 +(I0 +tp143 +S'b' +p144 +tp145 +Rp146 +(I1 +(I17 +tp147 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p148 +tp149 +bsbsS'_xs_tally' +p150 +NsS'_tallies' +p151 +g7 +((lp152 +(lp153 +S'flux' +p154 +ag0 +(copenmc.tallies +Tally +p155 +g2 +Ntp156 +Rp157 +(dp158 +S'_derived' +p159 +I01 +sS'_filters' +p160 +(lp161 +g0 +(copenmc.filter +Filter +p162 +g2 +Ntp163 +Rp164 +(dp165 +S'_bins' +p166 +g141 +(g142 +(I0 +tp167 +g144 +tp168 +Rp169 +(I1 +(I1 +tp170 +g35 +(S'i8' +p171 +I0 +I1 +tp172 +Rp173 +(I3 +S'<' +p174 +NNNI-1 +I-1 +I0 +tp175 +bI00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p176 +tp177 +bsS'_mesh' +p178 +Nsg23 +Vcell +p179 +sS'_stride' +p180 +I16 +sS'_num_bins' +p181 +I1 +sbag0 +(g162 +g2 +Ntp182 +Rp183 +(dp184 +g166 +g141 +(g142 +(I0 +tp185 +g144 +tp186 +Rp187 +(I1 +(I17 +tp188 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p189 +tp190 +bsg178 +Nsg23 +Venergy +p191 +sg180 +I1 +sg181 +I16 +sbasS'_sp_filename' +p192 +Vstatepoint.100.h5 +p193 +sS'_triggers' +p194 +(lp195 +sg129 +I00 +sS'_sum_sq' +p196 +g141 +(g142 +(I0 +tp197 +g144 +tp198 +Rp199 +(I1 +(I16 +I1 +I1 +tp200 +g38 +I00 +S"NI\x17\x1f\x15\xf3!@\x91\xb4\xf2Z]j1@EV\x0b\xdf\x82+C@\xa0_'&\x8f\x99 @\x03\xff\x0b\x15\xc6K\xe3?\x12\x04\xe5z\xd6\x08\x11@<\xedc\xa1^}\xf2?\xfc\x08\r\x91\xe9\xec\xca?\xde\xc2q\x03\xc5I\x9b?2\xfa\x0f\x0e\xef5\xae?\xa7@\xab\x1aM\xbf\x98?\x8e\xbfl\x7f\xdf\xee\xc5?[\\\x95/\x86\x7f,@\xca5\xe6[\xa8g\x87@\x80Wq~#:\x9c@LB!\xcd\x14\xa1\x90@" +p201 +tp202 +bsS'_std_dev' +p203 +g141 +(g142 +(I0 +tp204 +g144 +tp205 +Rp206 +(I1 +(I16 +I1 +I1 +tp207 +g38 +I00 +S"9m\xd9 \xc5\x93*?\x97\x1d\xb3\xae\xae\xa14?\x8a\xfbH\x1d\xf2\xbd;?!\x96\x9bv\x8ay0?\xb9olu.} ?\x02\xdd$=8\x97)?2k+\xaf\xd4\xa4#?\xbe\x1f\xb3uF\x9b\x18?\x018\x8d3N?\n?\xf8\x9bo8\xf6*\x10?C\xf7\x08\x85\xebR\t?v\x81yik\xcb\x17?\xcd/\x0bE\xe7\xe43?\x1dT\x11\xbe:\xc7I?:\\>\xee'@S?0>\xdb<\xf9\xf7W?" +p208 +tp209 +bsg46 +V +p210 +sS'_mean' +p211 +g141 +(g142 +(I0 +tp212 +g144 +tp213 +Rp214 +(I1 +(I16 +I1 +I1 +tp215 +g38 +I00 +S"\xcd\x154\xb5\xb65\xd4?n\x90c\xd1\x08'\xdc?0Z\xa3|\xb4\xe2\xe4?Rnq\xf9Uo\xd3?P}\xd1\xa5\xc9\xf3\xb4?\x87\xbbx\xaf\xad\xd7\xcb?\xeb`\xd7B\x93\x01\xbd?9\x95gG\xaa\xbf\xa8?ko~\xc5\x1f\x9d\x91?w\xc73\xb3s6\x9a?\xa1t\x1a\xe1\x05\xc6\x90?\xa4\x87E\xcd\x13V\xa6?\xff\xde\xef\xf0\xfev\xd9?Z\x82\x1f\x8c\xef\x13\x07@pT\xc5\x1a\xc2\xeb\x11@\xf6]E\xed\x91\x82\x0b@" +p216 +tp217 +bsS'_num_realizations' +p218 +g34 +(g35 +(S'i4' +p219 +I0 +I1 +tp220 +Rp221 +(I3 +S'<' +p222 +NNNI-1 +I-1 +I0 +tp223 +bS'Z\x00\x00\x00' +p224 +tp225 +Rp226 +sg48 +(lp227 +g0 +(g52 +g2 +Ntp228 +Rp229 +(dp230 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p231 +sbasS'_sum' +p232 +g141 +(g142 +(I0 +tp233 +g144 +tp234 +Rp235 +(I1 +(I16 +I1 +I1 +tp236 +g38 +I00 +S"\xa8>\xd1\xee\x88k<@\x8d\x01:3r\xcbC@\xd3\xb6E\xcf\xcd^M@$\x83\xc7\xe6\x90T;@9\x98.\x91\xd3v\x1d@\xdb\xe3`\x1f\xa6\x933@%p\xff\x8a\x1be$@\xec\xd44\xba\xc3f\x11@\xae\xcc\xb9\xad\xf4\xc4\xf8?@h\x00ZIn\x02@\x024\x8dDx\x96\xf7?\xbf\xc6\xa9\xd8\x0bi\x0f@\xcb\xa8hA\xab\xe7A@\xa7'\x86n\x04:p@\xbd~\xa5\xf5\x883y@\x11\xc6\xd4\x9a\xceWs@" +p237 +tp238 +bsS'_estimator' +p239 +Vtracklength +p240 +sS'_with_batch_statistics' +p241 +I00 +sS'_results_read' +p242 +I01 +sS'_scores' +p243 +(lp244 +Vflux +p245 +asg93 +I10002 +sS'_with_summary' +p246 +I01 +sbaa(lp247 +g12 +ag0 +(g155 +g2 +Ntp248 +Rp249 +(dp250 +g159 +I01 +sg160 +(lp251 +g0 +(g162 +g2 +Ntp252 +Rp253 +(dp254 +g166 +g141 +(g142 +(I0 +tp255 +g144 +tp256 +Rp257 +(I1 +(I1 +tp258 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p259 +tp260 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp261 +Rp262 +(dp263 +g166 +g141 +(g142 +(I0 +tp264 +g144 +tp265 +Rp266 +(I1 +(I17 +tp267 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p268 +tp269 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp270 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp271 +g144 +tp272 +Rp273 +(I1 +(I16 +I1 +I1 +tp274 +g38 +I00 +S'R*\xc96I\x13!@"\x999\xa1^R"@\xe7\xac\xe3\xbc\xb8],@n\x05n\x88\x06Y\x03@\xf0\x10,<\x89\xd7\xc5?8\xc9\n\xea\x19\xd3\xed?\xfc\x9eT\x87Kz\xcc?\xf7Q#\x0f\xa3\x94\xa4?t\x8e\xa1\xd2?tu?*\xa2;h\xbe:\x89?\xc6\xc6@\xfe\xdfHv?\xf9)\xcb\'j\xf2\xa0?\xef\xbe\x07(\xcd\xff\x02@\xc7\xe6\xe2j\x14\xe0l@\xbfE_\x1a,\xd5t@\x07Dx\x9e7\xf4S@' +p275 +tp276 +bsg203 +g141 +(g142 +(I0 +tp277 +g144 +tp278 +Rp279 +(I1 +(I16 +I1 +I1 +tp280 +g38 +I00 +S"q4\xe0%\xab\x16*?\xf6\xe0\xa1\xfd&\xc4-?\xa8\x97s\xde\xf9\xf40?\xec\xde\x8d/9\xca!?\x9f\x83$\xff\xe4\x97\x11?\xe76=\xf6\xb8\x04\x18?\x99\xf7\xbdQg;\x11?\x01\xb5}F\xa4\x83\x05?\xf4\x08S\x03\x1eF\xf7>\xcf:~\x04\xf9\x8e\xfd>\x04/\xb0*\xb5\x0b\xf8>\x1f\xde\x9az\x03\x0e\x05?\r\xda\x97\x04\xa07 ?\xa8\xad\x8eH%S??'S\xa0c}{@?\xcf\xf4\x0c\xfc\xdeQ:?" +p281 +tp282 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp283 +g144 +tp284 +Rp285 +(I1 +(I16 +I1 +I1 +tp286 +g38 +I00 +S'O\xc9\x05\xa9&\xb6\xd3?\xd3\xdf\x10>\x0fk\xd4?\xd4U\xbd\xe8\xebg\xd9?\xfa\xac*\xd6`\xfb\xc4?\xabi\x93\x84\xadJ\xa6?\x8d]\xb4=\xeb\x0c\xba?\x11\x0f\xb8.Rt\xa9?|\x15?\x14\x1c\xa3\x95?\x7f\x03\xa6\xeaQ<\x7f?\xf3`@rT\xf4\x87?\xa4\xbb\x06\x95\x8c\xd5\x7f?o\xdb\\#A\xa2\x93?\x03\x8f\xb4\x9d\xcd\xca\xc4?\x12\xb7\x19\x1f#\xa2\xf9?!%5\xd9\x9c\xca\xfe?\xb3Y\xe5y\x89"\xee?' +p287 +tp288 +bsg218 +g226 +sg48 +(lp289 +g0 +(g52 +g2 +Ntp290 +Rp291 +(dp292 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp293 +g144 +tp294 +Rp295 +(I1 +(I16 +I1 +I1 +tp296 +g38 +I00 +S'\x17#\xb0]&\xb8;@\xc1\xbaGo\x8d\xb6<@Y \xa5\xdf\x11\xddA@?\x03,-\x80\x81-@\x99Lo\x02\x04Y\x0f@\xc7\xd1bg\x15Q"@\x98j\xd9\xc8\xc9\xe5\x11@6\xb6x|_m\xfe?u\xba\xfc\x98i\xf6\xe5?+DU`\xcb\xd7\xf0?\xef\xbb\xc8\xd8&b\xe6?\x94\x94\xba\x99+\x9c\xfb?\x1c\xe9\xc5%1=-@\xb9\x14\xde\xb1\x00\x06b@\x1b^\xb9Hv\xa6e@\x12C\xb5\xa9H0U@' +p297 +tp298 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp299 +Vtotal +p300 +asg93 +I10003 +sg246 +I01 +sbaatp301 +Rp302 +sS'_by_nuclide' +p303 +I00 +sS'_rxn_rate_tally' +p304 +Nsbaa(lp305 +S'nu-fission' +p306 +ag0 +(copenmc.mgxs.mgxs +NuFissionXS +p307 +g2 +Ntp308 +Rp309 +(dp310 +g17 +g20 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +S'nu-fission' +p311 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp312 +(lp313 +g154 +ag0 +(g155 +g2 +Ntp314 +Rp315 +(dp316 +g159 +I01 +sg160 +(lp317 +g0 +(g162 +g2 +Ntp318 +Rp319 +(dp320 +g166 +g141 +(g142 +(I0 +tp321 +g144 +tp322 +Rp323 +(I1 +(I1 +tp324 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p325 +tp326 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp327 +Rp328 +(dp329 +g166 +g141 +(g142 +(I0 +tp330 +g144 +tp331 +Rp332 +(I1 +(I17 +tp333 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p334 +tp335 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp336 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp337 +g144 +tp338 +Rp339 +(I1 +(I16 +I1 +I1 +tp340 +g38 +I00 +S"NI\x17\x1f\x15\xf3!@\x91\xb4\xf2Z]j1@EV\x0b\xdf\x82+C@\xa0_'&\x8f\x99 @\x03\xff\x0b\x15\xc6K\xe3?\x12\x04\xe5z\xd6\x08\x11@<\xedc\xa1^}\xf2?\xfc\x08\r\x91\xe9\xec\xca?\xde\xc2q\x03\xc5I\x9b?2\xfa\x0f\x0e\xef5\xae?\xa7@\xab\x1aM\xbf\x98?\x8e\xbfl\x7f\xdf\xee\xc5?[\\\x95/\x86\x7f,@\xca5\xe6[\xa8g\x87@\x80Wq~#:\x9c@LB!\xcd\x14\xa1\x90@" +p341 +tp342 +bsg203 +g141 +(g142 +(I0 +tp343 +g144 +tp344 +Rp345 +(I1 +(I16 +I1 +I1 +tp346 +g38 +I00 +S"9m\xd9 \xc5\x93*?\x97\x1d\xb3\xae\xae\xa14?\x8a\xfbH\x1d\xf2\xbd;?!\x96\x9bv\x8ay0?\xb9olu.} ?\x02\xdd$=8\x97)?2k+\xaf\xd4\xa4#?\xbe\x1f\xb3uF\x9b\x18?\x018\x8d3N?\n?\xf8\x9bo8\xf6*\x10?C\xf7\x08\x85\xebR\t?v\x81yik\xcb\x17?\xcd/\x0bE\xe7\xe43?\x1dT\x11\xbe:\xc7I?:\\>\xee'@S?0>\xdb<\xf9\xf7W?" +p347 +tp348 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp349 +g144 +tp350 +Rp351 +(I1 +(I16 +I1 +I1 +tp352 +g38 +I00 +S"\xcd\x154\xb5\xb65\xd4?n\x90c\xd1\x08'\xdc?0Z\xa3|\xb4\xe2\xe4?Rnq\xf9Uo\xd3?P}\xd1\xa5\xc9\xf3\xb4?\x87\xbbx\xaf\xad\xd7\xcb?\xeb`\xd7B\x93\x01\xbd?9\x95gG\xaa\xbf\xa8?ko~\xc5\x1f\x9d\x91?w\xc73\xb3s6\x9a?\xa1t\x1a\xe1\x05\xc6\x90?\xa4\x87E\xcd\x13V\xa6?\xff\xde\xef\xf0\xfev\xd9?Z\x82\x1f\x8c\xef\x13\x07@pT\xc5\x1a\xc2\xeb\x11@\xf6]E\xed\x91\x82\x0b@" +p353 +tp354 +bsg218 +g226 +sg48 +(lp355 +g0 +(g52 +g2 +Ntp356 +Rp357 +(dp358 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp359 +g144 +tp360 +Rp361 +(I1 +(I16 +I1 +I1 +tp362 +g38 +I00 +S"\xa8>\xd1\xee\x88k<@\x8d\x01:3r\xcbC@\xd3\xb6E\xcf\xcd^M@$\x83\xc7\xe6\x90T;@9\x98.\x91\xd3v\x1d@\xdb\xe3`\x1f\xa6\x933@%p\xff\x8a\x1be$@\xec\xd44\xba\xc3f\x11@\xae\xcc\xb9\xad\xf4\xc4\xf8?@h\x00ZIn\x02@\x024\x8dDx\x96\xf7?\xbf\xc6\xa9\xd8\x0bi\x0f@\xcb\xa8hA\xab\xe7A@\xa7'\x86n\x04:p@\xbd~\xa5\xf5\x883y@\x11\xc6\xd4\x9a\xceWs@" +p363 +tp364 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp365 +g245 +asg93 +I10006 +sg246 +I01 +sbaa(lp366 +S'nu-fission' +p367 +ag0 +(g155 +g2 +Ntp368 +Rp369 +(dp370 +g159 +I01 +sg160 +(lp371 +g0 +(g162 +g2 +Ntp372 +Rp373 +(dp374 +g166 +g141 +(g142 +(I0 +tp375 +g144 +tp376 +Rp377 +(I1 +(I1 +tp378 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p379 +tp380 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp381 +Rp382 +(dp383 +g166 +g141 +(g142 +(I0 +tp384 +g144 +tp385 +Rp386 +(I1 +(I17 +tp387 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p388 +tp389 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp390 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp391 +g144 +tp392 +Rp393 +(I1 +(I16 +I1 +I1 +tp394 +g38 +I00 +S'\x1c[\xf9\x10_\xe4"@6]\xbaX\xa4\\\x18@YWP\x84\xad\xf1\x15@\xe0>\x0e\x96E\xad\xe0?\xc2n\xa4\xca\x19[\xa2?Mr\xed\x07l\x83\xb2?\r\x0bG\x1d\x0eP}?\xaf\x19\xe6\x0b\xeb\x16U?L\x9aJ\xaa\x87 -?v\x88#lz]J?\x95Ii<\x1d\x99@?n\x99\x02\xff\xf6&M? \n5\xf7\xdd\xfc\x82?T\x99\x97\xa9\x9a\xb9\xe5?#cG\xda\xb1\x93\x82?\x02\xe6\x10\xe4\x9fo\xe6?' +p395 +tp396 +bsg203 +g141 +(g142 +(I0 +tp397 +g144 +tp398 +Rp399 +(I1 +(I16 +I1 +I1 +tp400 +g38 +I00 +S'\x0c\xf8h\x8a\x83\x1d,?\x1e\xa9\x15\xde\xa1*(?\x13B=\x16\xc0a%?\x99\xf0\xc2\x06\xc3\x89\x10?\xb2\xab\x82\xb6\x1cC\x00?\x92\x17\x9c\x17\xca\xcc\xfb>l:\x0cG\xf3\xad\xe8>>W@\x83\xda\xd9\xde>pT\xf1 \x9e2\xd3>!\nQ1\x1bi\xde>\x95\xdc\x01\x17\xb0i\xdd>\xdb\xd5\x03\x11\x8e\x90\xdf>\x93\xf7\x94\xc8n\x9e\xe2>\xef3\xf5\xee\xd88\x06?\x1d\x12&\xa9\x14n\xc6>X\x1f#\xa8PP\x07?' +p401 +tp402 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp403 +g144 +tp404 +Rp405 +(I1 +(I16 +I1 +I1 +tp406 +g38 +I00 +S"k\x18~^\xce\xbb\xd4?\xaa\xa5\xddh\x02\xa6\xd0?:\xb3\xcf\xbe\x00\x9a\xcf?i\xe3\xe0\x97\xdcz\xb3?\xf30+\\zo\x94?\xd4\x13\x06=\x9c\x06\x9d?@\xf1\xf5\xd8\xccB\x82?\x8drmx\xbd\xf9n?|\xf5\x80&8\xbcY?\x07\t\xabt\xcf|h?i\x8f\xce\xceJmc?[\x16\x05\xc6\xde\xbfi?\t\xa05L'\xc9\x84?a\x85\xcd\xb2\xec;\xb6?\xf2\x0b\x17\x87o\x8f\x84?af\xec?P\x98\xb6?" +p407 +tp408 +bsg218 +g226 +sg48 +(lp409 +g0 +(g52 +g2 +Ntp410 +Rp411 +(dp412 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp413 +g144 +tp414 +Rp415 +(I1 +(I16 +I1 +I1 +tp416 +g38 +I00 +S'WR\xe14\x1a(=@\xf7\xb0wcsi7@\x05\n*\x86H86@\xcc?\x945\xc6d\x1b@\xd6\xbc\x9c\x11\xc4\xbc\xfc?\xf1E\xe8\xda\xa5h\x04@B\xdb\x19\x11\xf0\xad\xe9?\x8b\xf4\xac8\x99\xc7\xd5?\x9b\xac\x12{W\x18\xc2?YB\x08\xde\xc17\xd1?\xaby\xd22\xb1Q\xcb?\xb8\x93;\xa3\xe8\x1a\xd2?\ri+C\xdf:\xed?\x91\x03q\xdbDD\x1f@\xcch\xf8\xd5\xb4\xe9\xec?\xf8o\xe4\xd90\xc6\x1f@' +p417 +tp418 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp419 +Vnu-fission +p420 +asg93 +I10007 +sg246 +I01 +sbaatp421 +Rp422 +sg303 +I00 +sg304 +Nsbaa(lp423 +S'nu-scatter matrix' +p424 +ag0 +(copenmc.mgxs.mgxs +NuScatterMatrixXS +p425 +g2 +Ntp426 +Rp427 +(dp428 +g17 +g20 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +S'nu-scatter matrix' +p429 +sg46 +g134 +sg48 +NsS'_correction' +p430 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp431 +(lp432 +g154 +ag0 +(g155 +g2 +Ntp433 +Rp434 +(dp435 +g159 +I01 +sg160 +(lp436 +g0 +(g162 +g2 +Ntp437 +Rp438 +(dp439 +g166 +g141 +(g142 +(I0 +tp440 +g144 +tp441 +Rp442 +(I1 +(I1 +tp443 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p444 +tp445 +bsg178 +Nsg23 +Vcell +p446 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp447 +Rp448 +(dp449 +g166 +g141 +(g142 +(I0 +tp450 +g144 +tp451 +Rp452 +(I1 +(I17 +tp453 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p454 +tp455 +bsg178 +Nsg23 +Venergy +p456 +sg180 +I1 +sg181 +I16 +sbasg192 +Vstatepoint.100.h5 +p457 +sg194 +(lp458 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp459 +g144 +tp460 +Rp461 +(I1 +(I16 +I1 +I1 +tp462 +g38 +I00 +S'U\xd5\x8fB\xcb\xfb!@\x8f!\x14+\xd5m1@\\\x03\x04\xf7/(C@ui\x17 \xec\x9e @3\xcd\xf2\xea\xdbL\xe3?\xb6\xd4\xb4\xfb\x8a\x1c\x11@ur\xce\xad\xa7k\xf2?\xe6\x18X\xc5\x9f\x18\xcb?}\xe8\\#\xebI\x9b?\x8d.\xc7\xe5l\x81\xae?~A\x9d"$\xa6\x98?\x15\x81\xdf\xb3y"\xc6?\xd4N\xf4\xb8\x1cw,@\xab\x10\x08\x08\xb5e\x87@\xd9\xc2\x12\xaa\x13:\x9c@\xce\xa6\xba1.\xa3\x90@' +p463 +tp464 +bsg203 +g141 +(g142 +(I0 +tp465 +g144 +tp466 +Rp467 +(I1 +(I16 +I1 +I1 +tp468 +g38 +I00 +S'>\x8ba\xc5D\xef,?\x16b\xb4\x97\xfe\xcf3?g\xd40l31=?\x07\x99q\xbc\xc0\xfa4?B\x90\x86\xa5\x12~$?\x15\xf1F\xde\xb6\t/?a\xd8\x84[\xf6Y*?\xb0\\S,$Z ?\xadO\xa4{\xdd\xd9\x12?E\xad\xc8+\xc1\xb0\x17?hL\xb0\x9e\xa1n\x12?!R\x0f\xe7Fp\x1f?\xc8\xcb\xa3\x99K\xe3:?\xa7k;\x8f^vR?\xcf\x17Q\x8f70Y?\xbc5\x96\xa7\x90|W?' +p469 +tp470 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp471 +g144 +tp472 +Rp473 +(I1 +(I16 +I1 +I1 +tp474 +g38 +I00 +S'R\xad\x00%\x99:\xd4?!\xb0\xf3\x90\xd9)\xdc?\xee}\xcd\x1c\xe2\xe0\xe4?\x1b\xddY_ar\xd3?\xafXD\xe8\x11\xf4\xb4?r\x82)%\xa5\xe7\xcb?\x89X\xbb\xaa3\xf3\xbc?u\xd5M\xad\xea\xd2\xa8?\xc6\x9c\xd8S]\x9b\x91?\xe1"\x91/)U\x9a?\x0e\xb8\xb5$\x9e\xbb\x90??\xcd;*|o\xa6?Z\xc5\xa1\xbb\x18s\xd9?%\xa3\xcc\x15\xf4\x12\x07@\xf1&&\x85\xba\xeb\x11@\xe9\xa7\x89\xf7N\x84\x0b@' +p475 +tp476 +bsg218 +g34 +(g221 +S'Z\x00\x00\x00' +p477 +tp478 +Rp479 +sg48 +(lp480 +g0 +(g52 +g2 +Ntp481 +Rp482 +(dp483 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p484 +sbasg232 +g141 +(g142 +(I0 +tp485 +g144 +tp486 +Rp487 +(I1 +(I16 +I1 +I1 +tp488 +g38 +I00 +S'\xbc\xf3\x08\\gr<@\xd7W\xeb\xf9l\xcdC@\x16\xf9\x80\xf8=\\M@\xee^\x16\xee\xd8X;@\xb6\x1c\xa0.9w\x1d@\xb8/!\x1e\xe0\x9e3@@\xba\x0bT\x00[$@\x16\xba\xda\x01Mt\x11@w\x9c\xe8={\xc2\xf8?\x86\x0cr\xf5\xe0\x83\x02@\xd3\x8a\x9fc\xd6\x87\xf7?\xa0\x18d\x9b\xc6\x8c\x0f@\xc3\xbe\xedc\xed\xe4A@\xb6\xe2S\x9fS9p@\xc3\xa6=K~3y@\x10\xca\x0c\x86\x07Ys@' +p489 +tp490 +bsg239 +Vanalog +p491 +sg241 +I00 +sg242 +I01 +sg243 +(lp492 +Vflux +p493 +asg93 +I10010 +sg246 +I01 +sbaa(lp494 +S'scatter' +p495 +ag0 +(g155 +g2 +Ntp496 +Rp497 +(dp498 +g159 +I01 +sg160 +(lp499 +g0 +(g162 +g2 +Ntp500 +Rp501 +(dp502 +g166 +g141 +(g142 +(I0 +tp503 +g144 +tp504 +Rp505 +(I1 +(I1 +tp506 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p507 +tp508 +bsg178 +Nsg23 +Vcell +p509 +sg180 +I256 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp510 +Rp511 +(dp512 +g166 +g141 +(g142 +(I0 +tp513 +g144 +tp514 +Rp515 +(I1 +(I17 +tp516 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p517 +tp518 +bsg178 +Nsg23 +Venergy +p519 +sg180 +I16 +sg181 +I16 +sbag0 +(g162 +g2 +Ntp520 +Rp521 +(dp522 +g166 +g141 +(g142 +(I0 +tp523 +g144 +tp524 +Rp525 +(I1 +(I17 +tp526 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p527 +tp528 +bsg178 +Nsg23 +Venergyout +p529 +sg180 +I1 +sg181 +I16 +sbasg192 +Vstatepoint.100.h5 +p530 +sg194 +(lp531 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp532 +g144 +tp533 +Rp534 +(I1 +(I256 +I1 +I1 +tp535 +g38 +I00 +S'\xba\x9f\xb6q;L\xf1?\xd2\xb6/\xda\xc2w\x9b?h^\xc5\x9b\x19\xda\x10?\xbc\xbd\xd7\xd9\xdf|\xeb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xab\xd8\xf1\xfd\x9a\xa2?\xec\x95t\x843\xf3\xf9?\xac\xbc\xbf&\x94\x8a\xa2?\xad\x9aK!|\x1eV>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbd),\xf9_\xbc$?\xf3\xf0[\xc2\xd3\x03\xab?\xad\xce\x8a!\xe2!\x12@[+)c\xbb\xfct?\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xeb=\xecd\xc6\x94u#\x8f>\xb60\xef\x97m\xac\x91?\xfc\xaa&\x91\x07\xb6\xee?4\xa7\xb1W}\xc9=?\xf3\x05\x83m83\x80>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-\\\xa3\xa6\xdc\xcbm>\tr+i\xeemv?\x00i?D\xf5^\xa7?\x99\xec|\x98\xed\xa51?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\xcea\xe3\xa7\x9d\xf4=p\x0f\xd0X\x975*?\x94\x10\x8d\x9d\xd9vv?\x8e\x18U/L9\xe0?1\xac$\xaa\x9ei\x15?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\x0e\x86\xda\xa7\x05eA>\xcf\x87\xb7\xe2\xecc{?\x0c8\x81)\x87\xf6\xbb?`\x8f\xea\xbd\xf6\xa1\x02?\xe3A:\xdc\x11\xc5\x19>\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3\x85lv\xa6D\xd9>Z\x93:5\x1a/k?\x80\xb4\xc2\xe7\xdc\xa3\x8a?M\xb1E%I]\xf8>\xe5\xb1\x89N\x02\x1bx>)J\xff\xe0uU\x16>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x80\xe2V\xb1\x17b>\xc5Ubp\xa6\xe8\x15?2o\xc5%V$@?\x11\x84n\xe1G\xddH?\x1aS\xdc"<\xdb\xf4>\xb6\x1c?Y\xd3\xea;>N\xcea\xe3\xa7\x9d\x04>\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xea\x01x\xa5\xd3\x1cC>H\xfb\xe6G\nH\x0e?\xa7\xfc-\xf1\xa7U2?\xad\x05\xe1F\x1d\xa82?\x0b\xe4T\x1a\xd1\xf7c?F\xbe^\x1f\xeeJ\xf1>\x94\'\xd1\x11G\xbee>\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xfb=\x92\x8e\xe5\xf3\xc7\xc1\xd7>\xd5\xf3\xcd\xc2NT\x0e?Y\xb4SG\x14@\xf4>\xc2\x14\xcf[\xa8|0?\x98\x15\xb8c\x0btF?\xdbV\t\xcf\xb1\xa7\xf0>\xbc\xbd\xd7\xd9\xdf|\xeb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8\xfe\x8c\xd9\xf1\xa2\xc8>\xa1r\xa5\xce>\xb7\x19?\x90\x7f`2@\'\x0e?L\x914\xe2\xbfE2?k\x10\x7fo\xc0\x97\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\xf9T\xb7:\xc5a>\xc7\x8f\xd4*Qi\xd1>;\xb1\x0f1\xac\x82\xdb>\x83b\x08YF\x85\x12?\xcd\x1e\xe1\x14Sr\x19?\x980\xb2\x9f\xa7\xb3j?\x88\x18\xaf\xc2t\x8d\xfd?`\xec\x14\xd5a\x98\xaa>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8fG\xb7\xf8\xf09w?\xe4\xfa\xbc\x080Ge@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6\xc6(\x06BV\x88?\xef\xa3\xb9\xb8P\xecF\x05@e\xcd\x89sT:H@' +p536 +tp537 +bsg203 +g141 +(g142 +(I0 +tp538 +g144 +tp539 +Rp540 +(I1 +(I256 +I1 +I1 +tp541 +g38 +I00 +S'F\x0c\xfam`\x9e ?"\xab\x82\x8bq\xc3\xb8\xb1\xf8\x84>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+?\xf2\xdd\xd79\n?\xdcRP\x03a\x8d#?tN\xe5V*=\n?(\x07=\x95,\xe3\xb0>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00J\xfb\x9b\xd5+\x86\xe8>\xefA=\xba\xd6\xaa\x08?\xf3:of?^,?;\x924\x8d9M\xfc>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8bq\xc3\xb8\xb1\xf8\x84>\x92\'\xb1#\xec<\xc2>\t:\xd9\x0f\xd6\xe9\x04?\xeej\xae\xd4\x08\x90!?\xed\x0cyX\xb6u\xf2>\x0cs\xcc\xa2\x8f\x04\xc1>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\xa7<\xddU\xc7\xb8>Hx\xd7\x01\xd2l\xff>gk:\xcd\x12\xf4\x0c?\x9b\x0fh\x96\xb2\xae\xef>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f0F~\xd0\x89\x89>n\xf7\xd0W\xbb&\xeb>\xa3`\xeea\x15\xec\xfe>!\xbd\x8ee\xb0b\x19?\x80\xd3\x7fMD\xaa\xe3>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>5S\x04\t\xc1\x0f\xab>V&\x83\xac!\xfc\xff>`\x85\xf3\xdc\x94Q\x12?\x12\xceE\xad\xde,\xe3>\xc4\xb5q\xb2\x8f)\x9b>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9u\xc0\xfe"\xe0\xd6>\x93\x0cq\x18h\x81\xaa\xb9\x05?\x9fV\xd2-\x17A\xdf>s=\x02v\x81z\xbd>\xf3\x8e\x98\xa8:\x15\x9a>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8@\xe0\xd4\x81\xbd\xb5>\xc2\x81\xb9\x9a\xc3:\xe6>\x84\xf9?k\x064\xf0>U\x1b\x85\xce\xaeK\xf3>a\x08t\xcb\xd1\xca\xe0>\xe8\xf0\xc0I\xad\xd8\xa7>\x95\x00\xa1\'\x87\xbe\x91>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\xf51\x13/\x80\xac>\xab3\xa9\xc6\x99\xba\xe1>\xc1\x1a&\x83\x1f\xf2\xe9>\x0e\xd9\x93\xb2\x17h\xef>\xcf\xc8\x01\xc4E(\xfc>PE\xaf\xff\xf2?\xe0>\xa0\xa6t\xbc\xcc\x15\xb7>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00i\xf02\xc5\xb4Q\x8d>\x11\x81\x98\x94\x1e\x1c\xd6>\'\xf3\x984\x7f\x8b\xe3>U\x84\xf4$\xa1\x1e\xe2>Q\xe8\xbb\xa74\xc3\xef>0w\xb7F\xef\xa8\xf4>\xa1\xa6@8\xd1\xf3\xd8>\x8bq\xc3\xb8\xb1\xf8\x84>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9"\\\x07\xeb\xe0\xd1>\xa5\x8e\xfdf\x15\xf4\xe7>\x90\xc5s\x06\x7f$\xe1>u{\x0e\xd1\xc8\x15\xee>UL\xfaD\xae\xaa\xf1>\xf4\xa5\x84\xf5\r\x03\x05?a\xcd\xfc\x086M\xdb>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9K\xb5\xf9w\xbe\xb4>\xd6\x87U\xd6\x1c\x91\xd2>^XcS\xb7\n\xd5>\xb4\x0f\xc0"\xc1\xf6\xe2>,\xff\x10\x85\x16\x08\xe5>KV\xb5\xd7\'\x05\xfb>\x8d\xcb<\xdf\x03\x81$?(\xf2\xf9\xe8E*\xca>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xf6\x8247q\xff>%\xcd\xf9\xe4\xc7|B?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p\x8a\xc0;\x13\xe5\x04?\xcf\xe0\xceIl\x9eE?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ekU\xa7Ph\xc5>\xf5\xcc2\xaa`S ?\xd3\xd9\x99\x19\xac\xee7?' +p542 +tp543 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp544 +g144 +tp545 +Rp546 +(I1 +(I256 +I1 +I1 +tp547 +g38 +I00 +S'\xde[~\xcd_\x0e\xbc?\xcb\xa5\xde@n\xac\x91?$k\x85\x87\xf4\x8cK?\xc3\xc2\x98V\x7f\xd3\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x93\x8f\xca:\t\x92\x94?7a\xd53\x97.\xc1?\x0b-\xfe\xc9\xf2\x88\x94?Q\x81\xb6s%\xb3\xe8>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00yf\r\x8f\x9b\xa5U?\xcb\xa5S\x93/\xca\x98?\xb5\x18\xed\x8f\xbb\xb9\xcc?\xe8\xf0\x10\xc6O\xe3~?\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x8d>\x07\xb7\xb2\xf5\xaaY\x08?\xe4l:\x02\xb8Y\x8c?aY\xa5C\to\xba?\xc3\xbf\xb9]\xf3[b?\xe9\xd6\x06c\x93^\x00?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc7d\x94\x05\xd7\x8d\xf5>\x9c\x8f\xa74\xc4\xed\x7f?\xb9\x00\x0e\xb4\x15\x0e\x97?\x91\xf0\x94\x99\x83>\\?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\x96>\xac\x98\xc2!\xdfVX?\x06\x81\x82xJ\xf4\x7f?\x15\xc1\xb0\x9ar6\xb3?\xb6av\x8b\x0f\x15O?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>9\xbb\x01y\x89\xc4\xd7>iR\n\xba\xbd\xa4\x81?\xd7\xb7\xf5\x0fq\xd5\xa1?\xb0\xd6\'DqeD??\x1e\\v\xd7;\xb8>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\xdb\x9e\xd1\xf4\x9d0?,\x84\xd5X\xc2\xdax?U\x83\xbbd\xba\x9b\x88?k$X~U}@?&h\xdc_\xee1\xfc>\x8e\xed\xb5\xa0\xf7\xc6\xb0>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x1dUM\x10u\xef>\x97:\x9f\xc5\x03hO?7l[\x94\xd9 c?,$$\x83z\xbeg?\x8e\xbeI\xd3\xa0h>?\x0b/\x98\x83Q\xe7\xd5>\x12\x92\xf2\x80\x9f^\xa6>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00N\x81\xb6s%\xb3\xd8>\t\xe7\xa5\x13\xa7\x1eJ?\x947Kz\xb6\xd2\\?)\xa5\x05\xf3\x08\x0c]?\xd8\xdf\x12\x80\x7fJu?\x81\x12\x01\xc3A\xa4;?\xe7\x1a\x14\x1c\xc0\x97\xf1>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x9d>\xbahy\xbcT\x1d0?\x80}\xb0\xdb\xc9\x1cJ?"\x0fD\x16i\xe2=?3H\xfdD\xc7J[?\xf6\x8d\xe8\x9eu\x8df?\xab\xde\x07\r\xeaH;?\xc3\xc2\x98V\x7f\xd3\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xf9\xe4\xecN\x15\'?\xd8\xd3];\x8d\x03Q?\x01\xb9\xea\'\x89\x12J?\x81r\xb2\x98\x89\xc0\\?6\x13\xd3\x85X\xfda?\xab?\xc20`\xc9\x85?lf\xb8\xb2\xe2\xdf8?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x80\xafJ^\xec\xef>Jl+\xe3\xcc\x9c+?\xbd5\x12\xdd\x02k1?w\xb1\xde\xf7\xd1\xe5L?&i\xc2\xa7\xd7\xf1P?fi\x1c94\xa1x?\xe9\x89#^\x00V\xc2?\x8a\xa4R;%\\\x17?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe1\x7fz\x95\xf1>\x80?zP\x01\xce\x16\x01\xf6?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe2a)\xf46\x85\x87?\xf0 \xee\x88\xce#\xfe?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\xb2\xd8\xc4\x8d\x0c\x10?]\x19g\xe6\xdc\x00\xc6?\xe46\xb88\xdbz\xe7?' +p548 +tp549 +bsg218 +g34 +(g221 +S'Z\x00\x00\x00' +p550 +tp551 +Rp552 +sg48 +(lp553 +g0 +(g52 +g2 +Ntp554 +Rp555 +(dp556 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p557 +sbasg232 +g141 +(g142 +(I0 +tp558 +g144 +tp559 +Rp560 +(I1 +(I256 +I1 +I1 +tp561 +g38 +I00 +S'\x98\xd8|\\\x1b\xba#@%\x199\x0b{\xda\xf8?U\xcfI\xef\x1b_\xb3?\xf1h\xe3\x88\xb5\xf8\xf4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe7\xd9\xac\xfa\\\xed\xfc?\xb5\x10\xe4\xa0\x84)(@Wo\rl\x95\xe0\xfc?\xedR\\U\xf6]Q?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\xd8*\xc1\xe2p\xbe?\x93\xd0\x96s)n\x01@_\xb52\xe1\x9724@c\xe9C\x17\xd4\xb7\xe5?\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xf4>\xb1\xa8\xc14\x0c\x1fq?\x90\x14\x91a\x15\xef\xf3?\xd8B\x90\x83\x12\x96"@\xaa5\xcd;N\xd1\xc9?8\x9eAC\xff\x04g?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\xad\xd8_vO^?\xfa\xd0\x05\xf5-s\xe6?\x82\xd8\x99B\xe75\x00@&\xb9\xfc\x87\xf4\xdb\xc3?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x1dUM\x10u\xff>Y\xd3\xbc\xe3\x14\x1d\xc1?\xb8\xc2\xbb\\\xc4w\xe6?\x86\x8f\x88)\x91\x04\x1b@\xb4<\x0f\xee\xce\xda\xb5?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\xa47\x15\xa90\xb6@?\xe3\x83\x9e\xcd\xaa\xcf\xe8?\x87\x8aq\xfe&\x14\t@\xe7\x05\xd8G\xa7\xae\xac?D\xc58\x7f\x13\n!?\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xadd\xc7F ^\x97?\xef v\xa6\xd0y\xe1?X\xd8\xd3\x0e\x7fM\xf1?7\xf3\xab9@0\xa7?;\xf9f\x9b\x1b\xd3c?\x0f\xd6\xff9\xcc\x97\x17?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb5\xd8_vO\x1eV?2\xf5\xf3\xa6"\x15\xb6?.\x90\xa0\xf81\xe6\xca?oi5$\xee\xb1\xd0?\xfc\xd9\x8f\x14\x91a\xa5?\'\x02\x0e\xa1J\xcd>?i\x1dUM\x10u\x0f?\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xebR\\U\xf6]A?r\xa6\xd0y\x8d]\xb2?\x14\xe3\xfcM(D\xc4?!\xf8\xdfJvl\xc4?\xc8\x8a\x1aL\xc3\xf0\xdd?\x03\xc1\x1c=~o\xa3?\xd5E|\'f\xbdX?\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\x04?F\xbb\n)?\xa9\x96?>\x18x\xee=\\\xb2?\xa4\xda\xa7\xe31\x03\xa5?\xc4\x16\x82\x1c\x940\xc3?\xa2\x07wg\xed\xb6\xcf?\x90\x88)\x91D/\xa3?\xf1h\xe3\x88\xb5\xf8\xf4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\xff\x90~\xfb:\x90?\xe8\xf1{\x9b\xfe\xec\xb7?\x15\n\x11p\x08U\xb2?\x83x]\xbf`7\xc4?\x04\xd30|DL\xc9?\x88)\x91D/\xa3\xee?\x04\xa8\xa9ek}\xa1?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Yf\x83L2rV?$\x88\xba\x0f@j\x93?\x92\x9b\xe1\x06|~\x98?\xc8\x94H\xa2\x97Q\xb4?\xdec\xe9C\x17\xd4\xb7?\x1c\xfa\'\xb8XQ\xe1?\xef\xf9a\x84\xf0\xc8)@\xb1\x1b\xb6-\xcal\x80?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5C4\xba\x83\xd8\xe6?+\xd9\xb1\x11\x88\xf1^@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x18\xad\xa3\xaa\x89\xf0?)oG8-1e@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00r\xbb\xd0\\\xa7\x91v?\xab\xfb\x00\xa46\xf1.@\x98\x86\xe1#b\x82P@' +p562 +tp563 +bsg239 +Vanalog +p564 +sg241 +I00 +sg242 +I01 +sg243 +(lp565 +Vnu-scatter +p566 +asg93 +I10011 +sg246 +I01 +sbaatp567 +Rp568 +sg303 +I00 +sg304 +Nsbaa(lp569 +S'chi' +p570 +ag0 +(copenmc.mgxs.mgxs +Chi +p571 +g2 +Ntp572 +Rp573 +(dp574 +g17 +g20 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g570 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp575 +(lp576 +S'nu-fission-in' +p577 +ag0 +(g155 +g2 +Ntp578 +Rp579 +(dp580 +g159 +I01 +sg160 +(lp581 +g0 +(g162 +g2 +Ntp582 +Rp583 +(dp584 +g166 +g141 +(g142 +(I0 +tp585 +g144 +tp586 +Rp587 +(I1 +(I1 +tp588 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p589 +tp590 +bsg178 +Nsg23 +Vcell +p591 +sg180 +I1 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp592 +Rp593 +(dp594 +g166 +g141 +(g142 +(I0 +tp595 +g144 +tp596 +Rp597 +(I1 +(I2 +tp598 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p599 +tp600 +bsg178 +Nsg23 +Venergy +p601 +sg180 +I1 +sg181 +I1 +sbasg192 +Vstatepoint.100.h5 +p602 +sg194 +(lp603 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp604 +g144 +tp605 +Rp606 +(I1 +(I1 +I1 +I1 +tp607 +g38 +I00 +S'/\x83$G\x13\n_@' +p608 +tp609 +bsg203 +g141 +(g142 +(I0 +tp610 +g144 +tp611 +Rp612 +(I1 +(I1 +I1 +I1 +tp613 +g38 +I00 +S'\x9f\x9e\xb01\xd6\xf67?' +p614 +tp615 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp616 +g144 +tp617 +Rp618 +(I1 +(I1 +I1 +I1 +tp619 +g38 +I00 +S'h\xa5\x81q\xdd\xca\xf2?' +p620 +tp621 +bsg218 +g34 +(g221 +S'Z\x00\x00\x00' +p622 +tp623 +Rp624 +sg48 +(lp625 +g0 +(g52 +g2 +Ntp626 +Rp627 +(dp628 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p629 +sbasg232 +g141 +(g142 +(I0 +tp630 +g144 +tp631 +Rp632 +(I1 +(I1 +I1 +I1 +tp633 +g38 +I00 +S'\x9aP\x9egGmZ@' +p634 +tp635 +bsg239 +Vanalog +p636 +sg241 +I00 +sg242 +I01 +sg243 +(lp637 +Vnu-fission +p638 +asg93 +I10014 +sg246 +I01 +sbaa(lp639 +S'nu-fission-out' +p640 +ag0 +(g155 +g2 +Ntp641 +Rp642 +(dp643 +g159 +I01 +sg160 +(lp644 +g0 +(g162 +g2 +Ntp645 +Rp646 +(dp647 +g166 +g141 +(g142 +(I0 +tp648 +g144 +tp649 +Rp650 +(I1 +(I1 +tp651 +g173 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p652 +tp653 +bsg178 +Nsg23 +Vcell +p654 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp655 +Rp656 +(dp657 +g166 +g141 +(g142 +(I0 +tp658 +g144 +tp659 +Rp660 +(I1 +(I17 +tp661 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p662 +tp663 +bsg178 +Nsg23 +Venergyout +p664 +sg180 +I1 +sg181 +I16 +sbasg192 +Vstatepoint.100.h5 +p665 +sg194 +(lp666 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp667 +g144 +tp668 +Rp669 +(I1 +(I16 +I1 +I1 +tp670 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\x128\xb16r\xd2>\x81l\xd00\xe3j\x1c@\xde\x1c\x8f\xe4\x15\xf5Q@' +p671 +tp672 +bsg203 +g141 +(g142 +(I0 +tp673 +g144 +tp674 +Rp675 +(I1 +(I16 +I1 +I1 +tp676 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f.\xa2\x94\xbb\x88\xd9>YY\x86\xd4bH*?\xaf)\x0cjC\x065?' +p677 +tp678 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp679 +g144 +tp680 +Rp681 +(I1 +(I16 +I1 +I1 +tp682 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Kh\xf2\x00\xaf\xfa+?\xf0o?\xeb\x1d\xfb\xd1?\xbd\x82sBl\x96\xec?' +p683 +tp684 +bsg218 +g34 +(g221 +S'Z\x00\x00\x00' +p685 +tp686 +Rp687 +sg48 +(lp688 +g0 +(g52 +g2 +Ntp689 +Rp690 +(dp691 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p692 +sbasg232 +g141 +(g142 +(I0 +tp693 +g144 +tp694 +Rp695 +(I1 +(I16 +I1 +I1 +tp696 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Uq\xaa\x0cC\xac\x93?i5\xd1\x12"I9@\xed7\xb9\x1e\xc4\x19T@' +p697 +tp698 +bsg239 +Vanalog +p699 +sg241 +I00 +sg242 +I01 +sg243 +(lp700 +Vnu-fission +p701 +asg93 +I10015 +sg246 +I01 +sbaatp702 +Rp703 +sg303 +I00 +sg304 +Nsbaatp704 +Rp705 +aa(lp706 +I10001 +ag7 +((lp707 +(lp708 +g12 +ag0 +(g13 +g2 +Ntp709 +Rp710 +(dp711 +g17 +g0 +(g18 +g2 +Ntp712 +Rp713 +(dp714 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g0 +(g27 +g2 +Ntp715 +Rp716 +(dp717 +g31 +g32 +sg33 +g34 +(g38 +S'e\xb8\xc1bm\x83/?' +p718 +tp719 +Rp720 +sg44 +(lp721 +sg46 +VHelium +p722 +sg48 +g7 +((lp723 +(lp724 +VHe-4 +p725 +a(g0 +(g52 +g2 +Ntp726 +Rp727 +(dp728 +g56 +V71c +p729 +sg58 +Nsg59 +Nsg46 +g725 +sbg34 +(g38 +S'e\xb8\xc1bm\x83/?' +p730 +tp731 +Rp732 +g63 +tp733 +aatp734 +Rp735 +sg87 +g7 +((lp736 +tp737 +Rp738 +sg91 +I00 +sg92 +Nsg93 +I10001 +sbsg94 +Nsg46 +Vgap +p739 +sg96 +g0 +(copenmc.region +Intersection +p740 +g2 +Ntp741 +Rp742 +(dp743 +S'_nodes' +p744 +(lp745 +g0 +(g97 +g2 +Ntp746 +Rp747 +(dp748 +g101 +g104 +sg126 +S'+' +p749 +sbag0 +(g97 +g2 +Ntp750 +Rp751 +(dp752 +g101 +g0 +(g102 +g2 +Ntp753 +Rp754 +(dp755 +g23 +g106 +sg107 +(dp756 +g109 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p757 +tp758 +Rp759 +sg113 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p760 +tp761 +Rp762 +sg117 +g34 +(g38 +S'|\xf2\xb0Pk\x9a\xd9?' +p763 +tp764 +Rp765 +ssg46 +VClad IR +p766 +sg122 +Vtransmission +p767 +sg93 +I10001 +sg124 +(lp768 +g113 +ag109 +ag117 +asbsg126 +g127 +sbasbsg128 +Nsg93 +I10001 +sbsg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g12 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp769 +(lp770 +g154 +ag0 +(g155 +g2 +Ntp771 +Rp772 +(dp773 +g159 +I01 +sg160 +(lp774 +g0 +(g162 +g2 +Ntp775 +Rp776 +(dp777 +g166 +g141 +(g142 +(I0 +tp778 +g144 +tp779 +Rp780 +(I1 +(I1 +tp781 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p782 +tp783 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp784 +Rp785 +(dp786 +g166 +g141 +(g142 +(I0 +tp787 +g144 +tp788 +Rp789 +(I1 +(I17 +tp790 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p791 +tp792 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp793 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp794 +g144 +tp795 +Rp796 +(I1 +(I16 +I1 +I1 +tp797 +g38 +I00 +S'p\xd0\xc1\x11\xb8\x81\x92?u\x7f\x96\x02\xe4k\xa0?Mh\x06}\xcd\\\xb1?HD7\xb0\x01d\x8d?r\xe2\xd2\x0c\x19\x10Q?\x85\x9e0\x9b<^}?{\xf0\x8b\xe4\x17\xb0_?Y\xa6\x08z\x02\x167?\xb3\x1ar\x18\xe3\x80\x07?n\x84*\xea+\n\x1a?\xf9\xedm\xc5\xcd\x8f\x05?\xa9U\xdf\xc3\xef\xc72?\xa4\xf9\x90\xf5\x8d3\x98?\xf3\x97H\xe7+\x96\xf4?\x0c\xc9\xb5\xf2w\x18\x07@\xcbx\x08\x14\xe8g\xfa?' +p798 +tp799 +bsg203 +g141 +(g142 +(I0 +tp800 +g144 +tp801 +Rp802 +(I1 +(I16 +I1 +I1 +tp803 +g38 +I00 +S'a\xdb\xa1\xde\xcf<\xe6>K?\xd6N\xc0n\xee>\xceY\xdcMg\xc9\xf4>\xdf\xff\xaaY\x7f\x8a\xe6>\xd5\x9d\xa4\xc2Mj\xd8>m\x91\nz\xfe\xe6\xe2>\xfd\xa1r@\xda\x92\xda>\x0f\xed\xe6m\x18\xf3\xd1>\xbdp\x0c}\x8fh\xc1>\xebqiF\x8bj\xca>w3\x03y\r\xd0\xc1>\xedZ\xd1\x95\xa1\xf2\xcf>\x03\xa2\xb4\xce\x0e\x8f\xeb>\xf2\xb2\xe62\x82(\x01?\x13k\x9c\xb6j\xb1\t?.\xfd\xd1\xcb(\x18\x11?' +p804 +tp805 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp806 +g144 +tp807 +Rp808 +(I1 +(I16 +I1 +I1 +tp809 +g38 +I00 +S'\xa1<"\x19a\x05\x8d?\x04\xa7(\xe1\x8cT\x93?Ua\xfa\xbe\x0f\x1c\x9c?\xcb\xaef\x97?\xdc\x89?\x95\xb7|l\xef\xdck?\xaes\xa3\xa4]G\x82?\xcb\xc5\x85\xa1z\xfcr?p$\x12E!4`?u\xdb\xb96\x1a\x1eG?\xfa\r\xd0)\xab4Q?\xe9\xaaZ]\x10$F?\xc0\x1a\x1b\xba\xe6:]?\xc6\xc7\x06\xeb\xea\x97\x90?[\xb1\xfd\xd4\xe9\x9b\xbe?+\xed\xf6\xb2\xc3\xec\xc6?\xe8\xec\x85\xc2AU\xc1?' +p810 +tp811 +bsg218 +g226 +sg48 +(lp812 +g0 +(g52 +g2 +Ntp813 +Rp814 +(dp815 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp816 +g144 +tp817 +Rp818 +(I1 +(I16 +I1 +I1 +tp819 +g38 +I00 +S'\xa1\x12\xacE\xc8g\xf4?\xde*\xa1\x1c\xe6.\xfb?p\x0cH\x12\xbb\xc3\x03@\xe72t\xb6\xdc.\xf2?\x15\xb1GXX\x97\xd3?\xad\xda\x85\xaf[\xb4\xe9?&\x1e$s\x0c\xb3\xda?=\x83!\xc9N\xc9\xc6?N\xaezn*A\xb0?\xa7\x93\xcc\xb2\x102\xb8?W\x80G\x03\xb7"\xaf?\xcf\x0e\xdb:j\x8d\xc4?\xef\x88\x81Z\xa2U\xf7?\xb4`\xc2i\xa0\x85%@\xc2\x9e\xd5\x99y\x1e0@&U\x8cy\xe4_(@' +p820 +tp821 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp822 +g245 +asg93 +I10018 +sg246 +I01 +sbaa(lp823 +g12 +ag0 +(g155 +g2 +Ntp824 +Rp825 +(dp826 +g159 +I01 +sg160 +(lp827 +g0 +(g162 +g2 +Ntp828 +Rp829 +(dp830 +g166 +g141 +(g142 +(I0 +tp831 +g144 +tp832 +Rp833 +(I1 +(I1 +tp834 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p835 +tp836 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp837 +Rp838 +(dp839 +g166 +g141 +(g142 +(I0 +tp840 +g144 +tp841 +Rp842 +(I1 +(I17 +tp843 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p844 +tp845 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp846 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp847 +g144 +tp848 +Rp849 +(I1 +(I16 +I1 +I1 +tp850 +g38 +I00 +S'l\x08\x1a\xce\x8b\x87\x0f>@\xa8Z\xaa\xc1\xaf\x15>\xec\x98G}\xeaS%>R\x0b$C\xbfV\x01>\x98\x8bs\x00;\xdf\xc3=\xe9\xec\xf9U\xfb\xfc\xf0=\x19\x03GH\xe1<\xd2=\x8f\xf6N\xe1\xd3\x86\xaa=\x85\x06\xa0\xb6P\xfdz=\xe6X\xf1uV\xe4\x8d=]\xb9<\xd6F\xbex=\xd83h1\x9f\x8a\xa5=\xef\xe4,\xeb(\xb2\x0b>=\x84\x15\x1f\xa6}g>\xd7\xa7\xa7\xf5O\x08\x92>|e[\x05\xb2\xab\xbf>' +p851 +tp852 +bsg203 +g141 +(g142 +(I0 +tp853 +g144 +tp854 +Rp855 +(I1 +(I16 +I1 +I1 +tp856 +g38 +I00 +S'\xd6\xff|\xe8\x0c\x96$>l\x07\x1c,_\xbe(> v\x0b\xbe\xdeM0>P\x07X\x18\xddR!>^\x8e\x7f\x8ct\xa1\x12>k{\xa1\x16\x8c\xbf\x1c>1T\xf0\xa2\xd0(\x14>wu+\xf9\xe35\x0b>]SaA\xc6a\xfa=\x9a\xbe\xd4\x9c\\\x03\x04>\xe9\xc5\xbe\xf55\xfc\xfa=\xbeQ\x01\xbe\xc21\x08>3\xdfz\xd6\xc6\xd8$>\x8d\xa0\x14\xae\x8b\xeb9>\xcd[8LkJT>px\xd2\xb1\xfd\xa2s>' +p857 +tp858 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp859 +g144 +tp860 +Rp861 +(I1 +(I16 +I1 +I1 +tp862 +g38 +I00 +S'^\x98\xee\x02\xf4\xc8\xca>,W\xc4?Wj\xcf>\xbc\xc5]\xe7\x93\x07\xd6>\xa9@\xf3\xd0\xde\xdc\xc3>Z(\xa8j\x1eC\xa5>\x12i79\xea\xcd\xbb>\x8d\xbf\x952\xc7\xce\xac>M\x08c\xd5Q\x90\x98>\x14\xe83iX\x84\x81>\xfa\xe2\xde]\x03\x12\x8a>k\x92XHs\xc5\x80>p\xee65\xbe"\x96>\xf3j\xb3\x07\x91\x1a\xc9>n\xf2_\x84\xc4\x1e\xf7>\xb3\xfb\x0b\xd8\xb6\xa5\x0c?rt\xba\x94\x82\xfb"?' +p863 +tp864 +bsg218 +g226 +sg48 +(lp865 +g0 +(g52 +g2 +Ntp866 +Rp867 +(dp868 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp869 +g144 +tp870 +Rp871 +(I1 +(I16 +I1 +I1 +tp872 +g38 +I00 +S'"\xc3\x0f\x92K\xd52?K\r\xd6X\xc5\x166?\x10\xde[\xfd\xa7\xfa>?\xee\x12\xd6U\x99\xee+?\xbfx\xfc\xc5b\xe6\r?\xe1\xf5:\xb0\xc8\x8c#?\xafJ\x91\x0fdA\x14?\xd6\xa1\t\x8ayE\x01?\\\xfe\xf0S\x1c\xa2\xe8>\x98\xb7\x00^\xaaT\xf2>\xe7\x8d\xbc\x1d\xaa\x95\xe7>N?\xd5z\xdb \xff>3\'j\xf9\xad\xa61?uv\x13-\xa2A`?\xfal\xe8\x8f\x84$t?\xc13&\xa1\xaf\xb1\x8a?' +p873 +tp874 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp875 +g300 +asg93 +I10019 +sg246 +I01 +sbaatp876 +Rp877 +sg303 +I00 +sg304 +Nsbaa(lp878 +g306 +ag0 +(g307 +g2 +Ntp879 +Rp880 +(dp881 +g17 +g713 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g311 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp882 +(lp883 +g154 +ag0 +(g155 +g2 +Ntp884 +Rp885 +(dp886 +g159 +I01 +sg160 +(lp887 +g0 +(g162 +g2 +Ntp888 +Rp889 +(dp890 +g166 +g141 +(g142 +(I0 +tp891 +g144 +tp892 +Rp893 +(I1 +(I1 +tp894 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p895 +tp896 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp897 +Rp898 +(dp899 +g166 +g141 +(g142 +(I0 +tp900 +g144 +tp901 +Rp902 +(I1 +(I17 +tp903 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p904 +tp905 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp906 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp907 +g144 +tp908 +Rp909 +(I1 +(I16 +I1 +I1 +tp910 +g38 +I00 +S'p\xd0\xc1\x11\xb8\x81\x92?u\x7f\x96\x02\xe4k\xa0?Mh\x06}\xcd\\\xb1?HD7\xb0\x01d\x8d?r\xe2\xd2\x0c\x19\x10Q?\x85\x9e0\x9b<^}?{\xf0\x8b\xe4\x17\xb0_?Y\xa6\x08z\x02\x167?\xb3\x1ar\x18\xe3\x80\x07?n\x84*\xea+\n\x1a?\xf9\xedm\xc5\xcd\x8f\x05?\xa9U\xdf\xc3\xef\xc72?\xa4\xf9\x90\xf5\x8d3\x98?\xf3\x97H\xe7+\x96\xf4?\x0c\xc9\xb5\xf2w\x18\x07@\xcbx\x08\x14\xe8g\xfa?' +p911 +tp912 +bsg203 +g141 +(g142 +(I0 +tp913 +g144 +tp914 +Rp915 +(I1 +(I16 +I1 +I1 +tp916 +g38 +I00 +S'a\xdb\xa1\xde\xcf<\xe6>K?\xd6N\xc0n\xee>\xceY\xdcMg\xc9\xf4>\xdf\xff\xaaY\x7f\x8a\xe6>\xd5\x9d\xa4\xc2Mj\xd8>m\x91\nz\xfe\xe6\xe2>\xfd\xa1r@\xda\x92\xda>\x0f\xed\xe6m\x18\xf3\xd1>\xbdp\x0c}\x8fh\xc1>\xebqiF\x8bj\xca>w3\x03y\r\xd0\xc1>\xedZ\xd1\x95\xa1\xf2\xcf>\x03\xa2\xb4\xce\x0e\x8f\xeb>\xf2\xb2\xe62\x82(\x01?\x13k\x9c\xb6j\xb1\t?.\xfd\xd1\xcb(\x18\x11?' +p917 +tp918 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp919 +g144 +tp920 +Rp921 +(I1 +(I16 +I1 +I1 +tp922 +g38 +I00 +S'\xa1<"\x19a\x05\x8d?\x04\xa7(\xe1\x8cT\x93?Ua\xfa\xbe\x0f\x1c\x9c?\xcb\xaef\x97?\xdc\x89?\x95\xb7|l\xef\xdck?\xaes\xa3\xa4]G\x82?\xcb\xc5\x85\xa1z\xfcr?p$\x12E!4`?u\xdb\xb96\x1a\x1eG?\xfa\r\xd0)\xab4Q?\xe9\xaaZ]\x10$F?\xc0\x1a\x1b\xba\xe6:]?\xc6\xc7\x06\xeb\xea\x97\x90?[\xb1\xfd\xd4\xe9\x9b\xbe?+\xed\xf6\xb2\xc3\xec\xc6?\xe8\xec\x85\xc2AU\xc1?' +p923 +tp924 +bsg218 +g226 +sg48 +(lp925 +g0 +(g52 +g2 +Ntp926 +Rp927 +(dp928 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp929 +g144 +tp930 +Rp931 +(I1 +(I16 +I1 +I1 +tp932 +g38 +I00 +S'\xa1\x12\xacE\xc8g\xf4?\xde*\xa1\x1c\xe6.\xfb?p\x0cH\x12\xbb\xc3\x03@\xe72t\xb6\xdc.\xf2?\x15\xb1GXX\x97\xd3?\xad\xda\x85\xaf[\xb4\xe9?&\x1e$s\x0c\xb3\xda?=\x83!\xc9N\xc9\xc6?N\xaezn*A\xb0?\xa7\x93\xcc\xb2\x102\xb8?W\x80G\x03\xb7"\xaf?\xcf\x0e\xdb:j\x8d\xc4?\xef\x88\x81Z\xa2U\xf7?\xb4`\xc2i\xa0\x85%@\xc2\x9e\xd5\x99y\x1e0@&U\x8cy\xe4_(@' +p933 +tp934 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp935 +g245 +asg93 +I10022 +sg246 +I01 +sbaa(lp936 +g367 +ag0 +(g155 +g2 +Ntp937 +Rp938 +(dp939 +g159 +I01 +sg160 +(lp940 +g0 +(g162 +g2 +Ntp941 +Rp942 +(dp943 +g166 +g141 +(g142 +(I0 +tp944 +g144 +tp945 +Rp946 +(I1 +(I1 +tp947 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p948 +tp949 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp950 +Rp951 +(dp952 +g166 +g141 +(g142 +(I0 +tp953 +g144 +tp954 +Rp955 +(I1 +(I17 +tp956 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p957 +tp958 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp959 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp960 +g144 +tp961 +Rp962 +(I1 +(I16 +I1 +I1 +tp963 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p964 +tp965 +bsg203 +g141 +(g142 +(I0 +tp966 +g144 +tp967 +Rp968 +(I1 +(I16 +I1 +I1 +tp969 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p970 +tp971 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp972 +g144 +tp973 +Rp974 +(I1 +(I16 +I1 +I1 +tp975 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p976 +tp977 +bsg218 +g226 +sg48 +(lp978 +g0 +(g52 +g2 +Ntp979 +Rp980 +(dp981 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp982 +g144 +tp983 +Rp984 +(I1 +(I16 +I1 +I1 +tp985 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p986 +tp987 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp988 +g420 +asg93 +I10023 +sg246 +I01 +sbaatp989 +Rp990 +sg303 +I00 +sg304 +Nsbaa(lp991 +g424 +ag0 +(g425 +g2 +Ntp992 +Rp993 +(dp994 +g17 +g713 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g429 +sg46 +g134 +sg48 +Nsg430 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp995 +(lp996 +g154 +ag0 +(g155 +g2 +Ntp997 +Rp998 +(dp999 +g159 +I01 +sg160 +(lp1000 +g0 +(g162 +g2 +Ntp1001 +Rp1002 +(dp1003 +g166 +g141 +(g142 +(I0 +tp1004 +g144 +tp1005 +Rp1006 +(I1 +(I1 +tp1007 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1008 +tp1009 +bsg178 +Nsg23 +g446 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1010 +Rp1011 +(dp1012 +g166 +g141 +(g142 +(I0 +tp1013 +g144 +tp1014 +Rp1015 +(I1 +(I17 +tp1016 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1017 +tp1018 +bsg178 +Nsg23 +g456 +sg180 +I1 +sg181 +I16 +sbasg192 +g457 +sg194 +(lp1019 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1020 +g144 +tp1021 +Rp1022 +(I1 +(I16 +I1 +I1 +tp1023 +g38 +I00 +S'\x98\x7fX\x1aKn\xb4?]\xb6\xc7\x94d\x87\xc3?I\xe4\xba4\xd6U\xc6?\xde\xab\xcd\xb099\xb2?\xdb\x81\x0c\xb8\x8c\x8e\x9a?!]\xcd\xca\xc4\xb6\xad?\xbf\xf6\x1b\x84\xbc\xe2\x94?\xe47\xd9\x16\xd7\xec\x97?x\xec\x06\x8b\x84\xf0w?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y dD\xa4C\xb4?0M\n\x16\\\x9e\xfb?N>L?\xb7\xea\x0c@\x90\t\xb0G\xa8\xbb\xfc?' +p1024 +tp1025 +bsg203 +g141 +(g142 +(I0 +tp1026 +g144 +tp1027 +Rp1028 +(I1 +(I16 +I1 +I1 +tp1029 +g38 +I00 +S'\xae]m\x03v\xa6e?\xb12\x99;\xc1\xffm?\x97\xa7\xae\xb9\x7f\x9fm?:\x8b\x90M\xc4\xe5e?\x02\xaf\x18\x88\\\x93\\?2\xcf\x14\x90\xc0\xf7c?\xe1&\x98oh\x1bY?\xda \x03f\x0cF[?\xc8\xb6\x03!\x84\xadK?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf5\xf3\xad\x9c\x00\xc7f?4\x18\x90\xa89{\x81?YQ\xfe\x8d6g\x81?>\x93\x82\xb1FZp?' +p1030 +tp1031 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1032 +g144 +tp1033 +Rp1034 +(I1 +(I16 +I1 +I1 +tp1035 +g38 +I00 +S'\xeb\t\x88C\\\xac\x90?\xa8\xfc\x87,\xb9\xef\x96?\xd5\xe0\xdeW\x06\x82\x9c?\xe6Z\x1c\xf8\x13\x80\x89?4\xa6\x18\x06Q\x19q?=\x8d\xfd\xfc7\x10\x86?\xc3\x9e\xa2\xe0O2q?P\xdbW\x0e\xa4\x83m?\xbfJ\x01m\x9a\xaeS?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x89n:m\xe2V\x8c?)\xd3\n\xf7\x15\xd8\xbc?!]QG\x95\x82\xc7?\xcb`\xce\x16#m\xc1?' +p1036 +tp1037 +bsg218 +g479 +sg48 +(lp1038 +g0 +(g52 +g2 +Ntp1039 +Rp1040 +(dp1041 +g56 +Nsg58 +Nsg59 +Nsg46 +g484 +sbasg232 +g141 +(g142 +(I0 +tp1042 +g144 +tp1043 +Rp1044 +(I1 +(I16 +I1 +I1 +tp1045 +g38 +I00 +S'\xf2M\xf7\xbear\xf7?\xa6\x9dO3\x8e \x00@\x16\xb6\xc8ul\x0b\x04@\xea\xefs\n\x0e\xee\xf1?\xb9\xa9\x92\xf0\x99\x0b\xd8?\x9e\x8e\xc4\xbb\xce\x06\xef?B\xaf\xe4S\xc0.\xd8?4\xc6\x15Z\x8f\xc0\xd4?\x1c\xd1I)\x89\xad\xbb?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\x15\xcd4\x17\xed\xf3?y\x9c\xb3q\xefG$@{5%\xf6\xd0\x870@\x1d8\x12Xy\x81(@' +p1046 +tp1047 +bsg239 +g491 +sg241 +I01 +sg242 +I01 +sg243 +(lp1048 +g493 +asg93 +I10026 +sg246 +I01 +sbaa(lp1049 +g495 +ag0 +(g155 +g2 +Ntp1050 +Rp1051 +(dp1052 +g159 +I01 +sg160 +(lp1053 +g0 +(g162 +g2 +Ntp1054 +Rp1055 +(dp1056 +g166 +g141 +(g142 +(I0 +tp1057 +g144 +tp1058 +Rp1059 +(I1 +(I1 +tp1060 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1061 +tp1062 +bsg178 +Nsg23 +g509 +sg180 +I256 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1063 +Rp1064 +(dp1065 +g166 +g141 +(g142 +(I0 +tp1066 +g144 +tp1067 +Rp1068 +(I1 +(I17 +tp1069 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1070 +tp1071 +bsg178 +Nsg23 +g519 +sg180 +I16 +sg181 +I16 +sbag0 +(g162 +g2 +Ntp1072 +Rp1073 +(dp1074 +g166 +g141 +(g142 +(I0 +tp1075 +g144 +tp1076 +Rp1077 +(I1 +(I17 +tp1078 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1079 +tp1080 +bsg178 +Nsg23 +g529 +sg180 +I1 +sg181 +I16 +sbasg192 +g530 +sg194 +(lp1081 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1082 +g144 +tp1083 +Rp1084 +(I1 +(I256 +I1 +I1 +tp1085 +g38 +I00 +S'\xf4\x83k\xdd*\xe9(>\xbc\xbd\xd7\xd9\xdf|\xfb=\xbc\xbd\xd7\xd9\xdf|\xfb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x10\x93\xe4\xc0\xc1#>\x9a9u\xd7\xad4\x1d>\xbe\xbd\xd7\xd9\xdf|\x0b>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xeb=\x97\xd6&\xe8\x0b.\x11>ds\xe1\xd3b\xc8/>\x96\xd6&\xe8\x0b.\x01>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\xcea\xe3\xa7\x9d\xf4=t\xb5\x12\xd5{\xec\x0e>sR\xc4\xe5\xd9\xe5\x12>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\xbc\xbd\xd7\xd9\xdf|\xfb=\xbc\xbd\xd7\xd9\xdf|\xdb=\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\x04\xc6\x9c\xdeC\r\x08>M\xcea\xe3\xa7\x9d\xf4=v\xb5\x12\xd5{\xec\x0e>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00N\xcea\xe3\xa7\x9d\x04>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xeb=\xbc\xbd\xd7\xd9\xdf|\xeb=\xbc\xbd\xd7\xd9\xdf|\xeb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\xcea\xe3\xa7\x9d\xf4=M\xcea\xe3\xa7\x9d\xf4=\xbc\xbd\xd7\xd9\xdf|\xdb=\xbc\xbd\xd7\xd9\xdf|\xdb=\xbc\xbd\xd7\xd9\xdf|\xeb=\xbc\xbd\xd7\xd9\xdf|\xeb=\xbc\xbd\xd7\xd9\xdf|\xdb=\x97\xd6&\xe8\x0b.\x11>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xd6&\xe8\x0b.\x01>\xbb~\xd1u\x0bcn>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sR\xc4\xe5\xd9\xe5\x12>2\xeb\x97a\x82\xe7\x95>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a]\x83\xd1\xfc\xd7\x88>S\xe6#6\xcaD\xb2>' +p1086 +tp1087 +bsg203 +g141 +(g142 +(I0 +tp1088 +g144 +tp1089 +Rp1090 +(I1 +(I256 +I1 +I1 +tp1091 +g38 +I00 +S'68"\xabw\x9b\xa1>i\xf02\xc5\xb4Q\x8d>i\xf02\xc5\xb4Q\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xeb\xff;V\x92\xad\xa0>|a\x82\xad\x7f\x8d\x9c>\xc1\x87\xad\x91p>\x94>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8bq\xc3\xb8\xb1\xf8\x84>2\xf5#\x1a\x0c[\x96>\xe6\xb9\xd5\xd90<\xa3>\xf8\xeb\xed\x06ZK\x90>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f0F~\xd0\x89\x89>9\x83\x13\x1b\xce\xcd\x95>\xae\xf1\xf8\xef\xbfL\x97>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>i\xf02\xc5\xb4Q\x8d>\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x1e!\xed\xa9\xe9p\x93>\x8f0F~\xd0\x89\x89>kFN\xfe/W\x95>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x95\x00\xa1\'\x87\xbe\x91>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8bq\xc3\xb8\xb1\xf8\x84>\x8bq\xc3\xb8\xb1\xf8\x84>\x8bq\xc3\xb8\xb1\xf8\x84>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f0F~\xd0\x89\x89>\x8f0F~\xd0\x89\x89>\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\x8bq\xc3\xb8\xb1\xf8\x84>\x8bq\xc3\xb8\xb1\xf8\x84>\xc3\xc2\x98V\x7f\xd3}>2\xf5#\x1a\x0c[\x96>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xeb\xed\x06ZK\x90>\xbf,\xc5*\xec_\xba>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xae\xf1\xf8\xef\xbfL\x97>\xbb\xf9\xf10K\xb2\xc3>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9d\xc8N2Q_\xc0>\xe3<\xed/\x95#\xcd>' +p1092 +tp1093 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1094 +g144 +tp1095 +Rp1096 +(I1 +(I256 +I1 +I1 +tp1097 +g38 +I00 +S'(X\xa7{;M\xc7>\xc3\xc2\x98V\x7f\xd3\x9d>\xc3\xc2\x98V\x7f\xd3\x9d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xefN\x02L\xb7\xb0\xbf>\x976/aG\xf6\xbb>\xc3\xc2\x98V\x7f\xd3\xad>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x8d>\xbay\x1f\x96/\xa4\xb2>\xb0\xfc\xe3[\xe3\xe4\xcc>\xbay\x1f\x96/\xa4\xa2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\x96>k\xaa\xc5k\x0f\x19\xaa>\xe6\x05\x89\x8bg\x81\xb4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3\x9d>\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xbay\x1f\x96/\xa4\xa2>\x12\x92\xf2\x80\x9f^\x96>\x8e\xed\xb5\xa0\xf7\xc6\xb0>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\xa6>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x8d>\xc3\xc2\x98V\x7f\xd3\x8d>\xc3\xc2\x98V\x7f\xd3\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\x96>\x12\x92\xf2\x80\x9f^\x96>\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3\x8d>\xc3\xc2\x98V\x7f\xd3\x8d>\xc3\xc2\x98V\x7f\xd3}>\xbay\x1f\x96/\xa4\xb2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbay\x1f\x96/\xa4\xa2>~\x9a\x90\x87\\4\xf5>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe6\x05\x89\x8bg\x81\xb4>\xba_>Y1\\\r?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xebI\x96D\x94\xba\x05?\xbdy\xaaCn\x86\x1b?' +p1098 +tp1099 +bsg218 +g552 +sg48 +(lp1100 +g0 +(g52 +g2 +Ntp1101 +Rp1102 +(dp1103 +g56 +Nsg58 +Nsg59 +Nsg46 +g557 +sbasg232 +g141 +(g142 +(I0 +tp1104 +g144 +tp1105 +Rp1106 +(I1 +(I256 +I1 +I1 +tp1107 +g38 +I00 +S'\xfc\xa9\xf1\xd2Mb0?\xf1h\xe3\x88\xb5\xf8\x04?\xf1h\xe3\x88\xb5\xf8\x04?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x9fq\xe1@H&?b2U0*\xa9#?\xf1h\xe3\x88\xb5\xf8\x14?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xf4>-C\x1c\xeb\xe26\x1a?\xacM\x9c\xdc\xefP4?-C\x1c\xeb\xe26\n?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x1dUM\x10u\xff>\xd3\xfb\xc6\xd7\x9eY\x12?K\xb08\x9c\xf9\xd5\x1c?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\x04?\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>.C\x1c\xeb\xe26\n?j\x1dUM\x10u\xff>\x0f\xd6\xff9\xcc\x97\x17?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00i\x1dUM\x10u\x0f?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xf4>\xf1h\xe3\x88\xb5\xf8\xf4>\xf1h\xe3\x88\xb5\xf8\xf4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x1dUM\x10u\xff>j\x1dUM\x10u\xff>\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\xf4>\xf1h\xe3\x88\xb5\xf8\xf4>\xf1h\xe3\x88\xb5\xf8\xe4>-C\x1c\xeb\xe26\x1a?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-C\x1c\xeb\xe26\n?AY\xa3\x1e\xa2\xd1]?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K\xb08\x9c\xf9\xd5\x1c?O\xdb\xbf\xb2\xd2\xa4t?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3Ws\x80`\x8en?\x99\xdd\x93\x87\x85Z\x83?' +p1108 +tp1109 +bsg239 +g564 +sg241 +I01 +sg242 +I01 +sg243 +(lp1110 +g566 +asg93 +I10027 +sg246 +I01 +sbaatp1111 +Rp1112 +sg303 +I00 +sg304 +Nsbaa(lp1113 +g570 +ag0 +(g571 +g2 +Ntp1114 +Rp1115 +(dp1116 +g17 +g713 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g570 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1117 +(lp1118 +g577 +ag0 +(g155 +g2 +Ntp1119 +Rp1120 +(dp1121 +g159 +I01 +sg160 +(lp1122 +g0 +(g162 +g2 +Ntp1123 +Rp1124 +(dp1125 +g166 +g141 +(g142 +(I0 +tp1126 +g144 +tp1127 +Rp1128 +(I1 +(I1 +tp1129 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1130 +tp1131 +bsg178 +Nsg23 +g591 +sg180 +I1 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1132 +Rp1133 +(dp1134 +g166 +g141 +(g142 +(I0 +tp1135 +g144 +tp1136 +Rp1137 +(I1 +(I2 +tp1138 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1139 +tp1140 +bsg178 +Nsg23 +g601 +sg180 +I1 +sg181 +I1 +sbasg192 +g602 +sg194 +(lp1141 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1142 +g144 +tp1143 +Rp1144 +(I1 +(I1 +I1 +I1 +tp1145 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1146 +tp1147 +bsg203 +g141 +(g142 +(I0 +tp1148 +g144 +tp1149 +Rp1150 +(I1 +(I1 +I1 +I1 +tp1151 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1152 +tp1153 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1154 +g144 +tp1155 +Rp1156 +(I1 +(I1 +I1 +I1 +tp1157 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1158 +tp1159 +bsg218 +g624 +sg48 +(lp1160 +g0 +(g52 +g2 +Ntp1161 +Rp1162 +(dp1163 +g56 +Nsg58 +Nsg59 +Nsg46 +g629 +sbasg232 +g141 +(g142 +(I0 +tp1164 +g144 +tp1165 +Rp1166 +(I1 +(I1 +I1 +I1 +tp1167 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1168 +tp1169 +bsg239 +g636 +sg241 +I01 +sg242 +I01 +sg243 +(lp1170 +g638 +asg93 +I10030 +sg246 +I01 +sbaa(lp1171 +g640 +ag0 +(g155 +g2 +Ntp1172 +Rp1173 +(dp1174 +g159 +I01 +sg160 +(lp1175 +g0 +(g162 +g2 +Ntp1176 +Rp1177 +(dp1178 +g166 +g141 +(g142 +(I0 +tp1179 +g144 +tp1180 +Rp1181 +(I1 +(I1 +tp1182 +g173 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1183 +tp1184 +bsg178 +Nsg23 +g654 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1185 +Rp1186 +(dp1187 +g166 +g141 +(g142 +(I0 +tp1188 +g144 +tp1189 +Rp1190 +(I1 +(I17 +tp1191 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1192 +tp1193 +bsg178 +Nsg23 +g664 +sg180 +I1 +sg181 +I16 +sbasg192 +g665 +sg194 +(lp1194 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1195 +g144 +tp1196 +Rp1197 +(I1 +(I16 +I1 +I1 +tp1198 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1199 +tp1200 +bsg203 +g141 +(g142 +(I0 +tp1201 +g144 +tp1202 +Rp1203 +(I1 +(I16 +I1 +I1 +tp1204 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1205 +tp1206 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1207 +g144 +tp1208 +Rp1209 +(I1 +(I16 +I1 +I1 +tp1210 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1211 +tp1212 +bsg218 +g687 +sg48 +(lp1213 +g0 +(g52 +g2 +Ntp1214 +Rp1215 +(dp1216 +g56 +Nsg58 +Nsg59 +Nsg46 +g692 +sbasg232 +g141 +(g142 +(I0 +tp1217 +g144 +tp1218 +Rp1219 +(I1 +(I16 +I1 +I1 +tp1220 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1221 +tp1222 +bsg239 +g699 +sg241 +I01 +sg242 +I01 +sg243 +(lp1223 +g701 +asg93 +I10031 +sg246 +I01 +sbaatp1224 +Rp1225 +sg303 +I00 +sg304 +Nsbaatp1226 +Rp1227 +aa(lp1228 +I10002 +ag7 +((lp1229 +(lp1230 +g12 +ag0 +(g13 +g2 +Ntp1231 +Rp1232 +(dp1233 +g17 +g0 +(g18 +g2 +Ntp1234 +Rp1235 +(dp1236 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g0 +(g27 +g2 +Ntp1237 +Rp1238 +(dp1239 +g31 +g32 +sg33 +g34 +(g38 +S'\xd3!\x80FP\xc6\xa6?' +p1240 +tp1241 +Rp1242 +sg44 +(lp1243 +sg46 +VZircaloy 4 +p1244 +sg48 +g7 +((lp1245 +(lp1246 +VO-16 +p1247 +a(g0 +(g52 +g2 +Ntp1248 +Rp1249 +(dp1250 +g56 +V71c +p1251 +sg58 +Nsg59 +Nsg46 +g1247 +sbg34 +(g38 +S'\xc5\x84\x12\xf2\xf3\x1eD?' +p1252 +tp1253 +Rp1254 +g63 +tp1255 +aa(lp1256 +VFe-56 +p1257 +a(g0 +(g52 +g2 +Ntp1258 +Rp1259 +(dp1260 +g56 +V71c +p1261 +sg58 +Nsg59 +Nsg46 +g1257 +sbg34 +(g38 +S'\x9eg^\xb0\xad\xd01?' +p1262 +tp1263 +Rp1264 +g63 +tp1265 +aa(lp1266 +VZr-90 +p1267 +a(g0 +(g52 +g2 +Ntp1268 +Rp1269 +(dp1270 +g56 +V71c +p1271 +sg58 +Nsg59 +Nsg46 +g1267 +sbg34 +(g38 +S'\xf0\x1aW\x1b3R\xa6?' +p1272 +tp1273 +Rp1274 +g63 +tp1275 +aatp1276 +Rp1277 +sg87 +g7 +((lp1278 +tp1279 +Rp1280 +sg91 +I00 +sg92 +Nsg93 +I10002 +sbsg94 +Nsg46 +Vclad +p1281 +sg96 +g0 +(g740 +g2 +Ntp1282 +Rp1283 +(dp1284 +g744 +(lp1285 +g0 +(g97 +g2 +Ntp1286 +Rp1287 +(dp1288 +g101 +g754 +sg126 +g749 +sbag0 +(g97 +g2 +Ntp1289 +Rp1290 +(dp1291 +g101 +g0 +(g102 +g2 +Ntp1292 +Rp1293 +(dp1294 +g23 +g106 +sg107 +(dp1295 +g109 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1296 +tp1297 +Rp1298 +sg113 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1299 +tp1300 +Rp1301 +sg117 +g34 +(g38 +S'\xfb\xcb\xee\xc9\xc3B\xdd?' +p1302 +tp1303 +Rp1304 +ssg46 +VClad OR +p1305 +sg122 +Vtransmission +p1306 +sg93 +I10002 +sg124 +(lp1307 +g113 +ag109 +ag117 +asbsg126 +g127 +sbasbsg128 +Nsg93 +I10002 +sbsg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g12 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1308 +(lp1309 +g154 +ag0 +(g155 +g2 +Ntp1310 +Rp1311 +(dp1312 +g159 +I01 +sg160 +(lp1313 +g0 +(g162 +g2 +Ntp1314 +Rp1315 +(dp1316 +g166 +g141 +(g142 +(I0 +tp1317 +g144 +tp1318 +Rp1319 +(I1 +(I1 +tp1320 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1321 +tp1322 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1323 +Rp1324 +(dp1325 +g166 +g141 +(g142 +(I0 +tp1326 +g144 +tp1327 +Rp1328 +(I1 +(I17 +tp1329 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1330 +tp1331 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1332 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1333 +g144 +tp1334 +Rp1335 +(I1 +(I16 +I1 +I1 +tp1336 +g38 +I00 +S'\x97\x7f\xc9\x1e@\xc3\xf2?~\xc0\xd2\xd1i^\x00@\x82\xefV\xb3\x11$\x11@\xe8\xda\\.*\xdb\xec?\x99\xfc\xbb\t\x1c\xb2\xb0?kb\xef\xdc\x8f\xb1\xdc?Ml}\xab\xa3\xc4\xbe?\xae%\xb3\xcf\xadT\x96?\x8a\xa2M\xb4\x11\xc8f?\xa8F\xed\xa7Mmy?\xc6f\x01.W\xced?N\xe9\xf4\xb7\xd2.\x92?\x0b\xf5w\x88_o\xf7?\x86\xe8\xd5\xae\xbe\tT@!\x96[\xb6\xc4\x0cf@\x8e\x1d\xcby0\xe7X@' +p1337 +tp1338 +bsg203 +g141 +(g142 +(I0 +tp1339 +g144 +tp1340 +Rp1341 +(I1 +(I16 +I1 +I1 +tp1342 +g38 +I00 +S"fW/\x92\x17\xb2\x16?C\xcfe\xfc\x925\x1e?=+\x96M\x14\xad#?\x18\x03yF\x1a\x1d\x15?\xd6CI\xe5Y{\x07?\x1b\xcb^\xb7\x9fx\x10?\x05'\x83wS\x94\x07?\xf1\xbb\xf9\xb6\xdc2\x00?2%#2\xf9q\xf0>\xd7%\xb6\x1e{%\xf7>\xdb\x8c\xa5g\xd4^\xf1>\xf4\xb4\x18M\xdb\xa8\xfb>\xb0\x12Hq\xdc\xe7\x18?N\xb2\xeb\x14\x1a\xf0/?\x99\xde\xe9y\x19\x1d7?\x10\xe8\xd1\xe4\x16y>?" +p1343 +tp1344 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1345 +g144 +tp1346 +Rp1347 +(I1 +(I16 +I1 +I1 +tp1348 +g38 +I00 +S'/\x9f\xbf*\x948\xbd?e@~\xf5\x9cL\xc3?A+m\x07\x01\xee\xcb?N\x1e\xaa\xcf\xca\x9f\xb9?\xb3/F\x1c\xd4\x8f\x9b?\xb1%\xfe%]\x11\xb2?N:G@\x7f\xb5\xa2?\xd7\xa0rs\xb4\xdf\x8f?N\xd4)\xfd\xad\xc2v?\x84\xba\x013\xe8\x00\x81?\xeex\x877\xe2\xbfu?\xa1w\x10\xca\x1f\xc3\x8c?\x90\x8a\xea\x14$T\xc0?\x90(~\xb5\xd02\xee? \x93i%^f\xf6?\x9cB\x99\r&\xd5\xf0?' +p1349 +tp1350 +bsg218 +g226 +sg48 +(lp1351 +g0 +(g52 +g2 +Ntp1352 +Rp1353 +(dp1354 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1355 +g144 +tp1356 +Rp1357 +(I1 +(I16 +I1 +I1 +tp1358 +g38 +I00 +S'\xed\xbb\x0e.\xc8\x8b$@\x8e\x8a9\xb9\xbc#+@j\xc28\xb9X\xa33@O\x9d\x03\x9aZ\x04"@\x8aY\xe1#!a\x03@\x01em\xfdjh\x19@\xfd)d\xf2:O\n@\x17\x99,\xe1Ji\xf6?Gi\x01V\xe2\x00\xe0?In\xba\x87F\xe9\xe7?\x0e\x82\x16\x1e\xd6\x95\xde?\x1d\x94\x13Z29\xf4?\xda\xd2i\xbdR\xf6&@\x85\xb4\x9c\xbf\xba;U@\xe5v\x9cd\xf4\x7f_@\xab\x85\x1f\x83\xbd\xabW@' +p1359 +tp1360 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1361 +g245 +asg93 +I10034 +sg246 +I01 +sbaa(lp1362 +g12 +ag0 +(g155 +g2 +Ntp1363 +Rp1364 +(dp1365 +g159 +I01 +sg160 +(lp1366 +g0 +(g162 +g2 +Ntp1367 +Rp1368 +(dp1369 +g166 +g141 +(g142 +(I0 +tp1370 +g144 +tp1371 +Rp1372 +(I1 +(I1 +tp1373 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1374 +tp1375 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1376 +Rp1377 +(dp1378 +g166 +g141 +(g142 +(I0 +tp1379 +g144 +tp1380 +Rp1381 +(I1 +(I17 +tp1382 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1383 +tp1384 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1385 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1386 +g144 +tp1387 +Rp1388 +(I1 +(I16 +I1 +I1 +tp1389 +g38 +I00 +S'\x90\xcc Y!\xb0\xb2?\'\xc4voJ\xf9\xbf?\xf3\xdc*\xc6X\xa5\xd0?\xa2\xf3CU+\xec\xab?*YV(6"p?\xc8b\x1e0\xac\xb4\x9b?\xae\xc5e4N\xb0}?\x8f\xdaSj\x9e\x8aU?6]\x1b}[\xf9%?@\x0e\x90\x9c/\x868?\x07\x94@\xce\xe8\x10$?y\x06\xc3t\xe6\x88Q?\xda\xe2\xb5 \xad\x96\xb6?z3\xf1\x9et\x08\x14@\xd1\xe2\xfc\xc0\\{7@\x87!O \x0b\x97\x12@' +p1390 +tp1391 +bsg203 +g141 +(g142 +(I0 +tp1392 +g144 +tp1393 +Rp1394 +(I1 +(I16 +I1 +I1 +tp1395 +g38 +I00 +S'\xb8\xd6\xfd\xfb{\x9f\xf6>\xf9\xee6\xa83\xdb\xfd>\xac;a(Kd\x03?\x82\xe9\x92\xf8f\xc5\xf4>\xbahNH_\x15\xe7>\xfezvEN/\xf0>\xc3\xbf]\xaf{)\xe7>\x98?\xf2\xa4\xd2\xd1\xdf>\x05c+\xdd\xb0&\xd0>\xf2\x03\x11\xa4V\xbb\xd6>\x7f\x03k\x95\x07\x0f\xd1>f?\xb3\xeb\x88)\xdb>\xb7\xf8\xd21\x9bs\xf8>\xae[\x90\x0f%\x88\x12?\xb2\xa2@\x16\x9b\xbf"?\x88\x7f\xa4%h}\x19?' +p1396 +tp1397 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1398 +g144 +tp1399 +Rp1400 +(I1 +(I16 +I1 +I1 +tp1401 +g38 +I00 +S"\x97\xaex\xed\xac)\x9d?GR%+\xa3\x12\xa3?\xa1\x9b\x1bw\x01\x86\xab?\xbc\x85\xbdP\xce4\x99?[kg<\t\x18{?N\xca\x93\xf2\x0b\xc1\x91?\x0f9?\x94\xbb`\x82?\xab3\x1e\xc83No?\xf2{\x82\xd9|ZV?+\x96/\xa0\xee\xb2`?\xcaG\n\xfd\xf9[U?h\x80\x17\xe8\xb3>l?FY'\x16\xf4\x07\xa0?\x1f\xe7\xd2\xf1\xd51\xce?\xb5\xb6W\x82gX\xe0?\xb2\xd9~\x864\x16\xcd?" +p1402 +tp1403 +bsg218 +g226 +sg48 +(lp1404 +g0 +(g52 +g2 +Ntp1405 +Rp1406 +(dp1407 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1408 +g144 +tp1409 +Rp1410 +(I1 +(I16 +I1 +I1 +tp1411 +g38 +I00 +S"\xc2\xda\xf8\x96M\x81\x04@\xb4{\xact5\xd2\n@mi\xbf\x079Z\x13@\x08B\xc5\x10!\xb9\x01@|\xb7x~\xe6\x0c\xe3?~\xd4\x1f\xcdx\xf7\xf8?=\xe8x\xc8\x07\xd8\xe9?T<\xb5h\xfc\x02\xd6?L~\xdf\x91?o\xbf?-\xebB\x91\x9f{\xc7?\xf4t\xd6\x8bW\t\xbe?I\x860\x7f\x16\xdc\xd3?\x8aU'?/\x8b\x06@\x82J\x08n\n;5@\xefXK\x8fQ\xfcF@\x111\x91\xee\x9cs4@" +p1412 +tp1413 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1414 +g300 +asg93 +I10035 +sg246 +I01 +sbaatp1415 +Rp1416 +sg303 +I00 +sg304 +Nsbaa(lp1417 +g306 +ag0 +(g307 +g2 +Ntp1418 +Rp1419 +(dp1420 +g17 +g1235 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g311 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1421 +(lp1422 +g154 +ag0 +(g155 +g2 +Ntp1423 +Rp1424 +(dp1425 +g159 +I01 +sg160 +(lp1426 +g0 +(g162 +g2 +Ntp1427 +Rp1428 +(dp1429 +g166 +g141 +(g142 +(I0 +tp1430 +g144 +tp1431 +Rp1432 +(I1 +(I1 +tp1433 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1434 +tp1435 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1436 +Rp1437 +(dp1438 +g166 +g141 +(g142 +(I0 +tp1439 +g144 +tp1440 +Rp1441 +(I1 +(I17 +tp1442 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1443 +tp1444 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1445 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1446 +g144 +tp1447 +Rp1448 +(I1 +(I16 +I1 +I1 +tp1449 +g38 +I00 +S'\x97\x7f\xc9\x1e@\xc3\xf2?~\xc0\xd2\xd1i^\x00@\x82\xefV\xb3\x11$\x11@\xe8\xda\\.*\xdb\xec?\x99\xfc\xbb\t\x1c\xb2\xb0?kb\xef\xdc\x8f\xb1\xdc?Ml}\xab\xa3\xc4\xbe?\xae%\xb3\xcf\xadT\x96?\x8a\xa2M\xb4\x11\xc8f?\xa8F\xed\xa7Mmy?\xc6f\x01.W\xced?N\xe9\xf4\xb7\xd2.\x92?\x0b\xf5w\x88_o\xf7?\x86\xe8\xd5\xae\xbe\tT@!\x96[\xb6\xc4\x0cf@\x8e\x1d\xcby0\xe7X@' +p1450 +tp1451 +bsg203 +g141 +(g142 +(I0 +tp1452 +g144 +tp1453 +Rp1454 +(I1 +(I16 +I1 +I1 +tp1455 +g38 +I00 +S"fW/\x92\x17\xb2\x16?C\xcfe\xfc\x925\x1e?=+\x96M\x14\xad#?\x18\x03yF\x1a\x1d\x15?\xd6CI\xe5Y{\x07?\x1b\xcb^\xb7\x9fx\x10?\x05'\x83wS\x94\x07?\xf1\xbb\xf9\xb6\xdc2\x00?2%#2\xf9q\xf0>\xd7%\xb6\x1e{%\xf7>\xdb\x8c\xa5g\xd4^\xf1>\xf4\xb4\x18M\xdb\xa8\xfb>\xb0\x12Hq\xdc\xe7\x18?N\xb2\xeb\x14\x1a\xf0/?\x99\xde\xe9y\x19\x1d7?\x10\xe8\xd1\xe4\x16y>?" +p1456 +tp1457 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1458 +g144 +tp1459 +Rp1460 +(I1 +(I16 +I1 +I1 +tp1461 +g38 +I00 +S'/\x9f\xbf*\x948\xbd?e@~\xf5\x9cL\xc3?A+m\x07\x01\xee\xcb?N\x1e\xaa\xcf\xca\x9f\xb9?\xb3/F\x1c\xd4\x8f\x9b?\xb1%\xfe%]\x11\xb2?N:G@\x7f\xb5\xa2?\xd7\xa0rs\xb4\xdf\x8f?N\xd4)\xfd\xad\xc2v?\x84\xba\x013\xe8\x00\x81?\xeex\x877\xe2\xbfu?\xa1w\x10\xca\x1f\xc3\x8c?\x90\x8a\xea\x14$T\xc0?\x90(~\xb5\xd02\xee? \x93i%^f\xf6?\x9cB\x99\r&\xd5\xf0?' +p1462 +tp1463 +bsg218 +g226 +sg48 +(lp1464 +g0 +(g52 +g2 +Ntp1465 +Rp1466 +(dp1467 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1468 +g144 +tp1469 +Rp1470 +(I1 +(I16 +I1 +I1 +tp1471 +g38 +I00 +S'\xed\xbb\x0e.\xc8\x8b$@\x8e\x8a9\xb9\xbc#+@j\xc28\xb9X\xa33@O\x9d\x03\x9aZ\x04"@\x8aY\xe1#!a\x03@\x01em\xfdjh\x19@\xfd)d\xf2:O\n@\x17\x99,\xe1Ji\xf6?Gi\x01V\xe2\x00\xe0?In\xba\x87F\xe9\xe7?\x0e\x82\x16\x1e\xd6\x95\xde?\x1d\x94\x13Z29\xf4?\xda\xd2i\xbdR\xf6&@\x85\xb4\x9c\xbf\xba;U@\xe5v\x9cd\xf4\x7f_@\xab\x85\x1f\x83\xbd\xabW@' +p1472 +tp1473 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1474 +g245 +asg93 +I10038 +sg246 +I01 +sbaa(lp1475 +g367 +ag0 +(g155 +g2 +Ntp1476 +Rp1477 +(dp1478 +g159 +I01 +sg160 +(lp1479 +g0 +(g162 +g2 +Ntp1480 +Rp1481 +(dp1482 +g166 +g141 +(g142 +(I0 +tp1483 +g144 +tp1484 +Rp1485 +(I1 +(I1 +tp1486 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1487 +tp1488 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1489 +Rp1490 +(dp1491 +g166 +g141 +(g142 +(I0 +tp1492 +g144 +tp1493 +Rp1494 +(I1 +(I17 +tp1495 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1496 +tp1497 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1498 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1499 +g144 +tp1500 +Rp1501 +(I1 +(I16 +I1 +I1 +tp1502 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1503 +tp1504 +bsg203 +g141 +(g142 +(I0 +tp1505 +g144 +tp1506 +Rp1507 +(I1 +(I16 +I1 +I1 +tp1508 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1509 +tp1510 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1511 +g144 +tp1512 +Rp1513 +(I1 +(I16 +I1 +I1 +tp1514 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1515 +tp1516 +bsg218 +g226 +sg48 +(lp1517 +g0 +(g52 +g2 +Ntp1518 +Rp1519 +(dp1520 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1521 +g144 +tp1522 +Rp1523 +(I1 +(I16 +I1 +I1 +tp1524 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1525 +tp1526 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1527 +g420 +asg93 +I10039 +sg246 +I01 +sbaatp1528 +Rp1529 +sg303 +I00 +sg304 +Nsbaa(lp1530 +g424 +ag0 +(g425 +g2 +Ntp1531 +Rp1532 +(dp1533 +g17 +g1235 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g429 +sg46 +g134 +sg48 +Nsg430 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1534 +(lp1535 +g154 +ag0 +(g155 +g2 +Ntp1536 +Rp1537 +(dp1538 +g159 +I01 +sg160 +(lp1539 +g0 +(g162 +g2 +Ntp1540 +Rp1541 +(dp1542 +g166 +g141 +(g142 +(I0 +tp1543 +g144 +tp1544 +Rp1545 +(I1 +(I1 +tp1546 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1547 +tp1548 +bsg178 +Nsg23 +g446 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1549 +Rp1550 +(dp1551 +g166 +g141 +(g142 +(I0 +tp1552 +g144 +tp1553 +Rp1554 +(I1 +(I17 +tp1555 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1556 +tp1557 +bsg178 +Nsg23 +g456 +sg180 +I1 +sg181 +I16 +sbasg192 +g457 +sg194 +(lp1558 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1559 +g144 +tp1560 +Rp1561 +(I1 +(I16 +I1 +I1 +tp1562 +g38 +I00 +S'\xea\xda\xa3\x00\x87\xc4\xf2?\x15\xed(l\x1e]\x00@u\xd8\x99,\xc4\'\x11@\xb9&\x94-\x99\xc2\xec?h#\xab\x15\xbd\xbd\xb0?\xb1\xf4\xeb\xf5\xd6\xbe\xdc?B/~\xa1\xab\xa7\xbe?\xa6\x0e7\xdcvL\x96?\xeaK\xe5\xb4\xbd\x8df?\xf5\xc6p\x98\xb80y?*\xa2+]\x11Be?\xc5\xf8P\x94\xbed\x92?:\xcd\xa0f\xc3\x80\xf7?\xbbd\x03\xc6"\x10T@K:c\ny\x04f@?\xa2x\x0c\xe5\xe9X@' +p1563 +tp1564 +bsg203 +g141 +(g142 +(I0 +tp1565 +g144 +tp1566 +Rp1567 +(I1 +(I16 +I1 +I1 +tp1568 +g38 +I00 +S"']\x1f\xc1\x02'0?IM7!\xf4\x1b3?\xc0\xdb\x86\xb67\xf26?\xf8\x95\x00*bX,?m\x8c\xbe\xb6\x06\x99\x1e?\x89\x06\x12\x92/h(?\xdc\xe7w\x91\x99w\x1f?z\xff\xcf#\xee\x8e\x18?\xa0\xb3\xb1b\xf8m\t?\xdf\x83\xd2*\xd3Y\x11?\x8b\xfa\xe1\x0bMu\x08?\xf0A\xc6\x0bO\xe7\x17?\x92\xad\x94\xbb1\x08/?\x83\xc7\x80\x03\xddVI?w\xe4\x17\xe5\x93DJ?H\x98\xb7\xf0?\x83K?" +p1569 +tp1570 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1571 +g144 +tp1572 +Rp1573 +(I1 +(I16 +I1 +I1 +tp1574 +g38 +I00 +S"\xe2i\xedm68\xbd?}\xe6\xe6\xe9'K\xc3?\xf0c\xd8\xe3X\xf0\xcb?\x01\xeb\xd0\n\xb3\x93\xb9?w\x95 \x9fd\x94\x9b?|k\xdb!F\x14\xb2?\xd9=\x80\xf9\xb2\xaa\xa2?vV*~\x18\xce\x8f?\xa4b0z\xa4\x93v?3\xd3\xe4t\x95\xe1\x80?!\xe8\xe4C\x8a\xebu?\ntN\x1f\x11\xe1\x8c?\xe2\xfe7\x90\xa8Y\xc0?\xd1\x9f \xf1k7\xee?\x84\xb7\x8e\xc4\x15b\xf6?\x04`\x1dl\xfa\xd5\xf0?" +p1575 +tp1576 +bsg218 +g479 +sg48 +(lp1577 +g0 +(g52 +g2 +Ntp1578 +Rp1579 +(dp1580 +g56 +Nsg58 +Nsg59 +Nsg46 +g484 +sbasg232 +g141 +(g142 +(I0 +tp1581 +g144 +tp1582 +Rp1583 +(I1 +(I16 +I1 +I1 +tp1584 +g38 +I00 +S's\xeeJE\x86\x8b$@ \xb4\xec \xb0!+@E&4\x80\xfe\xa43@=\xe5\x9a\xe3\xd9\xfb!@\x18\xe9\xe2\xbfVd\x03@&\x8f\x9c\x9f\x82l\x19@\xf9V\xdc\xae\x0b@\n@\xcb\xc4\xb58\xe9\\\xf6?\xb6\n\xd4K\x9f\xbf\xdf?\x00\xc9a,:\xbd\xe7?o\xe6yo:\xd3\xde?\x97)\x03\n@N\xf4?n\xbe\xce\n\x15\xfe&@_\xf0\x8a\xe5\xf7>U@\x11\xb2h\x9c\xeey_@\x05O\t(\xe8\xacW@' +p1585 +tp1586 +bsg239 +g491 +sg241 +I01 +sg242 +I01 +sg243 +(lp1587 +g493 +asg93 +I10042 +sg246 +I01 +sbaa(lp1588 +g495 +ag0 +(g155 +g2 +Ntp1589 +Rp1590 +(dp1591 +g159 +I01 +sg160 +(lp1592 +g0 +(g162 +g2 +Ntp1593 +Rp1594 +(dp1595 +g166 +g141 +(g142 +(I0 +tp1596 +g144 +tp1597 +Rp1598 +(I1 +(I1 +tp1599 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1600 +tp1601 +bsg178 +Nsg23 +g509 +sg180 +I256 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1602 +Rp1603 +(dp1604 +g166 +g141 +(g142 +(I0 +tp1605 +g144 +tp1606 +Rp1607 +(I1 +(I17 +tp1608 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1609 +tp1610 +bsg178 +Nsg23 +g519 +sg180 +I16 +sg181 +I16 +sbag0 +(g162 +g2 +Ntp1611 +Rp1612 +(dp1613 +g166 +g141 +(g142 +(I0 +tp1614 +g144 +tp1615 +Rp1616 +(I1 +(I17 +tp1617 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1618 +tp1619 +bsg178 +Nsg23 +g529 +sg180 +I1 +sg181 +I16 +sbasg192 +g530 +sg194 +(lp1620 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1621 +g144 +tp1622 +Rp1623 +(I1 +(I256 +I1 +I1 +tp1624 +g38 +I00 +S':\xd6\x80\x99\xd3\x8b\xad?\xa1\x8a\xfc\x17\x9c\x8aJ?4\xeb\x97a\x82\xe75>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8d\\q\x99e[N?R\xda\xad\xba\rp\xb5?\xc8a\x11\xbb\xe69Q?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6\x9c\xdeC\rH>H\xf2\x04\xde\xa3\xe0T?\x86\xe9\xfd\xfb\x1a-\xcb?\x0b>\xa2I/X$?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xfb=}Q\xa8\x0e\x05\xf12?\xb3,w3\xda\xdb\xa6?*\xe9\x96\xc8\x06\x8c\xf5>\xbc\xbd\xd7\xd9\xdf|\xeb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=f\x8b\xac\xbc\xf2\xce\x19?\x86\x08\xb8\xdf\x1a\xcac?"fS\xeb\n(\xee>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\xc3-\x14i\x91O>\xd7?~`\x164\x17?\xda\xc9\xbd\x87&\xec\x97?\x88\xa0Mz\x16~\xd4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\xe2\xdf\x84\xd6\x8c\x12?\x1a\xad\x05\x1ea\x16w?B\x1c\x98\x08\xce3\xc3>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\xb5\x12\xd5{\xec\x1e>\xfc\xd6EG6\xbb\x0c?U\x04\xd2#a\xb6H?\xcf*F\x884k\xbe>\xbf\xdc|"\x95BE>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=RPU\x1b\xffiJ>C:\x08n\'\x80\x00?\x0b\xea,\xd2\x83D\x03?i\x16\x8d\x19\xc6t\xb8>O\xcea\xe3\xa7\x9d\x14>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xb1+e\xcdS3>\x92\x02\xe9,\xbcU\xc3>N\xe4\xb9o\x12R\xf9>\xc8\xf9\x9f\x9b\xfd\xca!?r\xa3n\x0f\x15v\xb7>ds\xe1\xd3b\xc8?>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xbd\xd7\xd9\xdf|\x0b>[O\x99H\x95\xdbP>\x97\x8eN!\x04Y\x90>\xc9P\x94@\x95\x9e\xfa>\xd9\x1fv\x8f}#\x02?\xea\xae\xba\xb6Ar\xb5>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\x0b>\x8a5\x8eg\xff\x9bA>j3\x1f\x9d$ I>\xb2^\xdd\x19s|\xc0>\xbd\xfd\xf7^\xc7\xf1\xff>\x8bz\x1a\xceBdD?7\xa7\xcab\xdf(\xb2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\xbe\xbd\xd7\xd9\xdf|\x0b>u\xb5\x12\xd5{\xec\x1e>\x85\x94\xf5\xe6\xf2\t2>\x1b\xa9f`i\xc3F>\xb0\xa4I\xd1\x9d\xf3\t?l\xc6\x82%\xcb\x87\xb5?\x85\x04EY\xe3_p>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6\x05\x98)\x91\xb3\x05?\xc3\xa8\x14Z\xde\xe2\x13@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001\xaf\x17R\x1b\xdf\x12?\xb0/\t\xb2\x86Q7@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe2A:\xdc\x11\xc5)>\xb8\x93\x01\xdbZ\xca\x9b?H\xd5L\xb8D\x99\x0f@' +p1625 +tp1626 +bsg203 +g141 +(g142 +(I0 +tp1627 +g144 +tp1628 +Rp1629 +(I1 +(I256 +I1 +I1 +tp1630 +g38 +I00 +S'\r\xe7\x91\xdd~\xf0\x0c?\x9e\x0e\x9b\x02\xe4\x03\xf5>\xd2{m\xf8\xad\xe4\xa5>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\xde#(r\xbc\xf3>V\xa8X\x0fsU\x11?u\xf3\xceB"7\xf3>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LX\x95kpq\xac>\x80\xd7\xf9\x9f\xfc\xcf\xf4>q\x8d\xff\x84Q\xcf\x14?\xb1$\xe3\x11\x9b(\xee>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00i\xf02\xc5\xb4Q\x8d>\xca\xb7\xd7\x10\xb6\x12\xeb>\x82\x83\xc0\x1b3\xfd\t?\xd44\x13\xca\xac\xd9\xe0>\x8bq\xc3\xb8\xb1\xf8\x84>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>T\xe0\x99m\xa2\xb2\xe5>C\xd3\x19\x89C\xde\xfb>\xd4d\x02\xc9-=\xde>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x95\xfaEI\xe2\xb0>\x83\x99\x99\xef\xab\xb0\xe6>\x95\x9fRn\x91\x87\x07?:\x9bwFz_\xd4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xeb\x0b\xec\x17\xf09\xe5>\xc6\xe1sne[\xfe>\xe5\xac\xdf\xb9\x10\x18\xd1>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc4O\xe7\xf5\xe70\x9d>\xdf\xbb\xa0\xc3\x9b\xc2\xe0>\xdb\xbeF\xb2\xa0\xf6\xf5>\xf3\xf6o\xe9H \xd0>\x18\x85\xce\x84d\x1e\xad>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00:\xeeV\x85\xaf\xae>_\x16\xdb>j\x00\xe2>\x1b\x1fEw\xa2R\xe0>\xae\xdd\xfb\x84\xd0\xc9\xcd>\x85\x97\x03\x10l.\x98>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!^\x93\xfc\xc2\xdf\xa3>R\xc5\xcf\xfd\x9d\x90\xcb>\x91\xa9\xa8\xca+ \xe1>+\\dM3G\xe7>/\xbe`k\x02\xb0\xce>\xf1\x8e\x98\xa8:\x15\xaa>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc1\x87\xad\x91p>\x94>\xae\xb2m\xbf\xf3\xe4\xb1>Y\x83P\xe1\xde\\\xc1>^8\xe6\r\x06\xd5\xde>\x03\xf6\xf4H\x13\x9a\xe2>\x05wi%\x1f\xe8\xcd>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc7\x00\xac\x89\xe2\xab\x94>r\xe1\xab\x8b=\xac\xac>J|n\x14Qa\xaf>\xe34\xd7\xfb\xd1\x8f\xd0>\xb37\x1d\x80}\xe1\xe3>\xb5jq\xd8\\\x94\xf2>CA\xe1\x95f\xf0\xce>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xc1\x87\xad\x91p>\x94>\xc4\xc2\x98V\x7f\xd3\x9d>a\x0cD\xfe0\xbf\xa4>+\xb3\xbd\xfd?t\xac>\x1fR\x19\rc\xbd\xe0>X\x08\x8f\xcaM\xe9\x0e?43\x9a\xc5\xf4\xa1\xbb>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\xb7\x81\xb1\xca\xb0\xe0>\x90F-\xcb\xac_)?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*F\xad\xc9\xeeF\xe8>BM?\xe7e\xdc0?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xeb}\x8f\x9d6\xa2>\xe0\xc9:\xcf{\xcd\x06?s\xd6C%b\xd9%?' +p1631 +tp1632 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1633 +g144 +tp1634 +Rp1635 +(I1 +(I256 +I1 +I1 +tp1636 +g38 +I00 +S'vr\xc2\xd3\x8d\xec\x99?\x8a\xf6\xb1\x82\xdf\x86h?\xb2\x16\xc5\x98\xe1,\xd2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.<\xf3#\x1c>j?\x80#\x81\x06\x9b:\x9f?\xf6\x90,\xaf\xbe\xf6k?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x8a[\xa3\xa9O\xe0>\xd8\x81$\x8aT\xc9n??vf\xe4h\xdd\xa8?A\xbcrn\xb1fU?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x9d>eO\xa0\x13\xf3J]?\x9a\xc2]\xd0U\xcd\x96?\xe1\x9ad \x1e\xeb>?\xc3\xc2\x98V\x7f\xd3\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xe7\x01\x19\'\xab\x0fQ? -\x1d\xd5%2u?\x10\x96b\xe5[\xd09?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\xe5\x17\x9a:\xf1\xe1>\xc6\x964\xa8r)P?\xfe+Ts\x08~\x90?\x87[\xef\xd5R\xf1-?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x93\xee#\x06\xe3L?\xebO\x80\xec\xa62\x80?z\xa7\xc6\xfczI$?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\xbd>\xaf\xf8s\xf7&sI?\xff\x8b\xa01\x93\xa8g?r^\xd8\xe9i\xfc!?\x94\xd3\xd4c\xf9~\xdb>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\r\xbc\x08\xa2P\x8b\xe0>W\xcf\xfa2\xdc1C?\x958\xdc\xe5\xe6\xccD?\x15,\x99\x14\xbd\x17 ?\x12\x92\xf2\x80\x9f^\xb6>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb3\x16\xc5\x98\xe1,\xd2>a%\x1f\xbb\x0b\x94$?\x18W\xab\xd8\xd4\xc8@?\xc9f!\x14n\x0cT?\n\xd1\xa9\x8d&f\x1f?\x17\x92\xf2\x80\x9f^\xd6>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\xad>.\xe5\x17\x9a:\xf1\xe1>\x1b}g\xf0FH\t?\xe9n\x00r\x11AA?2J\xaa\xc9f!D?\xb7\x01\xc5\xb5\xc7\xf8\x1d?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\xa6>\x00\xcc=\x86\x03p\xd5>\xd7%\xf3S\xcdJ\xde>f?\x8b\xa5H\xbe"?\x81\x9b\x01}\x84\xd6B?\xc0r\xe6\x93d\x7fe?\x06\xa2\'eRC\x1b?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\xc3\xc2\x98V\x7f\xd3\xad>k\xaa\xc5k\x0f\x19\xba>\xc7\xc2\x98V\x7f\xd3\xcd>\xe1\x88MQ\x1b\xc2\xde>\xda\xd1\xb0\xb6\xed,H?D\r};:L\x9f?\x0e/\x98\x83Q\xe7\xf5>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb5}\x8f\xfa\xeb\x15F?\x80F\x0fiA\x15\xce?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaci\xcb\xa6I\x16M?\x1c\xecM\x0c\xc9I\xe0?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\xc6>?o\xc8\xca\xe0\xc6\x91?\xc7\t\x88\x98t\xd0\xca?' +p1637 +tp1638 +bsg218 +g552 +sg48 +(lp1639 +g0 +(g52 +g2 +Ntp1640 +Rp1641 +(dp1642 +g56 +Nsg58 +Nsg59 +Nsg46 +g557 +sbasg232 +g141 +(g142 +(I0 +tp1643 +g144 +tp1644 +Rp1645 +(I1 +(I256 +I1 +I1 +tp1646 +g38 +I00 +S'{\xb8\xe4\xb8S:\x02@Y!\xe5\'\xd5>\xd1?\xeb\'\xd5>\x1d\x8f9?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x06G\xc9\xabs\xd2?\xf6\xcc\x92\x005\xf5\x05@\xedU+\x13~\xa9\xd3?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\xba\xb8\x8d\x06\xf0F?L\xab!q\x8f\xa5\xd5?$\x0b\x98\xc0\xad{\x11@\xbcXQ\x83i\x18\xbe?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\x04?\xd3\xb7\xcc\xe9\xb2\x98\xc4?\xd4\xec\x81V`\x08\x00@\xe6\xbc\xc6.Q\xbd\xa5?\xf1h\xe3\x88\xb5\xf8\xf4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\xad*\xfb\xae\x08\xfe\xb7?u\x07\xb13\x85\xce\xdd?\x83QI\x9d\x80&\xa2?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x9a\xb1h:;I?\x07\xf4\x89\xae\r\x95?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p\xbfCQ\xa0O\xb4?cp\x94\xbc:\xc7\xe6?\x83[w\xf3T\x87\x8c?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8$?\xdb\x8a\xfde\xf7\xe4\xb1?o\xe2\xe4~\x87\xa2\xd0?\xd0D\xd8\xf0\xf4J\x89?\xc4\xa41ZGUC?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>rH\xdcc\xe9CG?\x93\xb3\xb0\xa7\x1d\xfe\xaa?\x91\xaf=\xb3$@\xad?\xfde\xf7\xe4a\xa1\x86?i\x1dUM\x10u\x1f?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\'\xd5>\x1d\x8f9?\x91\xcc#\x7f0\xf0\x8c?z\xf2\xb0Pk\x9a\xa7?\x8b\xf8N\xccz1\xbc?\xfbf\x9b\x1b\xd3\x13\x86?p\x1dUM\x10u??\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\x14?I\x9a\xb1h:;I?\xf7\xc3\x08\xe1\xd1\xc6q?\xf7\x9bP\x88\x80C\xa8?Vx\x97\x8b\xf8N\xac?5\x85\xcek\xec\x12\x85?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x1dUM\x10u\x0f?\xe0\xe6\xc6\xf4\x84%>?\x9b\xf6\x06_\x98LE?\'\xd1\xcb(\x96[\x8a?\xaeB\xcaO\xaa}\xaa?^\x11\xfco%;\xce?\xec\xdd\x1f\xefU+\x83?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\xf1h\xe3\x88\xb5\xf8\x14?\xd3\xfb\xc6\xd7\x9eY"?\xf4h\xe3\x88\xb5\xf84?>\x84*5{\xa0E?\x8dSt$\x97\xff\xb0?T\xed\xd3\xf1\x98\x01\x06@+\x02\x0e\xa1J\xcd^?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc7\xc8Y\xd8\xd3\x0e\xaf?\x92\xbd\xde\xfd\xf1&5@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\x06G\xc9\xabs\xb4?\x08\x94M\xb9\xc2\xe7F@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00i\x1dUM\x10u/?q\xdc)\x1d\xac\xff\xf8?\xe0\xa6?\xfb\x91\xda2@' +p1647 +tp1648 +bsg239 +g564 +sg241 +I01 +sg242 +I01 +sg243 +(lp1649 +g566 +asg93 +I10043 +sg246 +I01 +sbaatp1650 +Rp1651 +sg303 +I00 +sg304 +Nsbaa(lp1652 +g570 +ag0 +(g571 +g2 +Ntp1653 +Rp1654 +(dp1655 +g17 +g1235 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g570 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1656 +(lp1657 +g577 +ag0 +(g155 +g2 +Ntp1658 +Rp1659 +(dp1660 +g159 +I01 +sg160 +(lp1661 +g0 +(g162 +g2 +Ntp1662 +Rp1663 +(dp1664 +g166 +g141 +(g142 +(I0 +tp1665 +g144 +tp1666 +Rp1667 +(I1 +(I1 +tp1668 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1669 +tp1670 +bsg178 +Nsg23 +g591 +sg180 +I1 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1671 +Rp1672 +(dp1673 +g166 +g141 +(g142 +(I0 +tp1674 +g144 +tp1675 +Rp1676 +(I1 +(I2 +tp1677 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1678 +tp1679 +bsg178 +Nsg23 +g601 +sg180 +I1 +sg181 +I1 +sbasg192 +g602 +sg194 +(lp1680 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1681 +g144 +tp1682 +Rp1683 +(I1 +(I1 +I1 +I1 +tp1684 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1685 +tp1686 +bsg203 +g141 +(g142 +(I0 +tp1687 +g144 +tp1688 +Rp1689 +(I1 +(I1 +I1 +I1 +tp1690 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1691 +tp1692 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1693 +g144 +tp1694 +Rp1695 +(I1 +(I1 +I1 +I1 +tp1696 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1697 +tp1698 +bsg218 +g624 +sg48 +(lp1699 +g0 +(g52 +g2 +Ntp1700 +Rp1701 +(dp1702 +g56 +Nsg58 +Nsg59 +Nsg46 +g629 +sbasg232 +g141 +(g142 +(I0 +tp1703 +g144 +tp1704 +Rp1705 +(I1 +(I1 +I1 +I1 +tp1706 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1707 +tp1708 +bsg239 +g636 +sg241 +I01 +sg242 +I01 +sg243 +(lp1709 +g638 +asg93 +I10046 +sg246 +I01 +sbaa(lp1710 +g640 +ag0 +(g155 +g2 +Ntp1711 +Rp1712 +(dp1713 +g159 +I01 +sg160 +(lp1714 +g0 +(g162 +g2 +Ntp1715 +Rp1716 +(dp1717 +g166 +g141 +(g142 +(I0 +tp1718 +g144 +tp1719 +Rp1720 +(I1 +(I1 +tp1721 +g173 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1722 +tp1723 +bsg178 +Nsg23 +g654 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1724 +Rp1725 +(dp1726 +g166 +g141 +(g142 +(I0 +tp1727 +g144 +tp1728 +Rp1729 +(I1 +(I17 +tp1730 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1731 +tp1732 +bsg178 +Nsg23 +g664 +sg180 +I1 +sg181 +I16 +sbasg192 +g665 +sg194 +(lp1733 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1734 +g144 +tp1735 +Rp1736 +(I1 +(I16 +I1 +I1 +tp1737 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1738 +tp1739 +bsg203 +g141 +(g142 +(I0 +tp1740 +g144 +tp1741 +Rp1742 +(I1 +(I16 +I1 +I1 +tp1743 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1744 +tp1745 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1746 +g144 +tp1747 +Rp1748 +(I1 +(I16 +I1 +I1 +tp1749 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1750 +tp1751 +bsg218 +g687 +sg48 +(lp1752 +g0 +(g52 +g2 +Ntp1753 +Rp1754 +(dp1755 +g56 +Nsg58 +Nsg59 +Nsg46 +g692 +sbasg232 +g141 +(g142 +(I0 +tp1756 +g144 +tp1757 +Rp1758 +(I1 +(I16 +I1 +I1 +tp1759 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p1760 +tp1761 +bsg239 +g699 +sg241 +I01 +sg242 +I01 +sg243 +(lp1762 +g701 +asg93 +I10047 +sg246 +I01 +sbaatp1763 +Rp1764 +sg303 +I00 +sg304 +Nsbaatp1765 +Rp1766 +aa(lp1767 +I10003 +ag7 +((lp1768 +(lp1769 +g12 +ag0 +(g13 +g2 +Ntp1770 +Rp1771 +(dp1772 +g17 +g0 +(g18 +g2 +Ntp1773 +Rp1774 +(dp1775 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g0 +(g27 +g2 +Ntp1776 +Rp1777 +(dp1778 +g31 +g32 +sg33 +g34 +(g38 +S'\xbfu\xda\xc4\x97\x08\xb3?' +p1779 +tp1780 +Rp1781 +sg44 +(lp1782 +(VHH2O +p1783 +V71t +p1784 +tp1785 +asg46 +VBorated Water +p1786 +sg48 +g7 +((lp1787 +(lp1788 +VB-10 +p1789 +a(g0 +(g52 +g2 +Ntp1790 +Rp1791 +(dp1792 +g56 +V71c +p1793 +sg58 +Nsg59 +Nsg46 +g1789 +sbg34 +(g38 +S'\x8a\x85\xac6\xb0\xd3\xe0>' +p1794 +tp1795 +Rp1796 +g63 +tp1797 +aa(lp1798 +VB-11 +p1799 +a(g0 +(g52 +g2 +Ntp1800 +Rp1801 +(dp1802 +g56 +V71c +p1803 +sg58 +Nsg59 +Nsg46 +g1799 +sbg34 +(g38 +S'U\x07\xff:\xc2\xee\x00?' +p1804 +tp1805 +Rp1806 +g63 +tp1807 +aa(lp1808 +VH-1 +p1809 +a(g0 +(g52 +g2 +Ntp1810 +Rp1811 +(dp1812 +g56 +V71c +p1813 +sg58 +Nsg59 +Nsg46 +g1809 +sbg34 +(g38 +S'\xd7S\xaa_7b\xa9?' +p1814 +tp1815 +Rp1816 +g63 +tp1817 +aa(lp1818 +VO-16 +p1819 +a(g0 +(g52 +g2 +Ntp1820 +Rp1821 +(dp1822 +g56 +V71c +p1823 +sg58 +Nsg59 +Nsg46 +g1819 +sbg34 +(g38 +S':\xda\xf0|^S\x99?' +p1824 +tp1825 +Rp1826 +g63 +tp1827 +aatp1828 +Rp1829 +sg87 +g7 +((lp1830 +tp1831 +Rp1832 +sg91 +I00 +sg92 +Nsg93 +I10003 +sbsg94 +Nsg46 +Vwater +p1833 +sg96 +g0 +(g97 +g2 +Ntp1834 +Rp1835 +(dp1836 +g101 +g1293 +sg126 +g749 +sbsg128 +Nsg93 +I10003 +sbsg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g12 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1837 +(lp1838 +g154 +ag0 +(g155 +g2 +Ntp1839 +Rp1840 +(dp1841 +g159 +I01 +sg160 +(lp1842 +g0 +(g162 +g2 +Ntp1843 +Rp1844 +(dp1845 +g166 +g141 +(g142 +(I0 +tp1846 +g144 +tp1847 +Rp1848 +(I1 +(I1 +tp1849 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1850 +tp1851 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1852 +Rp1853 +(dp1854 +g166 +g141 +(g142 +(I0 +tp1855 +g144 +tp1856 +Rp1857 +(I1 +(I17 +tp1858 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1859 +tp1860 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1861 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1862 +g144 +tp1863 +Rp1864 +(I1 +(I16 +I1 +I1 +tp1865 +g38 +I00 +S"\x17\x97\xb8\x1b=\xf0J@\t\xe5\x87<\x15OU@\xc3D\xf9\xdbXDe@sV\xf0\x11\x19cA@\xd5\x12\xbb\xa3\xe2\x01\x04@\x84\x80a,s\xd60@kh6zV\xe1\x11@\xdd\x00\x01T\xce\n\xea?\xe9i\xfd\xd2\x1c\x94\xba?\xabl\x96\xccA\xd1\xcd?\x00\x1e\xaf\\;`\xb8?E\x0e4x\x15+\xe5?\xce\xd7\x13\xf2[\x15K@)\xeb\xb3\xf2\x95{\xa7@Z,\xe9\x90\xd5Z\xb8@\xc2\x02'R\xff\xe5\xaa@" +p1866 +tp1867 +bsg203 +g141 +(g142 +(I0 +tp1868 +g144 +tp1869 +Rp1870 +(I1 +(I16 +I1 +I1 +tp1871 +g38 +I00 +S'\xd6.m\x9ad\x82@?\x88d\xde<\x07\x94C?\xf6@\xfd\xba}\x7fH?2\xc3[\xe1_89?\x0f\xf5qt\xccB,?\xd4\xc1=i\x88x5?\x88\'P#4x,?\xb8\xb2\x9dp\r^"?\xe8/7)Y\xb1\x11?\xf6A\x07t\xb1\xe2\x19?=\xf82\x1e\xde\xd3\x13?\xc1\xf5bjQ\xd5"?77UdP\x92;?\xc7^\xfd\x90e\x99S?\xebQ\xa6q\r\xbe_?\x18p\xf2\x93\xa6\xa7e?' +p1872 +tp1873 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1874 +g144 +tp1875 +Rp1876 +(I1 +(I16 +I1 +I1 +tp1877 +g38 +I00 +S'U\x8d\xa8.#\xc2\xe8?\xd5(m\x96\x16$\xef?\x81\xf0y\x96\x96\xff\xf5?\xbaD\\n\x04\xe4\xe3?3\x15\x9e\x9b\xeeU\xc5?f\xd9\x8b\xfbs\xae\xdb?C4\xad\x98k\x86\xcc?\x835\x9c\x10TW\xb8?\x1a\xb2\xf0c\x01c\xa1?\xfa"wl<\x0b\xaa?\xa10\xc0 N\xa6\xa0?_\xf89\xea\xe0\xf1\xb5?\r-\xcb\x9f5\xd3\xe8?\xc4\xc1\x94\xbc\xc2\x1d\x17@\x89\xde\xfb\x06z\xa5 @,\xebhX\x7f\xbd\x18@' +p1878 +tp1879 +bsg218 +g226 +sg48 +(lp1880 +g0 +(g52 +g2 +Ntp1881 +Rp1882 +(dp1883 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1884 +g144 +tp1885 +Rp1886 +(I1 +(I16 +I1 +I1 +tp1887 +g38 +I00 +S'`\x83\xce\xbc\x80hQ@\xb6\xc0\xc4\xe1_\xe5U@6z\x9b\xc3k\xef^@\xa6\xc01;\xa6\xf8K@\xd0M\xd6\x8a\xd7\x00.@\xdcT\xde\x8c\xa9vC@\xbf\xc8Y\xa7\x83\x0e4@\xa0\xd5\xad\x1bg\x1d!@tz\x8a\xf49s\x08@\x98\xc4C|\xe6O\x12@bD\x0e\xde\xddi\x07@F\x85aI$\xdc\x1e@\xad\xdbZ\xb4\x81tQ@>\x98\x98\xec\xec@\x80@\xf00\xd2\x99\xb3h\x87@[\xc5)\x8a=e\x81@' +p1888 +tp1889 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1890 +g245 +asg93 +I10050 +sg246 +I01 +sbaa(lp1891 +g12 +ag0 +(g155 +g2 +Ntp1892 +Rp1893 +(dp1894 +g159 +I01 +sg160 +(lp1895 +g0 +(g162 +g2 +Ntp1896 +Rp1897 +(dp1898 +g166 +g141 +(g142 +(I0 +tp1899 +g144 +tp1900 +Rp1901 +(I1 +(I1 +tp1902 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1903 +tp1904 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1905 +Rp1906 +(dp1907 +g166 +g141 +(g142 +(I0 +tp1908 +g144 +tp1909 +Rp1910 +(I1 +(I17 +tp1911 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1912 +tp1913 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1914 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1915 +g144 +tp1916 +Rp1917 +(I1 +(I16 +I1 +I1 +tp1918 +g38 +I00 +S'\xa9\xbd\xfa\x0f\x98\xe3\x80@\xd6.rr\x14\xf7z@\x9a\xaf\xc9.\xbc\xd2\x81@\xe4R\xa1(x\xdcS@/@\x0f\x937\x96\x12@\x01@\x82\xa4!\xc3:@\xfc$\x18\xc2\xdb\x90\x19@\xcb\x8a\x8c\xe5\x01\x1c\xf2?\xd7^0H\x87I\xc2?F\x8b(k\xa4_\xd4?\x08\x93\xb8em\x8c\xc0?5\x93\xb7\xd4\xa3\x80\xec?\xbd\xe6\xba6\r\x8dQ@L\xdeNx\xcd\xa4\xac@\xec\xc7\xa4\xdb~\xcb\xa4@\xba\xa8_#z\xf6a@' +p1919 +tp1920 +bsg203 +g141 +(g142 +(I0 +tp1921 +g144 +tp1922 +Rp1923 +(I1 +(I16 +I1 +I1 +tp1924 +g38 +I00 +S"\xe8\xa1\xa4&KJZ?\xa6\xe8\xcdrm\xebU?\xe5\x16i\x0fr\x8eV?\xd3\xb5\xc1:n9C?N\x8ct\xbd~G3?\x000r\x9b\xab\x02;?\x1d\xac\x11\xdd\xb1\x041?\x82&x \xe8\xa9%?\xe5+W'\xa8\xc1\x14?\xdc\xc2\xbe\xfc\x82C\x1e?\x1c\xb9Ia\xbf\x19\x17?\x88{\xf2\x10\xda\xda%?\xb8\xe8u\xf9\xa1`??\x06h\x01\\\x86\xa7U?`\xdds\x0f}\x9bT?\xb5\xe0\xe6B\xc8\x84A?" +p1925 +tp1926 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1927 +g144 +tp1928 +Rp1929 +(I1 +(I16 +I1 +I1 +tp1930 +g38 +I00 +S'\xf9\x05\xb3\xa8\x8b\x9a\x03@)h\x14\xf5\xf8\x83\x01@G!\x15E\x7f#\x04@\xf3g\xae8\x83\x10\xee?Ny\x17^\x10\x15\xcd?\x00\x1e\xa0\x89\x07s\xe1?\xf5\x95\xc6\xa3\xf7\r\xd1?\x98\xeeQ\xa9\xab\xb4\xbc?\xd5\x8d\n\xa6Te\xa4?\x15_\xcf\x13\xfdq\xae?[\xa8\xbbP\x99f\xa3?\x0b\x08M \xd9v\xb9?\x06\xceZ#\x16C\xec?\x80\xbc\xb7g\xc9\x87\x19@\x86S\xef%\xcb\xc0\x15@\xfd\xe5\xb2\x98\xad7\xf4?' +p1931 +tp1932 +bsg218 +g226 +sg48 +(lp1933 +g0 +(g52 +g2 +Ntp1934 +Rp1935 +(dp1936 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1937 +g144 +tp1938 +Rp1939 +(I1 +(I16 +I1 +I1 +tp1940 +g38 +I00 +S'f\xc0;eT\x91k@y\xb2\xa4\x18\x96\xa1h@\xcc\xb6%\xf9\xeaQl@\x17\xa1\xdaC\x9c#U@K\x81(\x82\xcfr4@0*\x89\x99\xc2\x89H@\xe1BO>\xa4\xfb7@\xc3\x9b\r\xb3\x08/$@t\xd7~\t\x7f\xae\x0c@\xdb\xce\xed\xf1%h\x15@\xc0\xe4\x87\x99GH\x0b@\xa8)\xb6\xaa\x90\xe7!@\xdc\xd8\xdb\x90+\xdfS@\x8a0\xed\x9cy\xf3\x81@u\x8dX\xad\x1d\x97~@l\x93\xbb\x1eLn\\@' +p1941 +tp1942 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp1943 +g300 +asg93 +I10051 +sg246 +I01 +sbaatp1944 +Rp1945 +sg303 +I00 +sg304 +Nsbaa(lp1946 +g306 +ag0 +(g307 +g2 +Ntp1947 +Rp1948 +(dp1949 +g17 +g1774 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g311 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp1950 +(lp1951 +g154 +ag0 +(g155 +g2 +Ntp1952 +Rp1953 +(dp1954 +g159 +I01 +sg160 +(lp1955 +g0 +(g162 +g2 +Ntp1956 +Rp1957 +(dp1958 +g166 +g141 +(g142 +(I0 +tp1959 +g144 +tp1960 +Rp1961 +(I1 +(I1 +tp1962 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1963 +tp1964 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp1965 +Rp1966 +(dp1967 +g166 +g141 +(g142 +(I0 +tp1968 +g144 +tp1969 +Rp1970 +(I1 +(I17 +tp1971 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p1972 +tp1973 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp1974 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp1975 +g144 +tp1976 +Rp1977 +(I1 +(I16 +I1 +I1 +tp1978 +g38 +I00 +S"\x17\x97\xb8\x1b=\xf0J@\t\xe5\x87<\x15OU@\xc3D\xf9\xdbXDe@sV\xf0\x11\x19cA@\xd5\x12\xbb\xa3\xe2\x01\x04@\x84\x80a,s\xd60@kh6zV\xe1\x11@\xdd\x00\x01T\xce\n\xea?\xe9i\xfd\xd2\x1c\x94\xba?\xabl\x96\xccA\xd1\xcd?\x00\x1e\xaf\\;`\xb8?E\x0e4x\x15+\xe5?\xce\xd7\x13\xf2[\x15K@)\xeb\xb3\xf2\x95{\xa7@Z,\xe9\x90\xd5Z\xb8@\xc2\x02'R\xff\xe5\xaa@" +p1979 +tp1980 +bsg203 +g141 +(g142 +(I0 +tp1981 +g144 +tp1982 +Rp1983 +(I1 +(I16 +I1 +I1 +tp1984 +g38 +I00 +S'\xd6.m\x9ad\x82@?\x88d\xde<\x07\x94C?\xf6@\xfd\xba}\x7fH?2\xc3[\xe1_89?\x0f\xf5qt\xccB,?\xd4\xc1=i\x88x5?\x88\'P#4x,?\xb8\xb2\x9dp\r^"?\xe8/7)Y\xb1\x11?\xf6A\x07t\xb1\xe2\x19?=\xf82\x1e\xde\xd3\x13?\xc1\xf5bjQ\xd5"?77UdP\x92;?\xc7^\xfd\x90e\x99S?\xebQ\xa6q\r\xbe_?\x18p\xf2\x93\xa6\xa7e?' +p1985 +tp1986 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp1987 +g144 +tp1988 +Rp1989 +(I1 +(I16 +I1 +I1 +tp1990 +g38 +I00 +S'U\x8d\xa8.#\xc2\xe8?\xd5(m\x96\x16$\xef?\x81\xf0y\x96\x96\xff\xf5?\xbaD\\n\x04\xe4\xe3?3\x15\x9e\x9b\xeeU\xc5?f\xd9\x8b\xfbs\xae\xdb?C4\xad\x98k\x86\xcc?\x835\x9c\x10TW\xb8?\x1a\xb2\xf0c\x01c\xa1?\xfa"wl<\x0b\xaa?\xa10\xc0 N\xa6\xa0?_\xf89\xea\xe0\xf1\xb5?\r-\xcb\x9f5\xd3\xe8?\xc4\xc1\x94\xbc\xc2\x1d\x17@\x89\xde\xfb\x06z\xa5 @,\xebhX\x7f\xbd\x18@' +p1991 +tp1992 +bsg218 +g226 +sg48 +(lp1993 +g0 +(g52 +g2 +Ntp1994 +Rp1995 +(dp1996 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp1997 +g144 +tp1998 +Rp1999 +(I1 +(I16 +I1 +I1 +tp2000 +g38 +I00 +S'`\x83\xce\xbc\x80hQ@\xb6\xc0\xc4\xe1_\xe5U@6z\x9b\xc3k\xef^@\xa6\xc01;\xa6\xf8K@\xd0M\xd6\x8a\xd7\x00.@\xdcT\xde\x8c\xa9vC@\xbf\xc8Y\xa7\x83\x0e4@\xa0\xd5\xad\x1bg\x1d!@tz\x8a\xf49s\x08@\x98\xc4C|\xe6O\x12@bD\x0e\xde\xddi\x07@F\x85aI$\xdc\x1e@\xad\xdbZ\xb4\x81tQ@>\x98\x98\xec\xec@\x80@\xf00\xd2\x99\xb3h\x87@[\xc5)\x8a=e\x81@' +p2001 +tp2002 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp2003 +g245 +asg93 +I10054 +sg246 +I01 +sbaa(lp2004 +g367 +ag0 +(g155 +g2 +Ntp2005 +Rp2006 +(dp2007 +g159 +I01 +sg160 +(lp2008 +g0 +(g162 +g2 +Ntp2009 +Rp2010 +(dp2011 +g166 +g141 +(g142 +(I0 +tp2012 +g144 +tp2013 +Rp2014 +(I1 +(I1 +tp2015 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2016 +tp2017 +bsg178 +Nsg23 +g179 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp2018 +Rp2019 +(dp2020 +g166 +g141 +(g142 +(I0 +tp2021 +g144 +tp2022 +Rp2023 +(I1 +(I17 +tp2024 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p2025 +tp2026 +bsg178 +Nsg23 +g191 +sg180 +I1 +sg181 +I16 +sbasg192 +g193 +sg194 +(lp2027 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp2028 +g144 +tp2029 +Rp2030 +(I1 +(I16 +I1 +I1 +tp2031 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2032 +tp2033 +bsg203 +g141 +(g142 +(I0 +tp2034 +g144 +tp2035 +Rp2036 +(I1 +(I16 +I1 +I1 +tp2037 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2038 +tp2039 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp2040 +g144 +tp2041 +Rp2042 +(I1 +(I16 +I1 +I1 +tp2043 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2044 +tp2045 +bsg218 +g226 +sg48 +(lp2046 +g0 +(g52 +g2 +Ntp2047 +Rp2048 +(dp2049 +g56 +Nsg58 +Nsg59 +Nsg46 +g231 +sbasg232 +g141 +(g142 +(I0 +tp2050 +g144 +tp2051 +Rp2052 +(I1 +(I16 +I1 +I1 +tp2053 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2054 +tp2055 +bsg239 +g240 +sg241 +I01 +sg242 +I01 +sg243 +(lp2056 +g420 +asg93 +I10055 +sg246 +I01 +sbaatp2057 +Rp2058 +sg303 +I00 +sg304 +Nsbaa(lp2059 +g424 +ag0 +(g425 +g2 +Ntp2060 +Rp2061 +(dp2062 +g17 +g1774 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g429 +sg46 +g134 +sg48 +Nsg430 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp2063 +(lp2064 +g154 +ag0 +(g155 +g2 +Ntp2065 +Rp2066 +(dp2067 +g159 +I01 +sg160 +(lp2068 +g0 +(g162 +g2 +Ntp2069 +Rp2070 +(dp2071 +g166 +g141 +(g142 +(I0 +tp2072 +g144 +tp2073 +Rp2074 +(I1 +(I1 +tp2075 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2076 +tp2077 +bsg178 +Nsg23 +g446 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp2078 +Rp2079 +(dp2080 +g166 +g141 +(g142 +(I0 +tp2081 +g144 +tp2082 +Rp2083 +(I1 +(I17 +tp2084 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p2085 +tp2086 +bsg178 +Nsg23 +g456 +sg180 +I1 +sg181 +I16 +sbasg192 +g457 +sg194 +(lp2087 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp2088 +g144 +tp2089 +Rp2090 +(I1 +(I16 +I1 +I1 +tp2091 +g38 +I00 +S'O\xf9F\x96\xbe\xecJ@\x0c\xd2O\xe3\xd3RU@A\xea\x9e\xc1ZCe@\x0c\xfb\x0b\xbf?gA@\xccc\x18\x8f\xdf\x08\x04@&\xc9\x0e\xc4\x8e\xd70@\xbc\x9d\x0c\x1f\xa3\xe1\x11@_\xb5Z\xd8!\x1c\xea?\xe2\xdf\x06u@\x9c\xba?\xa4\xf7\xe5\xb11\xc8\xcd?y\x1cr\x92eo\xb8?\x07\xe93\xe7\x8a+\xe5?\x11\x7f]_\xeb\x17K@.\xff-\x00\xce{\xa7@\x94\xfc\xfd\xca#]\xb8@T\xf6\x11\x85\xec\xea\xaa@' +p2092 +tp2093 +bsg203 +g141 +(g142 +(I0 +tp2094 +g144 +tp2095 +Rp2096 +(I1 +(I16 +I1 +I1 +tp2097 +g38 +I00 +S'\xd0YwZ\xb1H@?\xec\xfb\xbc\x14\xf6\xddC?&\x0c"\xc4\xd72H?\xb58\x06Y\x9a\x835?\xd9\x1d\x18\xe6\x89_%?\xf6uJ\xc0N\x9c0?\x0c\xf08\xf9\xd3Z&? hU\xbaD\x80\x1d?\xd6`gQ@\xce\xde\\\xa1K\xe7U@,\xbe\x8f\x96\xb3\xee^@\x8d\xfe\xecZ\x05\xfcK@Z[\xb7@S\x06.@\xb8t\xf4\x87ZwC@\xf2\x9b\xbb\xf2\xc3\x0e4@\x13\xb1\xe5c>#!@\x81\xe5\xec\xbf*w\x08@p\xfc\x17\x14mM\x12@\x9a\xf8\x00G\xaaq\x07@\xca\xa1\x7f\xda\xeb\xdc\x1e@\x85\xc6\xd3mZuQ@\xd6>\xd99\x01A\x80@\xf1\x12\xdd\r\xd1i\x87@\x85\x02\xdaf\xd5f\x81@' +p2114 +tp2115 +bsg239 +g491 +sg241 +I01 +sg242 +I01 +sg243 +(lp2116 +g493 +asg93 +I10058 +sg246 +I01 +sbaa(lp2117 +g495 +ag0 +(g155 +g2 +Ntp2118 +Rp2119 +(dp2120 +g159 +I01 +sg160 +(lp2121 +g0 +(g162 +g2 +Ntp2122 +Rp2123 +(dp2124 +g166 +g141 +(g142 +(I0 +tp2125 +g144 +tp2126 +Rp2127 +(I1 +(I1 +tp2128 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2129 +tp2130 +bsg178 +Nsg23 +g509 +sg180 +I256 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp2131 +Rp2132 +(dp2133 +g166 +g141 +(g142 +(I0 +tp2134 +g144 +tp2135 +Rp2136 +(I1 +(I17 +tp2137 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p2138 +tp2139 +bsg178 +Nsg23 +g519 +sg180 +I16 +sg181 +I16 +sbag0 +(g162 +g2 +Ntp2140 +Rp2141 +(dp2142 +g166 +g141 +(g142 +(I0 +tp2143 +g144 +tp2144 +Rp2145 +(I1 +(I17 +tp2146 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p2147 +tp2148 +bsg178 +Nsg23 +g529 +sg180 +I1 +sg181 +I16 +sbasg192 +g530 +sg194 +(lp2149 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp2150 +g144 +tp2151 +Rp2152 +(I1 +(I256 +I1 +I1 +tp2153 +g38 +I00 +S"E\xd3\xd9\x80\xe5,u@u\xb9\xac\xb5\xbcA#@\x14\xe0\xf3.[\xc1\xf8?\xc6\xa1)\x85A\x9cU?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf5\x08\xa8\x06W\xd0)@O\xffx\xb7\xc2\x00g@\x90ZK\xa8\xb0B$@\xd6\xdb\x9d\xf8\x1c&\x84?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00N\xb0\xbd\x1ee\xd7\x14@\xa2\x92\x0b\xed\x1b\x123@S=3/-\rp@\t\x84\x0f\xb8\xbd;\xe8?\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00H\xc7:=\xb4\x8d\xc1?\x86\x1dz_\x99\xd6\xdb?\xf7\xeb\xc0\xcc\x86\xd7!@OQ\x8dHh\xec5@\xb9u\x1dD\x90\x9e\x89?\xeaH\xb9\xa8\x8b\xd5\xfc>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcd\xc9\t^f\xb4c?P\xd8+\x0f>\xcb\x83?\xb6\xa0\n\xcf\xf1\x10\xc3?| \xd0\xe7\x8c\xe9\xea?\xa3\xd1y\xa2f\xae\xd8?m\x12\x82\xe4\xc4/q?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdf\xed\xe0\xb9\x95k\x89?\x89\x11t\x82\xde\xa5\x8f?5\x1a\xbf\x7f\x1a\xbf\xd7??\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Q7\xa8s\xc0\xcb7?[T\xe2\xf6_\xf9t?\xf1\xa6\xe0\x8a2}\xa3?\xd9\x13\x83L\xe2o\xc3?\xe4\xb6\xdf\xdd\xaf\xe2\xa3?Ky\xee{\x9b \xeb?kqXo\xd3\xd5\xdf?e\x89<=\xfe\xa8 ?\xe3A:\xdc\x11\xc5\x19>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_\xcb\xb1\xc7\x8b\xd6\x0f?\x94jc\x99\xf3M0?\xd1K\xb5\xe4+`v?\xb1@\xbe\xfb\x18\xb0\x92?^5\x08O>?t?\xb8!\xe9\xc3\x91\x88\xb2?\xbf\x90\x15\x80&I\xb7?y\x13\xd3A\xf2\xe0\x9f?\x80YY\xe0\x84)\x0e?\xc5\x16\x8f\xfdv\xda\xad>\x96\xd6&\xe8\x0b.\x01>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe1l\x99\x98\xde\xa1\xe0>\xb3F6A\x9fB\x01?\x83\xe2\x96:\x80\xf1@?\xa1\x17\x94\xc8\xca\xdf`?\x19\t4\xb32\xfc@?\x8f\xf0DgU\xdf\x7f?r!\t\x159\xd8|?u\x15u\x1f\xa5vp?!n\x7f\xcc]\xbbS?\x9d\xa3<\x90H\x1d\x05?O\xd73F\xdbXx>N\xcea\xe3\xa7\x9d\x04>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05yM1\x86w\xf2>\x92\x8a\xb9B\x1c\x06\x13?8\x95\xad\xfbl@R?Va\xc0E\xf8\xedl?\r\xf4\xe9eV\x9eP?5/^\xa7e\xa8\x90?P\xa4J\xee\x9a\x12\x88?~\xbe\xc3s\n\x80z?\x80`\xaa\xe1\xaf\xc5V?20\n\xbd\xe0\x85p?\x16\xcc\xccO\xe0K\x00?x7\x189\xaew\x9d>\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^`\xaf\xe0\x19\x95\xdd>)\xd4Hz\xf9\xde\xfd>\xfd\x1b\xa8\x9ba\xad5?!\xe2\xf14\xea\xefV?\x18\x18[\x03\xb9\x969?a\x01Nc\x820x?\xa9P\xd1\xa0>\x0cp?\xe5\xbf\x02?\xc3G_?U\xe0\xaa\x82\xff\x939?\xc4\xeb\x16\xa4\t\xf2T?\x10\x97{\rqOO?\xb3\xb4\x9cIp*\xff>\xbc\xbd\xd7\xd9\xdf|\xeb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x92\xaev$\x80\n?k\xaf*\x16\x96\xf3)?*\xc3\x982\x80\x90]?H\xc5\xc0\xb9\r\n\x81?\xaef\xbd\xdaALa?\xbf\x12\xf0\xf5:\x8c\xa1?\xec\xaf!\xaf<\x85\x97?d\xd7\xa70w\xac\x80?\x03\x0b\xfd\x9f\x05\x99[?\xe9\xcfTIQ`v?f\xa4\xb7\xb0\x90\xefi?M\x8f'Dg\xb2\x92?>Cz9\x8c\x03\xf8>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x92e\x84a\x07hW?\x00\xbf\xc2\xeb\xba|j?\xa7\xfbu\xfa\xcc\x18\xac?\x11\xc7\xfeg\xc9\x12\xcb?\xec\x86\xder\xd6\x1f\xad?-\xf6\xdd\x8d\xfa\x9d\xec?\xd3\x7fT\x0e\x9fX\xe3?\x92G\xf6\x13\x15\xbb\xc6?\x86\xe4\x12v2y\x9c?\n\xee\xf9\xec\x088\xb3?\xacC$\xf9\x00\x13\xa3?v\xa6\x98\xcf.I\xd5?\x95?\x97\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xf4j\xa4O\xa9N?Fq\xb3\xdc\xb7\xf1^?\xed=\xb6\xe1\x87\xb5\x91?\x81SH\x10/J\xab?\xad\xb7+\xc6\x89G\x8b?za\xe9\xc7\x98\xd7\xc9?\xf9\xb9\xfdP\xf2l\xc1?\xa9u\xbc\xf48\xcd\xa4?\xec\xa3\xf4\t7Yz?\xabhZHZO\x90?T\xfd\xac\xecY\xd4~?\x87\\\xb5#\xff\t\xaf?\xd0\xfe\xa0+\x9a]4@\xd8\x10\xef\xcc\xd2\xad\xa6@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0w\xbfh\x18\xc00>\x8d5\x8eg\xff\x9b1>q3\x1f\x9d$ Y>dA\xdc\xf2\xdc\xfdt>d\xd1\x8c\x80\xec\xa7V>\x92\xa5\xb9\x819t\x8e>\x17x\x1dRM\x87\x85>&\xda\xafn\x85\xffg>\xf2\x05_\x15\x82\xb5N>1\xcc\xf2\x18\xcd!\\>\x11\x08\xce\xdf\\1G>8\xcb6Fc\x93r>\xbe\x88\xcb#\xd7\xc3\xf2>\xd5J\xa56\x01\xd7R@\xa4\x91\x9a9O\xc6\x9c@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00M\xcea\xe3\xa7\x9d\xf4=\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xdb=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbc\xbd\xd7\xd9\xdf|\xeb=O\xcea\xe3\xa7\x9d\x14>\xcfQ\xb8eZwP?\x04\xe0\xf1\xbe\xc9A9@\x8fM\x9b\xb5\x80\xeeG@" +p2154 +tp2155 +bsg203 +g141 +(g142 +(I0 +tp2156 +g144 +tp2157 +Rp2158 +(I1 +(I256 +I1 +I1 +tp2159 +g38 +I00 +S'x,\xbe\xf1\x80\xd6V?\xca\xe1\xa8y&d/?V\xa0~\xab\x80\xa3 ?\xf5r,5\x00\x0f\xf5>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbd\x0f\xd3t\x1e?0?\xd9\x14\x7fR\xb4\x8aP?\xf7\xf0W\x89\x02E1?{\x9dT\xf9b\x8d\x03?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88G\x87\xddiK%?=\xda_\x1a\x14\xe62?\x14\xed7L\xb5\x1eQ?\x9d(\x00\xaf\x8bx\x1c?\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xf9.\xb5\xbd\xf2\r?\x8c^\xc8\xc5.}\x17?\n\x950w\xde\x16\'?z\xb9As\xa6\xc59?\x85\xf0\xfa(\xd7\xbd\x03?\x14\xe6\xa9\xb0\xd1/\xe2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^b\xd6\xdfGX\xfc>\xe77I\x058\x84\xfe>\xd4\x8f\xd4X\x04\xa7\x0f?\xdb\xe1\x90c\xe2\xe7\x1b?\xc2.\xeb\xe6\x1e\xfb\x1f?\xfc\x07d\x10b\xb9\xfc>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\xe5\xf2e\xcf\xfc\x05?\x05\x00e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xcb\x9d\xd9[C\xec>\x97s}\xdd\x9c\xfe\xfd>|7\xf4\xf5Cv\x0b?\xb9\x04k\xb8\xd6\xb2\x0f?\xda\x1f\xab>\xebl\x07?\xf6U\t\x07I\x8a\x1a?\xa4\x87\x0c\xa8\xf1\x89\x1d?\xca\xb8\xf2:R\xa9\xea>B\x8a\xfd\xfe\xb2\x82\x9a>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x15\xdf\n\xd7q\xe2>^\xf6T\x13l\x84\xea>\xa3\x9b\xda\x8c\x94;\xfd>\x93`SV\x83,\x04?\xda\xb1\xff@]v\xfa>\xeb\xa86o6\xfc\r?\xff\x1c\xfe\x15\x95\xf6\x10?\x8d\x8d\x84||z\n?;\xfe\xea\x87\xac?\xe5>\x93\x11\xbf,\x91\x17\xcd>\xf8\xeb\xed\x06ZK\x90>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\xe3?\x8ed\x08\xd8>7\xdc7\xc2\xf2\xb8\xe0>3\x15\x89A\xbe\x0f\xf1>\xd7\x16>h\x95\xb8\xf9>t^65\x07\x90\xf1>\xd1\xc8\x9f\x8c\xbe\x03\x00?H\x92\xe2*\xb62\xfd>\xcb\xde\x19\x13>\xc4\xfd>\xea\xd69c\xfb\x15\xf9>\xaa\x1e\x05\xd0L\x1a\xe0>\xd7\xa0\xd0|B\xf8\xba>\x95\x00\xa1\'\x87\xbe\x91>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16t\xc6\xad\xe7\xd5\xde>,\xe3\x980;_\xe1>\x98\x19\xef$\xb0\xc8\xf1>\x1a\x07X\x08\x1f\x03\xf9>\x08\xc2\xf4\x83^:\xf5>\xe5!\xb4\xdc\xa1\x0e\x01?W\x18\xa2;\\\x11\x04?c`]\xe7\\V\xff>\x81UF\x14\xa0\x0c\xf4>\x87\xf2+\xce\xbe\xf9\xfd>\x7fW\x15^\x196\xe1>\xa3\x8c\xf9o\x98:\xc6>\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8by\xee\x06\x89\x8a\xd8>\xf2\xd0\xb3m\x8f\x1f\xe2>\xcfmbF\x03\t\xeb>\x0eK;\xf75Q\xf4>mlO\xc9(\x90\xee>\xe0C.\x8f\xadA\x00?\xdcs\xf1\xe1_w\xfe>\x12\xb69X.\xf4\xf5>f\x98\x10w\xf4\x06\xf0>\x97\xff\xc0\x8a\xf6\xd0\xf5>\xc1V;\xfe\x96N\xf4>\xfav\xfav=\xec\xde>\x8bq\xc3\xb8\xb1\xf8\x84>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\xaf\x18\xce\x1c\xd3\xe1>J\xf6\x8418\x80\xec>\x82\xc9\xe8\xd2~\x13\xf8>P\x8c\xbaZ@;\x01?a\xd7\xeb\xd5"\xf1\xf6>|\xb57\x80\xda>\x0b?Nr\xde\xb6\x14/\x03?\x9b\xc3\xdf\xcf\xe6\x01\x02?z\xf4\x7f\x12\xf2\x83\xf6>b>\x8b`wh\xf8>\xa6\xfbZ\xfb\x7fk\xf9>\x1e\\\xbd\xba#q\x06?\xf0\xf2Y=\xa0v\xe2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x06{c\xc1\x98\xf8>\xbc\xeb\xce\xd6\x19\\\xf7>\t\xa5,m(\xc1\x0b?0y<\xd5\x98\x17\x12?2\xf6\xf7%\x8eS\x0c?\xb8\x9aM\xbeo\x90\x1c?\xe4\xc2\xf1\xcar|\x16?\xee\xb5S\xd6N\x85\x11?\x9f\x9e\xa6U-\xe2\x06?\xba\xae\x8a\xc1J\xa4\x0e?\xb9\x82\x9a\xf9\x1b\xa6\x07?5i\xae\xfa\xa2\xa5\x15?d\x0cq\x9e\xd8\xa72?$\x00X\xbfZ;\xc1>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86M1\xc8\xa1?\xf2>3/h\x03\xd03\xf7>\x15\x8c\xfa\x85Q\xc4\x04?\xd7\xa94\xc1\xf8\x18\x0c?-\'\xe34\x8b\xd2\x00?\x19\x12\xfa\xc1\xe2\x98\x11?\xdc\rR0\x02\xd9\x0e?\xb3\x97\xaf|q{\x07?\x89\xf7\x07\xb6LI\xfe>\x97\x1e\x05[\xea\xb7\x03?r\xceY\x9d\xde\xed\x00?}\x84/\xc2\x95\xe0\t?l#Y\xb7][%?J8\xb2\xc4\xf6\xb7N?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf10\x95\xf8\xd6\xf3\xa3>z\xeb\xb6i\x1c\xa5\xa4>\xa9Nw\xaa\x19<\xb2>\xb7&t*\x91K\xbd>\x0c\r\xc7\xae\xf3\x16\xb2>\xcd\x94=\xfd!3\xc4>\x9a\xb2m\xbf\xf3\xe4\xc1>\xf2\x19\xe8H\x98]\xb3>\xc6\xb7B\xb1\x91\x16\xb0>\xb6\xee\xc1\xe5\xc5\xe1\xb3>\xf1\x8c\xa0:\xdco\xab>}\x11\x8c\\\x8c\xa4\xba>S\xdam\xbes\x01\xdc>\x92\xfcV\xa3\x9e\xfd\x17?r.\x1e\xf6\xd2\xb3L?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x8f0F~\xd0\x89\x89>\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8bq\xc3\xb8\xb1\xf8\x84>\x85\x97\x03\x10l.\x98>\x9e\x98\xc6\xa3*\x04\xf5>\xae@b\'JI\'?\xa8a\xbf\x96\x1cb:?' +p2160 +tp2161 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp2162 +g144 +tp2163 +Rp2164 +(I1 +(I256 +I1 +I1 +tp2165 +g38 +I00 +S'\x81\xe9\xda\x04\x05\x0b\xff?\x81\xda\xd1t\xc5\xee\xd4?\xf0\xeaB\x993\xc8\xc0?\xc7\xfc\x18\xc2\x93Ro?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x97\xcc&\x0fm<\xd8?\x80\xc6r8\xe0\xe0\xf6?$\xd4\x0c\xa9\xa2x\xd5?Z\xba3\xb1\x84f\x85?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbd\xaa\xdc\x80\x1e\xcc\xce?\xb6\xf2\x1a\x1d\xccu\xdd?\x81A\x83\xeb\x15\x07\xfb?\xa1\x15z9;{\xb7?\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87\x1e\xcf\xf2\xed\xfb\xa3?\xd6\xe3\\N\xba\xcb\xb1?\xe6\x08\xb7@3&\xd4?\xb5F\xdb\xbc"\x96\xdf?\x90\tm\x88S"\x88?\xf7>B\xba\xc5\xe9A?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\xac`\x90C&u?\x17d@E77\x85?\x9b\x18\xa5^\xca\xd3\xa4?r\x15\xc4@\xd7\xbe\xb8?\xf6/6\x9aI\xc1\xb0?}cD\xf1\x8c\xf2{?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc1\xa79y\x91\t\x88?\x12\xe7\xe1\x04\xa6\xd3\x8a?n/\xde\xde\x97o\xb0?\xf6\x1c/h\xd2D\xc1?\xc9"M\xbc\x03<\xb5?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\xb7\xe7[[\xc7J?J\xa0\xae\xdb\x8d+[?\x0e-\xdb\xc3\xad\xe4\x7f?e#\xea\x18j\'\x8d?r\xaa-\x13\tW~?\xa8\x8a\x93\x99\x96\t\x9d?:\xa3qY#F\xa0?\xac\xc8]\xd3\xe5\t\x93?\xd5\xb7D\xcc\xb0\x02J?\xb7\x8e5\xd4\xc6\x9c\x18?\xbay\x1f\x96/\xa4\xa2>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00k\x19Z;\x15!3?)\xe7O\xcc\x18\xaaC?u|\xb48c\x98c?\x9d\x92\xd5\xe9\x8f\x92s?\x18\xb9\x94\xe0\xfa\x9dc?h\xbb\xa4\xa6\xac\x08\x83?]\x06\'S\xa3\x1b\x82?/\xeb\'\xd8\xceY{?\x8e\x00\x1fZ\xef\xe8m?\x0eK<\xa0l\xcaE?\xff\xc6\xe7\xd9]>\xfd>\x12\x92\xf2\x80\x9f^\xa6>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3$a}\xc7\xa1\xfd\x18\x11?\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s^\xd8\xe9i\xfc1?\x9d\xcce\x90\xa8=B?\xcd\x93\xf6\xb7\xa2X_?\x90RX\x0b(#p?^\x9fL\xb6\x94\x06a?\xaf\x1c\x96U:\x94\x80?\x80w\xa3-r\x00{?\xa0\x0c\xf3\xa9\x14\xd9r?\xd15W~\xb7\x04a?\xb7\x02\xe1\xce6\xd5n?\xd5R\xa2a\x80\xa6j?\x8e\\\xd5\x1d<\xb1B?\xc3\xc2\x98V\x7f\xd3\x8d>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf2lS\xedqjH?5\x87~\x80\xc85X?@\xfb\xf3\xa9\xb2Qr?\xa4\x148\x8aJ\xae\x83?\x9f\xf1j\xa6h\xd2s?5I\xca\xa1\xf6\xf9\x93?r\xd9\xfbg\xe0Z\x90?\xc6n\xee\x11\xa6w\x83?NF\xf7\xe8\\\xb3q?\xd4\x92R\x811\xe6\x7f?$=\x1fx\x8fFx?\xae0\xa3E\xa3(\x8d?\xf5 fk\xccM@?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\xaft>\xb0\xfc\xe3[\xe3\xe4\xcc>r\xaa\xc5k\x0f\x19\xea>fGkn\xc1\xa1\xf9>\xbf\xec\xaew0\x00\xe8>T=\xa9\xba\xf8y\x07?\x14\xa7}\x11\xf8t\x03?+m2\x0c\x94c\xf4>:Hr\x97\x88h\xe2>\x8bpzf\xab\x07\xeb>\x88\x8a[\xa3\xa9O\xe0>\xcbO\tu~w\xf8>k\x0c\xafs5\xee\x00\x00\x00\x00\x00\x00\x00\x00\x12\x92\xf2\x80\x9f^\x96>\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3}>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc3\xc2\x98V\x7f\xd3\x8d>\x12\x92\xf2\x80\x9f^\xb6>\x87_\xc4Q\xccTk?\xb1\xff\x89\xf3\xac\xf3\xe0?\xbc\xa1e,\xfcU\xe7?' +p2166 +tp2167 +bsg218 +g552 +sg48 +(lp2168 +g0 +(g52 +g2 +Ntp2169 +Rp2170 +(dp2171 +g56 +Nsg58 +Nsg59 +Nsg46 +g557 +sbasg232 +g141 +(g142 +(I0 +tp2172 +g144 +tp2173 +Rp2174 +(I1 +(I256 +I1 +I1 +tp2175 +g38 +I00 +S'/\xeci\x87\xbf\xd3e@F\x1bG\xac\xc5o=@a\x1a\x86\x8f\x88\x99\'@\xbc\x91y\xe4\x0f\x06\xd6?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdaG\xa7\xae|\nA@\x92\xb3\xb0\xa7\x1d\x16`@R\n\xba\xbd\xa41>@\x0f\xbe0\x99*\x18\xee?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r(\x9br\x85\xa75@\xa8\xf2v\x84\xd3\xb6D@\x0fJ\x98i\xfb\x00c@5\xd7i\xa4\xa5\x82 @\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xeeBs\x9dF\x1a\x0c@e\xa02\xfe}\x06\x19@\x83d\x01\x13\xb8U<@\xb7-\xcal\x905F@\xb9\xaa\xec\xbb"\xf8\xf0?\x8c(\xed\r\xbe0\xa9?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xf2\x07\x03\xcf\xbd\xdd?\xc0\x8cb\xb9\xa5\xd5\xed?\x9a*\x18\x95\xd4I\r@\x14\xdf\x89Y/f!@r3\xdc\x80\xcf\x8f\x17@\xf4\x15\xa4\x19\x8b\xa6\xe3?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf4\x89\xa9\xf6\xe9x\xd44@\xb0\x11\x88\xd7\xf5\x0b\xca?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xba\x88\xef\xc4\xac\x17\xc7?I\x02\xd4\xd4\xb2\xb5\xe5?\x989]\x16\x13\x9b\xfd?\xa4\xed_Yi\x92\r@*\x00\xc63h\xe8\xfd?\xf2\x98\x81\xca\xf8w!@P\xdf2\xa7\xcb\xc2\x1a@\xe7\xa4\xf7\x8d\xaf=\xbb?b2U0*\xa9#?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbf\xec\x9e<,\xd4\xb2?\xb4\xc8v\xbe\x9f\x1a\xc3?\xae\x1b\xb6-\xcal\xe6?\xe3\xa0\x84\x99\xb6\x7f\xf4?\xd8\x1b|a2U\xe5?~\xbd\xfb\xe3\xbdj\x04@\x8a\xcd\xc7\xb5\xa1\xe2\x06@2\xe2;1\xeb\xc5\xfa?BQ\xa0O\xe4I\xb2?Y\xa85\xcd;N\x81?-C\x1c\xeb\xe26\n?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbf\xb3v\xdb\x85\xe6\x9a?\x12]P\xdf2\xa7\xab?\x04\xcf\xbd\x87K\x8e\xcb?-V\xd4`\x1a\x86\xdb?J$\xd1\xcb(\x96\xcb?\x8a\xa7W\xca2\xc4\xea?\xf3\xe0\xee\xac\xddv\xe9?]\x11\xfco%;\xe3?d\xcc]K\xc8\x07\xd5?\x8c\xc9T\xc1\xa8\xa4\xae?\xeb\xf76\xfd\xd9\x8fd?i\x1dUM\x10u\x0f?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfbM(D\xc0!\xa4?\xea>\x00\xa9M\x9c\xb4?\xe4tYLl>\xd4?\xf4\x1f\xd2o_\x07\xe2?V\xa85\xcd;N\xd3?\xb2<\x0f\xee\xceZ\xf3?\x88$z\x19\xc5r\xf0?\xbak\t\xf9\xa0g\xe8?wb\xd6\x8b\xa1\x9c\xd6?N\xd1\x91\\\xfeC\xe3?c\x97\xa8\xde\x1a\xd8\xaa?\xd3\xb8p $\x0bx?\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd2D\xd8\xf0\xf4J\x99?\xbd\'\x0f\x0b\xb5\xa6\xa9?\xec_YiR\n\xc6?\x1a4\xf4Op\xb1\xd6?\x1c\xc0[ A\xf1\xc7?V\x18[\x08rP\xe7?\x06\xf0\x16HP\xfc\xe2?\xc1\xc9\xfd\x0eE\x81\xda?\xae\xa3\xaa\t\xa2\xee\xc7?\xe95v\x89\xea\xad\xd5?>"\xa6D\x12\xbd\xd2?\'\n\xf4\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\xa8\xde\x1a\xd8*\xb1?\x11\xf7X\xfa\xd0\x05\xc1?R\x19\xff>\xe3\xc2\xd9?\x06\xdd^\xd2\x18\xad\xeb?\xc7c\x06*\xe3\xdf\xdb?\xf3v\x84\xd3\x82\x17\xfc?\xc8):\x92\xcb\xff\xf6?\xc6K7\x89A`\xeb?\xdd\xba\x9b\xa7:\xe4\xd8?=\x0f\xee\xce\xdam\xe6?\xfd\xf6u\xe0\x9c\x11\xe1?:\xbe\xf6\xcc\x92\x80\xf4?Y\x9e\x07wg\xed\xa6?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x17\xd4\xb7\xcc\xe9\xd6?8J^\x9dc@\xe1?/>\x05\xc0x\xc6\x01@\xa41ZGUs\x11@H\xf0\xbf\x95\xec\x18\x02@q_\x07\xce\x19\xf1!@mB!\x02\x0e\x81\x1d@\xb7\x02CV\xb7\xfa\x0f@Y\xc0\x04n\xddM\xf9?\xed\xd3\xf1\x98\x81\xca\x04@\xed\xd3\xf1\x98\x81J\xfd?n\x86\x1b\xf0\xf9\xe1\x15@\xef=\\r\xdc\xc9B@\x1b\x8cJ\xea\x044q?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x93\x82n/i\x8c\xd2?\xad\xf4\xa1\x0b\xea[\xda?\x89\xc4=\x96>\xf4\xf3?\xbf\xf1\xb5g\x96\x84\x01@\xfb\'\xb8XQ\x83\xf1?]\x94\xd9 \x93\x0c\x11@\x8c;\xa5\x83\xf5\xff\x0b@\xd4/\xd8\r\xdb\x96\xfe?\xd8\xeb\xdd\x1f\xefU\xe8?\xbb?\xde\xabV&\xf3?Q\x88\x80C\xa8R\xea?\xab\x8b\xdbh\x00\xaf\x02@`@\xf6z\xf7gE@\x00\xf2^\xb52\xf2\x7f@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xacM\x9c\xdc\xefP4?\xacM\x9c\xdc\xefP4?\xd8\xfb\xc6\xd7\x9eYR?4n\xa3\x01\xbc\x05b?v\xfe&\x14"\xe0P?\x1f\xff>\xe3\xc2\x81p?\xf4\xb2\x98\xd8|\\k?\x84\xe9&1\x08\xac\\?\x91\xb5\xf8\x14\x00\xe3I?"\x17\x0e\x84d\x01S?\xcf\xba\xb8\x8d\x06\xf0F?\x1b\x8cJ\xea\x044a?\xbb\x14W\x95}W\xa4?\r\x1a\xfa\'\xb8\x96T@M\x9c\xdc\xef\xd0qy@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00j\x1dUM\x10u\xff>\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xe4>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1h\xe3\x88\xb5\xf8\xf4>i\x1dUM\x10u\x1f?+\x13~\xa9\x9f7\xd3?\x91\x0fz6\xab\xd6G@\xb8u7OuhP@' +p2176 +tp2177 +bsg239 +g564 +sg241 +I01 +sg242 +I01 +sg243 +(lp2178 +g566 +asg93 +I10059 +sg246 +I01 +sbaatp2179 +Rp2180 +sg303 +I00 +sg304 +Nsbaa(lp2181 +g570 +ag0 +(g571 +g2 +Ntp2182 +Rp2183 +(dp2184 +g17 +g1774 +sg129 +I00 +sg130 +g131 +sg132 +Nsg133 +g570 +sg46 +g134 +sg48 +Nsg135 +g138 +sg150 +Nsg151 +g7 +((lp2185 +(lp2186 +g577 +ag0 +(g155 +g2 +Ntp2187 +Rp2188 +(dp2189 +g159 +I01 +sg160 +(lp2190 +g0 +(g162 +g2 +Ntp2191 +Rp2192 +(dp2193 +g166 +g141 +(g142 +(I0 +tp2194 +g144 +tp2195 +Rp2196 +(I1 +(I1 +tp2197 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2198 +tp2199 +bsg178 +Nsg23 +g591 +sg180 +I1 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp2200 +Rp2201 +(dp2202 +g166 +g141 +(g142 +(I0 +tp2203 +g144 +tp2204 +Rp2205 +(I1 +(I2 +tp2206 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2207 +tp2208 +bsg178 +Nsg23 +g601 +sg180 +I1 +sg181 +I1 +sbasg192 +g602 +sg194 +(lp2209 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp2210 +g144 +tp2211 +Rp2212 +(I1 +(I1 +I1 +I1 +tp2213 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2214 +tp2215 +bsg203 +g141 +(g142 +(I0 +tp2216 +g144 +tp2217 +Rp2218 +(I1 +(I1 +I1 +I1 +tp2219 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2220 +tp2221 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp2222 +g144 +tp2223 +Rp2224 +(I1 +(I1 +I1 +I1 +tp2225 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2226 +tp2227 +bsg218 +g624 +sg48 +(lp2228 +g0 +(g52 +g2 +Ntp2229 +Rp2230 +(dp2231 +g56 +Nsg58 +Nsg59 +Nsg46 +g629 +sbasg232 +g141 +(g142 +(I0 +tp2232 +g144 +tp2233 +Rp2234 +(I1 +(I1 +I1 +I1 +tp2235 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2236 +tp2237 +bsg239 +g636 +sg241 +I01 +sg242 +I01 +sg243 +(lp2238 +g638 +asg93 +I10062 +sg246 +I01 +sbaa(lp2239 +g640 +ag0 +(g155 +g2 +Ntp2240 +Rp2241 +(dp2242 +g159 +I01 +sg160 +(lp2243 +g0 +(g162 +g2 +Ntp2244 +Rp2245 +(dp2246 +g166 +g141 +(g142 +(I0 +tp2247 +g144 +tp2248 +Rp2249 +(I1 +(I1 +tp2250 +g173 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2251 +tp2252 +bsg178 +Nsg23 +g654 +sg180 +I16 +sg181 +I1 +sbag0 +(g162 +g2 +Ntp2253 +Rp2254 +(dp2255 +g166 +g141 +(g142 +(I0 +tp2256 +g144 +tp2257 +Rp2258 +(I1 +(I17 +tp2259 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00+i\xa4)+\x1b`>\xeed\xc6\x94u#o>\xb3z\xea\x05]\xca\x82>\xb3z\xea\x05]\xca\x92>_\x19eG\xf4|\x97>\xf1h\xe3\x88\xb5\xf8\xa4>=zh\xc4q\x85\xac>\xaf\xdd\\M\xb5N\xb0>\xbe\xaf>\xdc\xdd\x1c\xb1>a\x9bsA\x94g\xb2>\xfc\x9d7_6K\xb3>kN\xb9\x1du\xcf\xb5>\x8d\xed\xb5\xa0\xf7\xc6\xd0>\xd8\x9eY\x12\xa0\xa6v?\x12\x83\xc0\xca\xa1E\xea?\x00\x00\x00\x00\x00\x004@' +p2260 +tp2261 +bsg178 +Nsg23 +g664 +sg180 +I1 +sg181 +I16 +sbasg192 +g665 +sg194 +(lp2262 +sg129 +I00 +sg196 +g141 +(g142 +(I0 +tp2263 +g144 +tp2264 +Rp2265 +(I1 +(I16 +I1 +I1 +tp2266 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2267 +tp2268 +bsg203 +g141 +(g142 +(I0 +tp2269 +g144 +tp2270 +Rp2271 +(I1 +(I16 +I1 +I1 +tp2272 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2273 +tp2274 +bsg46 +g210 +sg211 +g141 +(g142 +(I0 +tp2275 +g144 +tp2276 +Rp2277 +(I1 +(I16 +I1 +I1 +tp2278 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2279 +tp2280 +bsg218 +g687 +sg48 +(lp2281 +g0 +(g52 +g2 +Ntp2282 +Rp2283 +(dp2284 +g56 +Nsg58 +Nsg59 +Nsg46 +g692 +sbasg232 +g141 +(g142 +(I0 +tp2285 +g144 +tp2286 +Rp2287 +(I1 +(I16 +I1 +I1 +tp2288 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +p2289 +tp2290 +bsg239 +g699 +sg241 +I01 +sg242 +I01 +sg243 +(lp2291 +g701 +asg93 +I10063 +sg246 +I01 +sbaatp2292 +Rp2293 +sg303 +I00 +sg304 +Nsbaatp2294 +Rp2295 +aatp2296 +Rp2297 +sg135 +g138 +sg192 +Vstatepoint.100.h5 +p2298 +sS'_openmc_geometry' +p2299 +g0 +(copenmc.geometry +Geometry +p2300 +g2 +Ntp2301 +Rp2302 +(dp2303 +g128 +(dp2304 +sS'_root_universe' +p2305 +g0 +(copenmc.universe +Universe +p2306 +g2 +Ntp2307 +Rp2308 +(dp2309 +S'_cells' +p2310 +g7 +((lp2311 +(lp2312 +I10004 +ag0 +(g18 +g2 +Ntp2313 +Rp2314 +(dp2315 +g22 +Nsg23 +S'fill' +p2316 +sg25 +Nsg26 +g0 +(g2306 +g2 +Ntp2317 +Rp2318 +(dp2319 +g2310 +g7 +((lp2320 +(lp2321 +I10000 +ag20 +aa(lp2322 +I10001 +ag713 +aa(lp2323 +I10002 +ag1235 +aa(lp2324 +I10003 +ag1774 +aatp2325 +Rp2326 +sS'_num_regions' +p2327 +I0 +sg93 +I10000 +sS'_cell_offsets' +p2328 +g7 +((lp2329 +tp2330 +Rp2331 +sg46 +g134 +sbsg94 +Nsg46 +Vroot +p2332 +sg96 +g0 +(g740 +g2 +Ntp2333 +Rp2334 +(dp2335 +g744 +(lp2336 +g0 +(g97 +g2 +Ntp2337 +Rp2338 +(dp2339 +g101 +g0 +(copenmc.surface +XPlane +p2340 +g2 +Ntp2341 +Rp2342 +(dp2343 +g23 +S'x-plane' +p2344 +sg107 +(dp2345 +S'A' +p2346 +F1.0 +sS'C' +p2347 +F0.0 +sS'B' +p2348 +F0.0 +sg113 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4\xbf' +p2349 +tp2350 +Rp2351 +sS'D' +p2352 +F0.0 +ssg46 +Vmin x +p2353 +sg122 +Vreflective +p2354 +sg93 +I10003 +sg124 +(lp2355 +g113 +asbsg126 +g749 +sbag0 +(g97 +g2 +Ntp2356 +Rp2357 +(dp2358 +g101 +g0 +(g2340 +g2 +Ntp2359 +Rp2360 +(dp2361 +g23 +g2344 +sg107 +(dp2362 +g2346 +F1.0 +sg2347 +F0.0 +sg2348 +F0.0 +sg113 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4?' +p2363 +tp2364 +Rp2365 +sg2352 +F0.0 +ssg46 +Vmax x +p2366 +sg122 +Vreflective +p2367 +sg93 +I10004 +sg124 +(lp2368 +g113 +asbsg126 +g127 +sbag0 +(g97 +g2 +Ntp2369 +Rp2370 +(dp2371 +g101 +g0 +(copenmc.surface +YPlane +p2372 +g2 +Ntp2373 +Rp2374 +(dp2375 +g23 +S'y-plane' +p2376 +sg107 +(dp2377 +g2346 +F1.0 +sg109 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4\xbf' +p2378 +tp2379 +Rp2380 +sg2347 +F0.0 +sg2348 +F0.0 +sg2352 +F0.0 +ssg46 +Vmin y +p2381 +sg122 +Vreflective +p2382 +sg93 +I10005 +sg124 +(lp2383 +g109 +asbsg126 +g749 +sbag0 +(g97 +g2 +Ntp2384 +Rp2385 +(dp2386 +g101 +g0 +(g2372 +g2 +Ntp2387 +Rp2388 +(dp2389 +g23 +g2376 +sg107 +(dp2390 +g2346 +F1.0 +sg109 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4?' +p2391 +tp2392 +Rp2393 +sg2347 +F0.0 +sg2348 +F0.0 +sg2352 +F0.0 +ssg46 +Vmax y +p2394 +sg122 +Vreflective +p2395 +sg93 +I10006 +sg124 +(lp2396 +g109 +asbsg126 +g127 +sbag0 +(g97 +g2 +Ntp2397 +Rp2398 +(dp2399 +g101 +g0 +(copenmc.surface +ZPlane +p2400 +g2 +Ntp2401 +Rp2402 +(dp2403 +g23 +S'z-plane' +p2404 +sg107 +(dp2405 +g2346 +F1.0 +sg2347 +F0.0 +sg2348 +F0.0 +sS'z0' +p2406 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4\xbf' +p2407 +tp2408 +Rp2409 +sg2352 +F0.0 +ssg46 +Vmin z +p2410 +sg122 +Vreflective +p2411 +sg93 +I10007 +sg124 +(lp2412 +g2406 +asbsg126 +g749 +sbag0 +(g97 +g2 +Ntp2413 +Rp2414 +(dp2415 +g101 +g0 +(g2400 +g2 +Ntp2416 +Rp2417 +(dp2418 +g23 +g2404 +sg107 +(dp2419 +g2346 +F1.0 +sg2347 +F0.0 +sg2348 +F0.0 +sg2406 +g34 +(g38 +S'\x0e\x15\xe3\xfcM(\xe4?' +p2420 +tp2421 +Rp2422 +sg2352 +F0.0 +ssg46 +Vmax z +p2423 +sg122 +Vreflective +p2424 +sg93 +I10008 +sg124 +(lp2425 +g2406 +asbsg126 +g127 +sbasbsg128 +Nsg93 +I10004 +sbaatp2426 +Rp2427 +sg2327 +I0 +sg93 +I0 +sg2328 +g7 +((lp2428 +tp2429 +Rp2430 +sg46 +g134 +sbsbsg129 +I00 +sS'_mgxs_types' +p2431 +(lp2432 +g12 +ag306 +ag424 +ag570 +asg130 +g131 +sg132 +Nsg46 +g134 +sS'_domains' +p2433 +S'all' +p2434 +sS'_opencg_geometry' +p2435 +Nsg430 +NsS'_keff' +p2436 +g34 +(g38 +S'\x7f\xf6\x86\xeaN\xc9\xf2?' +p2437 +tp2438 +Rp2439 +sg303 +I00 +sb. \ No newline at end of file diff --git a/sample-input/sph-factors/pin-cell/run-openmc.py b/sample-input/sph-factors/pin-cell/run-openmc.py new file mode 100644 index 000000000..301112861 --- /dev/null +++ b/sample-input/sph-factors/pin-cell/run-openmc.py @@ -0,0 +1,176 @@ +import openmc +import openmc.mgxs + +############################################################################### +# Simulation Input File Parameters +############################################################################### + +# OpenMC simulation parameters +batches = 100 +inactive = 10 +particles = 100000 + + +############################################################################### +# Exporting to OpenMC materials.xml File +############################################################################### + +# Instantiate some Nuclides +h1 = openmc.Nuclide('H-1') +he4 = openmc.Nuclide('He-4') +b10 = openmc.Nuclide('B-10') +b11 = openmc.Nuclide('B-11') +o16 = openmc.Nuclide('O-16') +fe56 = openmc.Nuclide('Fe-56') +zr90 = openmc.Nuclide('Zr-90') +u235 = openmc.Nuclide('U-235') +u238 = openmc.Nuclide('U-238') + +# Instantiate some Materials and register the appropriate Nuclides +uo2 = openmc.Material(name='UO2 Fuel') +uo2.set_density('g/cm3', 10.29769) +uo2.add_nuclide(u235, 5.5815e-4) +uo2.add_nuclide(u238, 2.2408e-2) +uo2.add_nuclide(o16, 4.5829e-2) + +helium = openmc.Material(name='Helium') +helium.set_density('g/cm3', 0.001598) +helium.add_nuclide(he4, 2.4044e-4) + +zircaloy = openmc.Material(name='Zircaloy 4') +zircaloy.set_density('g/cm3', 6.55) +zircaloy.add_nuclide(o16, 3.0743e-4) +zircaloy.add_nuclide(fe56, 1.3610e-4) +zircaloy.add_nuclide(zr90, 2.1827e-2) + +borated_water = openmc.Material(name='Borated Water') +borated_water.set_density('g/cm3', 0.740582) +borated_water.add_nuclide(b10, 8.0042e-6) +borated_water.add_nuclide(b11, 3.2218e-5) +borated_water.add_nuclide(h1, 4.9457e-2) +borated_water.add_nuclide(o16, 2.4672e-2) +borated_water.add_s_alpha_beta('HH2O', '71t') + +# Instantiate a MaterialsFile, register all Materials, and export to XML +materials_file = openmc.MaterialsFile() +materials_file.default_xs = '71c' +materials_file.add_materials([uo2, helium, zircaloy, borated_water]) +materials_file.make_isotropic_in_lab() +materials_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC geometry.xml File +############################################################################### + +# Instantiate ZCylinder surfaces +fuel_or = openmc.ZCylinder(x0=0, y0=0, R=0.39218, name='Fuel OR') +clad_ir = openmc.ZCylinder(x0=0, y0=0, R=0.40005, name='Clad IR') +clad_or = openmc.ZCylinder(x0=0, y0=0, R=0.45720, name='Clad OR') +min_x = openmc.XPlane(x0=-0.62992, name='min x') +max_x = openmc.XPlane(x0=+0.62992, name='max x') +min_y = openmc.YPlane(y0=-0.62992, name='min y') +max_y = openmc.YPlane(y0=+0.62992, name='max y') +min_z = openmc.ZPlane(z0=-0.62992, name='min z') +max_z = openmc.ZPlane(z0=+0.62992, name='max z') + +min_x.boundary_type = 'reflective' +max_x.boundary_type = 'reflective' +min_y.boundary_type = 'reflective' +max_y.boundary_type = 'reflective' +min_z.boundary_type = 'reflective' +max_z.boundary_type = 'reflective' + +# Instantiate Cells +fuel = openmc.Cell(name='fuel') +gap = openmc.Cell(name='gap') +clad = openmc.Cell(name='clad') +water = openmc.Cell(name='water') +root_cell = openmc.Cell(name='root') + +# Use surface half-spaces to define regions +fuel.region = -fuel_or +gap.region = +fuel_or & -clad_ir +clad.region = +clad_ir & -clad_or +water.region = +clad_or +root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z + +# Instantiate Universe +pin = openmc.Universe(name='pin cell universe') +root_univ = openmc.Universe(universe_id=0, name='root universe') + +# Register fills with Cells +fuel.fill = uo2 +gap.fill = helium +clad.fill = zircaloy +water.fill = borated_water +root_cell.fill = pin + +# Register Cells with Universe +pin.add_cells([fuel, gap, clad, water]) +root_univ.add_cell(root_cell) + +# Instantiate a Geometry and register the root Universe +geometry = openmc.Geometry() +geometry.root_universe = root_univ + +# Instantiate a GeometryFile, register Geometry, and export to XML +geometry_file = openmc.GeometryFile() +geometry_file.geometry = geometry +geometry_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC settings.xml File +############################################################################### + +# Construct uniform initial source distribution over fissionable zones +lower_left = [-0.62992, -0.62992, -0.62992] +upper_right = [+0.62992, +0.62992, +0.62992] +source = openmc.source.Source(space=openmc.stats.Box(lower_left, upper_right)) +source.only_fissionable = True + +# Instantiate a SettingsFile +settings_file = openmc.SettingsFile() +settings_file.batches = batches +settings_file.inactive = inactive +settings_file.particles = particles +settings_file.output = {'tallies': False, 'summary': True} +settings_file.source = source +settings_file.sourcepoint_write = False + +# Export to "settings.xml" +settings_file.export_to_xml() + + +############################################################################### +# Create OpenMC MGXS Library +############################################################################### + +# Instantiate a 16-group EnergyGroups object +groups = openmc.mgxs.EnergyGroups() +groups.group_edges = [0., 0.03e-6, 0.058e-6, 0.14e-6, 0.28e-6, 0.35e-6, + 0.625e-6, 0.85e-6, 0.972e-6, 1.02e-6, 1.097e-6, + 1.15e-6, 1.3e-6, 4.e-6, 5.53e-3, 821.e-3, 20.] + +# Initialize an MGXS Library for OpenMOC +mgxs_lib = openmc.mgxs.Library(geometry) +mgxs_lib.energy_groups = groups +mgxs_lib.mgxs_types = ['total', 'nu-fission', 'nu-scatter matrix', 'chi'] +mgxs_lib.domain_type = 'cell' +mgxs_lib.correction = None +mgxs_lib.build_library() + +# Create a "tallies.xml" file for the MGXS Library +tallies_file = openmc.TalliesFile() +mgxs_lib.add_to_tallies_file(tallies_file, merge=True) +tallies_file.export_to_xml() + + +############################################################################### +# Run OpenMC Simulation +############################################################################### + +# Run OpenMC +executor = openmc.Executor() +executor.run_simulation(output=True, mpi_procs=4) diff --git a/sample-input/sph-factors/pin-cell/sph-factors.py b/sample-input/sph-factors/pin-cell/sph-factors.py new file mode 100644 index 000000000..5c66170cf --- /dev/null +++ b/sample-input/sph-factors/pin-cell/sph-factors.py @@ -0,0 +1,206 @@ +import openmoc +import openmc.mgxs + +import numpy as np +import matplotlib + +# Enable Matplotib to work for headless nodes +matplotlib.use('Agg') +import matplotlib.pyplot as plt +plt.ioff() + + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Eigenvalue Calculation w/o SPH Factors +############################################################################### + +# Initialize 2-group OpenMC multi-group cross section library for a pin cell +mgxs_lib = openmc.mgxs.Library.load_from_file(filename='mgxs', directory='.') + +# Create an OpenMOC Geometry from the OpenCG Geometry +openmoc_geometry = \ + openmoc.opencg_compatible.get_openmoc_geometry(mgxs_lib.opencg_geometry) + +# Load cross section data +openmoc_materials = \ + openmoc.materialize.load_openmc_mgxs_lib(mgxs_lib, openmoc_geometry) + +# Initialize an OpenMOC TrackGenerator and Solver +track_generator = openmoc.TrackGenerator(openmoc_geometry, opts.num_azim, + opts.track_spacing) +track_generator.generateTracks() + +# Initialize an OpenMOC Solver +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) + +# Run an eigenvalue calulation with the MGXS from OpenMC +solver.computeEigenvalue() +solver.printTimerReport() +keff_no_sph = solver.getKeff() + +# Extract the OpenMOC scalar fluxes +fluxes_no_sph = openmoc.process.get_scalar_fluxes(solver) + + +############################################################################### +# Eigenvalue Calculation with SPH Factors +############################################################################### + +# Compute SPH factors +sph, sph_mgxs_lib, sph_indices = \ + openmoc.materialize.compute_sph_factors(mgxs_lib, + track_spacing=opts.track_spacing, + num_azim=opts.num_azim, + num_threads=opts.num_omp_threads) + +# Load the SPH-corrected MGXS library data +materials = \ + openmoc.materialize.load_openmc_mgxs_lib(sph_mgxs_lib, openmoc_geometry) + +# Run an eigenvalue calculation with the SPH-corrected modified MGXS library +solver.computeEigenvalue() +solver.printTimerReport() +keff_with_sph = solver.getKeff() + +# Report the OpenMC and OpenMOC eigenvalues +openmoc.log.py_printf('RESULT', 'OpenMOC keff w/o SPH: \t%1.5f', keff_no_sph) +openmoc.log.py_printf('RESULT', 'OpenMOC keff w/ SPH: \t%1.5f', keff_with_sph) +openmoc.log.py_printf('RESULT', 'OpenMC keff: \t\t1.17574 +/- 0.00086') + + +############################################################################### +# Extracting Scalar Fluxes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +# Plot the cells +openmoc.plotter.plot_cells(openmoc_geometry) + +# Extract the OpenMOC scalar fluxes +fluxes_sph = openmoc.process.get_scalar_fluxes(solver) +fluxes_sph *= sph + +# Extract the OpenMC scalar fluxes +num_fsrs = openmoc_geometry.getNumFSRs() +num_groups = openmoc_geometry.getNumEnergyGroups() +openmc_fluxes = np.zeros((num_fsrs, num_groups), dtype=np.float64) + +# Get the OpenMC flux in each FSR +for fsr in range(num_fsrs): + + # Find the OpenMOC cell and volume for this FSR + openmoc_cell = openmoc_geometry.findCellContainingFSR(fsr) + cell_id = openmoc_cell.getId() + fsr_volume = track_generator.getFSRVolume(fsr) + + # Store the volume-averaged flux + mgxs = mgxs_lib.get_mgxs(cell_id, 'nu-fission') + flux = mgxs.tallies['flux'].mean.flatten() + flux = np.flipud(flux) / fsr_volume + openmc_fluxes[fsr, :] = flux + +# Extract energy group edges +group_edges = mgxs_lib.energy_groups.group_edges +group_edges *= 1e6 # Convert to units of eV +group_edges += 1e-5 # Adjust lower bound to 1e-3 eV (for loglog scaling) + +# Compute difference in energy bounds for each group +group_deltas = np.ediff1d(group_edges) +group_edges = np.flipud(group_edges) +group_deltas = np.flipud(group_deltas) + +# Normalize fluxes to the total integrated flux +openmc_fluxes /= np.sum(openmc_fluxes * group_deltas, axis=1)[:,np.newaxis] +fluxes_sph /= np.sum(fluxes_sph * group_deltas, axis=1)[:,np.newaxis] +fluxes_no_sph /= np.sum(fluxes_no_sph * group_deltas, axis=1)[:,np.newaxis] + + +############################################################################### +# Plot the OpenMC, OpenMOC Scalar Fluxes +############################################################################### + +# Extend the mgxs values array for matplotlib's step plot of fluxes +openmc_fluxes = np.insert(openmc_fluxes, 0, openmc_fluxes[:,0], axis=1) +fluxes_no_sph = np.insert(fluxes_no_sph, 0, fluxes_no_sph[:,0], axis=1) +fluxes_sph = np.insert(fluxes_sph, 0, fluxes_sph[:,0], axis=1) + +# Plot OpenMOC and OpenMC fluxes in each FSR +for fsr in range(num_fsrs): + + # Get the OpenMOC cell and material for this FSR + cell = openmoc_geometry.findCellContainingFSR(fsr) + material_name = cell.getFillMaterial().getName() + + # Create a step plot for the MGXS + fig = plt.figure() + plt.plot(group_edges, openmc_fluxes[fsr,:], + drawstyle='steps', color='r', linewidth=2) + plt.plot(group_edges, fluxes_no_sph[fsr,:], + drawstyle='steps', color='b', linewidth=2) + plt.plot(group_edges, fluxes_sph[fsr,:], + drawstyle='steps', color='g', linewidth=2) + + plt.yscale('log') + plt.xscale('log') + plt.xlabel('Energy [eV]') + plt.ylabel('Flux') + plt.title('Normalized Flux ({0})'.format(material_name)) + plt.xlim((min(group_edges), max(group_edges))) + plt.legend(['openmc', 'openmoc w/o sph', 'openmoc w/ sph'], loc='best') + plt.grid() + filename = 'plots/flux-{0}.png'.format(material_name.replace(' ', '-')) + plt.savefig(filename, bbox_inches='tight') + plt.close() + + +############################################################################### +# Plot OpenMC-to-OpenMOC Scalar Flux Errors +############################################################################### + +# Compute the percent relative error in the flux +rel_err_no_sph = np.zeros(openmc_fluxes.shape) +rel_err_sph = np.zeros(openmc_fluxes.shape) + +for fsr in range(num_fsrs): + delta_flux_no_sph = fluxes_no_sph[fsr,:] - openmc_fluxes[fsr,:] + delta_flux_sph = fluxes_sph[fsr,:] - openmc_fluxes[fsr,:] + rel_err_no_sph[fsr,:] = delta_flux_no_sph / openmc_fluxes[fsr,:] * 100. + rel_err_sph[fsr,:] = delta_flux_sph / openmc_fluxes[fsr,:] * 100. + +# Plot OpenMOC relative flux errors in each FSR +for fsr in range(num_fsrs): + + # Get the OpenMOC cell and material for this FSR + cell = openmoc_geometry.findCellContainingFSR(fsr) + material_name = cell.getFillMaterial().getName() + + + # Create a step plot for the MGXS + fig = plt.figure() + plt.plot(group_edges, rel_err_no_sph[fsr,:], + drawstyle='steps', color='r', linewidth=2) + plt.plot(group_edges, rel_err_sph[fsr,:], + drawstyle='steps', color='b', linewidth=2) + + plt.xscale('log') + plt.xlabel('Energy [eV]') + plt.ylabel('Relative Error [%]') + plt.title('OpenMOC-to-OpenMC Flux Rel. Err. ({0})'.format(material_name)) + plt.xlim((min(group_edges), max(group_edges))) + plt.legend(['openmoc w/o sph', 'openmoc w/ sph'], loc='best') + plt.grid() + filename = 'plots/rel-err-{0}.png'.format(material_name.replace(' ', '-')) + plt.savefig(filename, bbox_inches='tight') + plt.close() diff --git a/sample-input/sph-factors/slab/compute-mgxs.py b/sample-input/sph-factors/slab/compute-mgxs.py new file mode 100644 index 000000000..3b0d3b91d --- /dev/null +++ b/sample-input/sph-factors/slab/compute-mgxs.py @@ -0,0 +1,23 @@ +import openmc +import openmc.mgxs + +# Load the last statepoint file +sp = openmc.StatePoint('statepoint.100.h5') +su = openmc.Summary('summary.h5') +sp.link_with_summary(su) + +# Instantiate a 1-group EnergyGroups object +groups = openmc.mgxs.EnergyGroups() +groups.group_edges = [0., 20.] + +# Initialize an 2-group MGXS Library for OpenMOC +mgxs_lib = openmc.mgxs.Library(su.openmc_geometry) +mgxs_lib.energy_groups = groups +mgxs_lib.mgxs_types = ['total', 'nu-fission', 'nu-scatter matrix', 'chi'] +mgxs_lib.domain_type = 'cell' +mgxs_lib.correction = None +mgxs_lib.build_library() +mgxs_lib.load_from_statepoint(sp) + +# Store library and its MGXS objects in a pickled binary file +mgxs_lib.dump_to_file(filename='mgxs', directory='.') diff --git a/sample-input/sph-factors/slab/mgxs.pkl b/sample-input/sph-factors/slab/mgxs.pkl new file mode 100644 index 000000000..b4955146a --- /dev/null +++ b/sample-input/sph-factors/slab/mgxs.pkl @@ -0,0 +1,167806 @@ +ccopy_reg +_reconstructor +p0 +(copenmc.mgxs.library +Library +p1 +c__builtin__ +object +p2 +Ntp3 +Rp4 +(dp5 +S'_all_mgxs' +p6 +ccollections +OrderedDict +p7 +((lp8 +(lp9 +I10000 +ag7 +((lp10 +(lp11 +S'total' +p12 +ag0 +(copenmc.mgxs.mgxs +TotalXS +p13 +g2 +Ntp14 +Rp15 +(dp16 +S'_domain' +p17 +g0 +(copenmc.universe +Cell +p18 +g2 +Ntp19 +Rp20 +(dp21 +S'_translation' +p22 +NsS'_type' +p23 +S'normal' +p24 +sS'_rotation' +p25 +NsS'_fill' +p26 +g0 +(copenmc.material +Material +p27 +g2 +Ntp28 +Rp29 +(dp30 +S'_density_units' +p31 +S'atom/b-cm' +p32 +sS'_density' +p33 +cnumpy.core.multiarray +scalar +p34 +(cnumpy +dtype +p35 +(S'f8' +p36 +I0 +I1 +tp37 +Rp38 +(I3 +S'<' +p39 +NNNI-1 +I-1 +I0 +tp40 +bS'~\xc3\xc8\xbb\xb8\xc7\xa5?' +p41 +tp42 +Rp43 +sS'_sab' +p44 +(lp45 +sS'_name' +p46 +VCladding +p47 +sS'_nuclides' +p48 +g7 +((lp49 +(lp50 +VZr-90 +p51 +a(g0 +(copenmc.nuclide +Nuclide +p52 +g2 +Ntp53 +Rp54 +(dp55 +S'_xs' +p56 +V71c +p57 +sS'_scattering' +p58 +NsS'_zaid' +p59 +Nsg46 +g51 +sbg34 +(g38 +S'\x17G\xe5&ji\x96?' +p60 +tp61 +Rp62 +S'ao' +p63 +tp64 +aa(lp65 +VZr-91 +p66 +a(g0 +(g52 +g2 +Ntp67 +Rp68 +(dp69 +g56 +V71c +p70 +sg58 +Nsg59 +Nsg46 +g66 +sbg34 +(g38 +S'0\x1d\xe7\xf4\xc4\x8cs?' +p71 +tp72 +Rp73 +g63 +tp74 +aa(lp75 +VZr-92 +p76 +a(g0 +(g52 +g2 +Ntp77 +Rp78 +(dp79 +g56 +V71c +p80 +sg58 +Nsg59 +Nsg46 +g76 +sbg34 +(g38 +S'\xbb\xe5\xb8\x8d\xe5\xe1}?' +p81 +tp82 +Rp83 +g63 +tp84 +aa(lp85 +VZr-94 +p86 +a(g0 +(g52 +g2 +Ntp87 +Rp88 +(dp89 +g56 +V71c +p90 +sg58 +Nsg59 +Nsg46 +g86 +sbg34 +(g38 +S'\xa8{SG}H~?' +p91 +tp92 +Rp93 +g63 +tp94 +aa(lp95 +VZr-96 +p96 +a(g0 +(g52 +g2 +Ntp97 +Rp98 +(dp99 +g56 +V71c +p100 +sg58 +Nsg59 +Nsg46 +g96 +sbg34 +(g38 +S'\xfe\x03\xf6\xe2\xd5\x83S?' +p101 +tp102 +Rp103 +g63 +tp104 +aatp105 +Rp106 +sS'_elements' +p107 +g7 +((lp108 +tp109 +Rp110 +sS'_convert_to_distrib_comps' +p111 +I00 +sS'_distrib_otf_file' +p112 +NsS'_id' +p113 +I10001 +sbsS'_distribcell_index' +p114 +Nsg46 +Vclad +p115 +sS'_region' +p116 +g0 +(copenmc.region +Intersection +p117 +g2 +Ntp118 +Rp119 +(dp120 +S'_nodes' +p121 +(lp122 +g0 +(copenmc.surface +Halfspace +p123 +g2 +Ntp124 +Rp125 +(dp126 +S'_surface' +p127 +g0 +(copenmc.surface +XPlane +p128 +g2 +Ntp129 +Rp130 +(dp131 +g23 +S'x-plane' +p132 +sS'_coeffs' +p133 +(dp134 +S'A' +p135 +F1.0 +sS'C' +p136 +F0.0 +sS'B' +p137 +F0.0 +sS'x0' +p138 +g34 +(g38 +S'\xecQ\xb8\x1e\x85\xeb\x01@' +p139 +tp140 +Rp141 +sS'D' +p142 +F0.0 +ssg46 +V +p143 +sS'_boundary_type' +p144 +Vtransmission +p145 +sg113 +I3 +sS'_coeff_keys' +p146 +(lp147 +g138 +asbsS'_side' +p148 +S'-' +p149 +sbag0 +(g123 +g2 +Ntp150 +Rp151 +(dp152 +g127 +g0 +(g128 +g2 +Ntp153 +Rp154 +(dp155 +g23 +g132 +sg133 +(dp156 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xc3\xf5(\\\x8f\xc2\x01@' +p157 +tp158 +Rp159 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p160 +sg113 +I4 +sg146 +(lp161 +g138 +asbsg148 +S'+' +p162 +sbasbsS'_offsets' +p163 +Nsg113 +I10000 +sbsS'_sparse' +p164 +I00 +sS'_domain_type' +p165 +S'cell' +p166 +sS'_tally_trigger' +p167 +NsS'_rxn_type' +p168 +g12 +sg46 +S'' +p169 +sg48 +NsS'_energy_groups' +p170 +g0 +(copenmc.mgxs.groups +EnergyGroups +p171 +g2 +Ntp172 +Rp173 +(dp174 +S'_group_edges' +p175 +cnumpy.core.multiarray +_reconstruct +p176 +(cnumpy +ndarray +p177 +(I0 +tp178 +S'b' +p179 +tp180 +Rp181 +(I1 +(I2 +tp182 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p183 +tp184 +bsbsS'_xs_tally' +p185 +NsS'_tallies' +p186 +g7 +((lp187 +(lp188 +S'flux' +p189 +ag0 +(copenmc.tallies +Tally +p190 +g2 +Ntp191 +Rp192 +(dp193 +S'_derived' +p194 +I01 +sS'_filters' +p195 +(lp196 +g0 +(copenmc.filter +Filter +p197 +g2 +Ntp198 +Rp199 +(dp200 +S'_bins' +p201 +g176 +(g177 +(I0 +tp202 +g179 +tp203 +Rp204 +(I1 +(I1 +tp205 +g35 +(S'i8' +p206 +I0 +I1 +tp207 +Rp208 +(I3 +S'<' +p209 +NNNI-1 +I-1 +I0 +tp210 +bI00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p211 +tp212 +bsS'_mesh' +p213 +Nsg23 +Vcell +p214 +sS'_stride' +p215 +I1 +sS'_num_bins' +p216 +I1 +sbag0 +(g197 +g2 +Ntp217 +Rp218 +(dp219 +g201 +g176 +(g177 +(I0 +tp220 +g179 +tp221 +Rp222 +(I1 +(I2 +tp223 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p224 +tp225 +bsg213 +Nsg23 +Venergy +p226 +sg215 +I1 +sg216 +I1 +sbasS'_sp_filename' +p227 +Vstatepoint.100.h5 +p228 +sS'_triggers' +p229 +(lp230 +sg164 +I00 +sS'_sum_sq' +p231 +g176 +(g177 +(I0 +tp232 +g179 +tp233 +Rp234 +(I1 +(I1 +I1 +I1 +tp235 +g38 +I00 +S'(\x03\x9bba\x03\x0e@' +p236 +tp237 +bsS'_std_dev' +p238 +g176 +(g177 +(I0 +tp239 +g179 +tp240 +Rp241 +(I1 +(I1 +I1 +I1 +tp242 +g38 +I00 +S"9'|\xc3\xa6\xdf+?" +p243 +tp244 +bsg46 +g143 +sS'_mean' +p245 +g176 +(g177 +(I0 +tp246 +g179 +tp247 +Rp248 +(I1 +(I1 +I1 +I1 +tp249 +g38 +I00 +S'\xefp\xcd\x8d\xe3!\xca?' +p250 +tp251 +bsS'_num_realizations' +p252 +g34 +(g35 +(S'i4' +p253 +I0 +I1 +tp254 +Rp255 +(I3 +S'<' +p256 +NNNI-1 +I-1 +I0 +tp257 +bS'Z\x00\x00\x00' +p258 +tp259 +Rp260 +sg48 +(lp261 +g0 +(g52 +g2 +Ntp262 +Rp263 +(dp264 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p265 +sbasS'_sum' +p266 +g176 +(g177 +(I0 +tp267 +g179 +tp268 +Rp269 +(I1 +(I1 +I1 +I1 +tp270 +g38 +I00 +S'hs\xb4\xff\xd3_2@' +p271 +tp272 +bsS'_estimator' +p273 +Vtracklength +p274 +sS'_with_batch_statistics' +p275 +I00 +sS'_results_read' +p276 +I01 +sS'_scores' +p277 +(lp278 +Vflux +p279 +asg113 +I10002 +sS'_with_summary' +p280 +I01 +sbaa(lp281 +g12 +ag0 +(g190 +g2 +Ntp282 +Rp283 +(dp284 +g194 +I01 +sg195 +(lp285 +g0 +(g197 +g2 +Ntp286 +Rp287 +(dp288 +g201 +g176 +(g177 +(I0 +tp289 +g179 +tp290 +Rp291 +(I1 +(I1 +tp292 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p293 +tp294 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp295 +Rp296 +(dp297 +g201 +g176 +(g177 +(I0 +tp298 +g179 +tp299 +Rp300 +(I1 +(I2 +tp301 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p302 +tp303 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp304 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp305 +g179 +tp306 +Rp307 +(I1 +(I1 +I1 +I1 +tp308 +g38 +I00 +S'\x88*\x0b\x84b\xe8\xd6?' +p309 +tp310 +bsg238 +g176 +(g177 +(I0 +tp311 +g179 +tp312 +Rp313 +(I1 +(I1 +I1 +I1 +tp314 +g38 +I00 +S'\xb1/\xa8V\xe7\x93\x11?' +p315 +tp316 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp317 +g179 +tp318 +Rp319 +(I1 +(I1 +I1 +I1 +tp320 +g38 +I00 +S'\x9c\n\xa5r\xbd$\xb0?' +p321 +tp322 +bsg252 +g260 +sg48 +(lp323 +g0 +(g52 +g2 +Ntp324 +Rp325 +(dp326 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp327 +g179 +tp328 +Rp329 +(I1 +(I1 +I1 +I1 +tp330 +g38 +I00 +S'\xec\x168i\xaa\xb3\x16@' +p331 +tp332 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp333 +Vtotal +p334 +asg113 +I10003 +sg280 +I01 +sbaatp335 +Rp336 +sS'_by_nuclide' +p337 +I00 +sS'_rxn_rate_tally' +p338 +Nsbaa(lp339 +S'nu-fission' +p340 +ag0 +(copenmc.mgxs.mgxs +NuFissionXS +p341 +g2 +Ntp342 +Rp343 +(dp344 +g17 +g20 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +S'nu-fission' +p345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp346 +(lp347 +g189 +ag0 +(g190 +g2 +Ntp348 +Rp349 +(dp350 +g194 +I01 +sg195 +(lp351 +g0 +(g197 +g2 +Ntp352 +Rp353 +(dp354 +g201 +g176 +(g177 +(I0 +tp355 +g179 +tp356 +Rp357 +(I1 +(I1 +tp358 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p359 +tp360 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp361 +Rp362 +(dp363 +g201 +g176 +(g177 +(I0 +tp364 +g179 +tp365 +Rp366 +(I1 +(I2 +tp367 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p368 +tp369 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp370 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp371 +g179 +tp372 +Rp373 +(I1 +(I1 +I1 +I1 +tp374 +g38 +I00 +S'(\x03\x9bba\x03\x0e@' +p375 +tp376 +bsg238 +g176 +(g177 +(I0 +tp377 +g179 +tp378 +Rp379 +(I1 +(I1 +I1 +I1 +tp380 +g38 +I00 +S"9'|\xc3\xa6\xdf+?" +p381 +tp382 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp383 +g179 +tp384 +Rp385 +(I1 +(I1 +I1 +I1 +tp386 +g38 +I00 +S'\xefp\xcd\x8d\xe3!\xca?' +p387 +tp388 +bsg252 +g260 +sg48 +(lp389 +g0 +(g52 +g2 +Ntp390 +Rp391 +(dp392 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp393 +g179 +tp394 +Rp395 +(I1 +(I1 +I1 +I1 +tp396 +g38 +I00 +S'hs\xb4\xff\xd3_2@' +p397 +tp398 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp399 +g279 +asg113 +I10006 +sg280 +I01 +sbaa(lp400 +S'nu-fission' +p401 +ag0 +(g190 +g2 +Ntp402 +Rp403 +(dp404 +g194 +I01 +sg195 +(lp405 +g0 +(g197 +g2 +Ntp406 +Rp407 +(dp408 +g201 +g176 +(g177 +(I0 +tp409 +g179 +tp410 +Rp411 +(I1 +(I1 +tp412 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p413 +tp414 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp415 +Rp416 +(dp417 +g201 +g176 +(g177 +(I0 +tp418 +g179 +tp419 +Rp420 +(I1 +(I2 +tp421 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p422 +tp423 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp424 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp425 +g179 +tp426 +Rp427 +(I1 +(I1 +I1 +I1 +tp428 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p429 +tp430 +bsg238 +g176 +(g177 +(I0 +tp431 +g179 +tp432 +Rp433 +(I1 +(I1 +I1 +I1 +tp434 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p435 +tp436 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp437 +g179 +tp438 +Rp439 +(I1 +(I1 +I1 +I1 +tp440 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p441 +tp442 +bsg252 +g260 +sg48 +(lp443 +g0 +(g52 +g2 +Ntp444 +Rp445 +(dp446 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp447 +g179 +tp448 +Rp449 +(I1 +(I1 +I1 +I1 +tp450 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p451 +tp452 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp453 +Vnu-fission +p454 +asg113 +I10007 +sg280 +I01 +sbaatp455 +Rp456 +sg337 +I00 +sg338 +Nsbaa(lp457 +S'nu-scatter matrix' +p458 +ag0 +(copenmc.mgxs.mgxs +NuScatterMatrixXS +p459 +g2 +Ntp460 +Rp461 +(dp462 +g17 +g20 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +S'nu-scatter matrix' +p463 +sg46 +g169 +sg48 +NsS'_correction' +p464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp465 +(lp466 +g189 +ag0 +(g190 +g2 +Ntp467 +Rp468 +(dp469 +g194 +I01 +sg195 +(lp470 +g0 +(g197 +g2 +Ntp471 +Rp472 +(dp473 +g201 +g176 +(g177 +(I0 +tp474 +g179 +tp475 +Rp476 +(I1 +(I1 +tp477 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p478 +tp479 +bsg213 +Nsg23 +Vcell +p480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp481 +Rp482 +(dp483 +g201 +g176 +(g177 +(I0 +tp484 +g179 +tp485 +Rp486 +(I1 +(I2 +tp487 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p488 +tp489 +bsg213 +Nsg23 +Venergy +p490 +sg215 +I1 +sg216 +I1 +sbasg227 +Vstatepoint.100.h5 +p491 +sg229 +(lp492 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp493 +g179 +tp494 +Rp495 +(I1 +(I1 +I1 +I1 +tp496 +g38 +I00 +S'o\xad\xc0\x90\xc0G\x0e@' +p497 +tp498 +bsg238 +g176 +(g177 +(I0 +tp499 +g179 +tp500 +Rp501 +(I1 +(I1 +I1 +I1 +tp502 +g38 +I00 +S'\x95\xf1`\xbd\xe9\x9eM?' +p503 +tp504 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp505 +g179 +tp506 +Rp507 +(I1 +(I1 +I1 +I1 +tp508 +g38 +I00 +S'\xech\xed\xa8\x19:\xca?' +p509 +tp510 +bsg252 +g34 +(g255 +S'Z\x00\x00\x00' +p511 +tp512 +Rp513 +sg48 +(lp514 +g0 +(g52 +g2 +Ntp515 +Rp516 +(dp517 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p518 +sbasg266 +g176 +(g177 +(I0 +tp519 +g179 +tp520 +Rp521 +(I1 +(I1 +I1 +I1 +tp522 +g38 +I00 +S'\xc6\xed\xc6\n\xdap2@' +p523 +tp524 +bsg273 +Vanalog +p525 +sg275 +I00 +sg276 +I01 +sg277 +(lp526 +Vflux +p527 +asg113 +I10010 +sg280 +I01 +sbaa(lp528 +S'scatter' +p529 +ag0 +(g190 +g2 +Ntp530 +Rp531 +(dp532 +g194 +I01 +sg195 +(lp533 +g0 +(g197 +g2 +Ntp534 +Rp535 +(dp536 +g201 +g176 +(g177 +(I0 +tp537 +g179 +tp538 +Rp539 +(I1 +(I1 +tp540 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p541 +tp542 +bsg213 +Nsg23 +Vcell +p543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp544 +Rp545 +(dp546 +g201 +g176 +(g177 +(I0 +tp547 +g179 +tp548 +Rp549 +(I1 +(I2 +tp550 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p551 +tp552 +bsg213 +Nsg23 +Venergy +p553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp554 +Rp555 +(dp556 +g201 +g176 +(g177 +(I0 +tp557 +g179 +tp558 +Rp559 +(I1 +(I2 +tp560 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p561 +tp562 +bsg213 +Nsg23 +Venergyout +p563 +sg215 +I1 +sg216 +I1 +sbasg227 +Vstatepoint.100.h5 +p564 +sg229 +(lp565 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp566 +g179 +tp567 +Rp568 +(I1 +(I1 +I1 +I1 +tp569 +g38 +I00 +S'q\xb6\x88A\xc3\xcf\xd6?' +p570 +tp571 +bsg238 +g176 +(g177 +(I0 +tp572 +g179 +tp573 +Rp574 +(I1 +(I1 +I1 +I1 +tp575 +g38 +I00 +S'i\xc2\x18\x99;\x922?' +p576 +tp577 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp578 +g179 +tp579 +Rp580 +(I1 +(I1 +I1 +I1 +tp581 +g38 +I00 +S'n\x9f\xa4"\x8a\x18\xb0?' +p582 +tp583 +bsg252 +g34 +(g255 +S'Z\x00\x00\x00' +p584 +tp585 +Rp586 +sg48 +(lp587 +g0 +(g52 +g2 +Ntp588 +Rp589 +(dp590 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p591 +sbasg266 +g176 +(g177 +(I0 +tp592 +g179 +tp593 +Rp594 +(I1 +(I1 +I1 +I1 +tp595 +g38 +I00 +S'2\x80\xb7@\x82\xa2\x16@' +p596 +tp597 +bsg273 +Vanalog +p598 +sg275 +I00 +sg276 +I01 +sg277 +(lp599 +Vnu-scatter +p600 +asg113 +I10011 +sg280 +I01 +sbaatp601 +Rp602 +sg337 +I00 +sg338 +Nsbaa(lp603 +S'chi' +p604 +ag0 +(copenmc.mgxs.mgxs +Chi +p605 +g2 +Ntp606 +Rp607 +(dp608 +g17 +g20 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp609 +(lp610 +S'nu-fission-in' +p611 +ag0 +(g190 +g2 +Ntp612 +Rp613 +(dp614 +g194 +I01 +sg195 +(lp615 +g0 +(g197 +g2 +Ntp616 +Rp617 +(dp618 +g201 +g176 +(g177 +(I0 +tp619 +g179 +tp620 +Rp621 +(I1 +(I1 +tp622 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p623 +tp624 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp625 +Rp626 +(dp627 +g201 +g176 +(g177 +(I0 +tp628 +g179 +tp629 +Rp630 +(I1 +(I2 +tp631 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p632 +tp633 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp634 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp635 +g179 +tp636 +Rp637 +(I1 +(I1 +I1 +I1 +tp638 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p639 +tp640 +bsg238 +g176 +(g177 +(I0 +tp641 +g179 +tp642 +Rp643 +(I1 +(I1 +I1 +I1 +tp644 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p645 +tp646 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp647 +g179 +tp648 +Rp649 +(I1 +(I1 +I1 +I1 +tp650 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p651 +tp652 +bsg252 +g513 +sg48 +(lp653 +g0 +(g52 +g2 +Ntp654 +Rp655 +(dp656 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp657 +g179 +tp658 +Rp659 +(I1 +(I1 +I1 +I1 +tp660 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p661 +tp662 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp663 +Vnu-fission +p664 +asg113 +I10014 +sg280 +I01 +sbaa(lp665 +S'nu-fission-out' +p666 +ag0 +(g190 +g2 +Ntp667 +Rp668 +(dp669 +g194 +I01 +sg195 +(lp670 +g0 +(g197 +g2 +Ntp671 +Rp672 +(dp673 +g201 +g176 +(g177 +(I0 +tp674 +g179 +tp675 +Rp676 +(I1 +(I1 +tp677 +g208 +I00 +S"\x10'\x00\x00\x00\x00\x00\x00" +p678 +tp679 +bsg213 +Nsg23 +Vcell +p680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp681 +Rp682 +(dp683 +g201 +g176 +(g177 +(I0 +tp684 +g179 +tp685 +Rp686 +(I1 +(I2 +tp687 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p688 +tp689 +bsg213 +Nsg23 +Venergyout +p690 +sg215 +I1 +sg216 +I1 +sbasg227 +Vstatepoint.100.h5 +p691 +sg229 +(lp692 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp693 +g179 +tp694 +Rp695 +(I1 +(I1 +I1 +I1 +tp696 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p697 +tp698 +bsg238 +g176 +(g177 +(I0 +tp699 +g179 +tp700 +Rp701 +(I1 +(I1 +I1 +I1 +tp702 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p703 +tp704 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp705 +g179 +tp706 +Rp707 +(I1 +(I1 +I1 +I1 +tp708 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p709 +tp710 +bsg252 +g34 +(g255 +S'Z\x00\x00\x00' +p711 +tp712 +Rp713 +sg48 +(lp714 +g0 +(g52 +g2 +Ntp715 +Rp716 +(dp717 +g56 +Nsg58 +Nsg59 +Nsg46 +Vtotal +p718 +sbasg266 +g176 +(g177 +(I0 +tp719 +g179 +tp720 +Rp721 +(I1 +(I1 +I1 +I1 +tp722 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p723 +tp724 +bsg273 +Vanalog +p725 +sg275 +I00 +sg276 +I01 +sg277 +(lp726 +Vnu-fission +p727 +asg113 +I10015 +sg280 +I01 +sbaatp728 +Rp729 +sg337 +I00 +sg338 +Nsbaatp730 +Rp731 +aa(lp732 +I10001 +ag7 +((lp733 +(lp734 +g12 +ag0 +(g13 +g2 +Ntp735 +Rp736 +(dp737 +g17 +g0 +(g18 +g2 +Ntp738 +Rp739 +(dp740 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p741 +sg116 +g0 +(g117 +g2 +Ntp742 +Rp743 +(dp744 +g121 +(lp745 +g0 +(g123 +g2 +Ntp746 +Rp747 +(dp748 +g127 +g0 +(g128 +g2 +Ntp749 +Rp750 +(dp751 +g23 +g132 +sg133 +(dp752 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\x02@' +p753 +tp754 +Rp755 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p756 +sg113 +I5 +sg146 +(lp757 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp758 +Rp759 +(dp760 +g127 +g0 +(g128 +g2 +Ntp761 +Rp762 +(dp763 +g23 +g132 +sg133 +(dp764 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'=\n\xd7\xa3p=\x02@' +p765 +tp766 +Rp767 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p768 +sg113 +I6 +sg146 +(lp769 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10001 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp770 +(lp771 +g189 +ag0 +(g190 +g2 +Ntp772 +Rp773 +(dp774 +g194 +I01 +sg195 +(lp775 +g0 +(g197 +g2 +Ntp776 +Rp777 +(dp778 +g201 +g176 +(g177 +(I0 +tp779 +g179 +tp780 +Rp781 +(I1 +(I1 +tp782 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p783 +tp784 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp785 +Rp786 +(dp787 +g201 +g176 +(g177 +(I0 +tp788 +g179 +tp789 +Rp790 +(I1 +(I2 +tp791 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p792 +tp793 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp794 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp795 +g179 +tp796 +Rp797 +(I1 +(I1 +I1 +I1 +tp798 +g38 +I00 +S'\x88\x08/T\xb2\xae\r@' +p799 +tp800 +bsg238 +g176 +(g177 +(I0 +tp801 +g179 +tp802 +Rp803 +(I1 +(I1 +I1 +I1 +tp804 +g38 +I00 +S'v\xae5\x1e\x11B+?' +p805 +tp806 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp807 +g179 +tp808 +Rp809 +(I1 +(I1 +I1 +I1 +tp810 +g38 +I00 +S'\x9c\x02x/\xee\xfc\xc9?' +p811 +tp812 +bsg252 +g260 +sg48 +(lp813 +g0 +(g52 +g2 +Ntp814 +Rp815 +(dp816 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp817 +g179 +tp818 +Rp819 +(I1 +(I1 +I1 +I1 +tp820 +g38 +I00 +S'\xd6a`y\xd7E2@' +p821 +tp822 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp823 +g279 +asg113 +I10018 +sg280 +I01 +sbaa(lp824 +g12 +ag0 +(g190 +g2 +Ntp825 +Rp826 +(dp827 +g194 +I01 +sg195 +(lp828 +g0 +(g197 +g2 +Ntp829 +Rp830 +(dp831 +g201 +g176 +(g177 +(I0 +tp832 +g179 +tp833 +Rp834 +(I1 +(I1 +tp835 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p836 +tp837 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp838 +Rp839 +(dp840 +g201 +g176 +(g177 +(I0 +tp841 +g179 +tp842 +Rp843 +(I1 +(I2 +tp844 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p845 +tp846 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp847 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp848 +g179 +tp849 +Rp850 +(I1 +(I1 +I1 +I1 +tp851 +g38 +I00 +S'\x89N\xaa\xa7Y\xc0\xd6?' +p852 +tp853 +bsg238 +g176 +(g177 +(I0 +tp854 +g179 +tp855 +Rp856 +(I1 +(I1 +I1 +I1 +tp857 +g38 +I00 +S'\xb5i\x85\xa5\x8b\xa1\x11?' +p858 +tp859 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp860 +g179 +tp861 +Rp862 +(I1 +(I1 +I1 +I1 +tp863 +g38 +I00 +S'u\x8b:K\x9b\x16\xb0?' +p864 +tp865 +bsg252 +g260 +sg48 +(lp866 +g0 +(g52 +g2 +Ntp867 +Rp868 +(dp869 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp870 +g179 +tp871 +Rp872 +(I1 +(I1 +I1 +I1 +tp873 +g38 +I00 +S'\x1cT\xcaa\xca\x9f\x16@' +p874 +tp875 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp876 +g334 +asg113 +I10019 +sg280 +I01 +sbaatp877 +Rp878 +sg337 +I00 +sg338 +Nsbaa(lp879 +g340 +ag0 +(g341 +g2 +Ntp880 +Rp881 +(dp882 +g17 +g739 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp883 +(lp884 +g189 +ag0 +(g190 +g2 +Ntp885 +Rp886 +(dp887 +g194 +I01 +sg195 +(lp888 +g0 +(g197 +g2 +Ntp889 +Rp890 +(dp891 +g201 +g176 +(g177 +(I0 +tp892 +g179 +tp893 +Rp894 +(I1 +(I1 +tp895 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p896 +tp897 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp898 +Rp899 +(dp900 +g201 +g176 +(g177 +(I0 +tp901 +g179 +tp902 +Rp903 +(I1 +(I2 +tp904 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p905 +tp906 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp907 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp908 +g179 +tp909 +Rp910 +(I1 +(I1 +I1 +I1 +tp911 +g38 +I00 +S'\x88\x08/T\xb2\xae\r@' +p912 +tp913 +bsg238 +g176 +(g177 +(I0 +tp914 +g179 +tp915 +Rp916 +(I1 +(I1 +I1 +I1 +tp917 +g38 +I00 +S'v\xae5\x1e\x11B+?' +p918 +tp919 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp920 +g179 +tp921 +Rp922 +(I1 +(I1 +I1 +I1 +tp923 +g38 +I00 +S'\x9c\x02x/\xee\xfc\xc9?' +p924 +tp925 +bsg252 +g260 +sg48 +(lp926 +g0 +(g52 +g2 +Ntp927 +Rp928 +(dp929 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp930 +g179 +tp931 +Rp932 +(I1 +(I1 +I1 +I1 +tp933 +g38 +I00 +S'\xd6a`y\xd7E2@' +p934 +tp935 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp936 +g279 +asg113 +I10022 +sg280 +I01 +sbaa(lp937 +g401 +ag0 +(g190 +g2 +Ntp938 +Rp939 +(dp940 +g194 +I01 +sg195 +(lp941 +g0 +(g197 +g2 +Ntp942 +Rp943 +(dp944 +g201 +g176 +(g177 +(I0 +tp945 +g179 +tp946 +Rp947 +(I1 +(I1 +tp948 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p949 +tp950 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp951 +Rp952 +(dp953 +g201 +g176 +(g177 +(I0 +tp954 +g179 +tp955 +Rp956 +(I1 +(I2 +tp957 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p958 +tp959 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp960 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp961 +g179 +tp962 +Rp963 +(I1 +(I1 +I1 +I1 +tp964 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p965 +tp966 +bsg238 +g176 +(g177 +(I0 +tp967 +g179 +tp968 +Rp969 +(I1 +(I1 +I1 +I1 +tp970 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p971 +tp972 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp973 +g179 +tp974 +Rp975 +(I1 +(I1 +I1 +I1 +tp976 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p977 +tp978 +bsg252 +g260 +sg48 +(lp979 +g0 +(g52 +g2 +Ntp980 +Rp981 +(dp982 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp983 +g179 +tp984 +Rp985 +(I1 +(I1 +I1 +I1 +tp986 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p987 +tp988 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp989 +g454 +asg113 +I10023 +sg280 +I01 +sbaatp990 +Rp991 +sg337 +I00 +sg338 +Nsbaa(lp992 +g458 +ag0 +(g459 +g2 +Ntp993 +Rp994 +(dp995 +g17 +g739 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp996 +(lp997 +g189 +ag0 +(g190 +g2 +Ntp998 +Rp999 +(dp1000 +g194 +I01 +sg195 +(lp1001 +g0 +(g197 +g2 +Ntp1002 +Rp1003 +(dp1004 +g201 +g176 +(g177 +(I0 +tp1005 +g179 +tp1006 +Rp1007 +(I1 +(I1 +tp1008 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1009 +tp1010 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1011 +Rp1012 +(dp1013 +g201 +g176 +(g177 +(I0 +tp1014 +g179 +tp1015 +Rp1016 +(I1 +(I2 +tp1017 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1018 +tp1019 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp1020 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1021 +g179 +tp1022 +Rp1023 +(I1 +(I1 +I1 +I1 +tp1024 +g38 +I00 +S'\x0b[.\xa2R\xba\r@' +p1025 +tp1026 +bsg238 +g176 +(g177 +(I0 +tp1027 +g179 +tp1028 +Rp1029 +(I1 +(I1 +I1 +I1 +tp1030 +g38 +I00 +S'bv\xc9\x02\x04\xf9K?' +p1031 +tp1032 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1033 +g179 +tp1034 +Rp1035 +(I1 +(I1 +I1 +I1 +tp1036 +g38 +I00 +S'a\xcd8\xe7\x18\xfd\xc9?' +p1037 +tp1038 +bsg252 +g513 +sg48 +(lp1039 +g0 +(g52 +g2 +Ntp1040 +Rp1041 +(dp1042 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp1043 +g179 +tp1044 +Rp1045 +(I1 +(I1 +I1 +I1 +tp1046 +g38 +I00 +S'h\xf0\x93\x82\xf5E2@' +p1047 +tp1048 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp1049 +g527 +asg113 +I10026 +sg280 +I01 +sbaa(lp1050 +g529 +ag0 +(g190 +g2 +Ntp1051 +Rp1052 +(dp1053 +g194 +I01 +sg195 +(lp1054 +g0 +(g197 +g2 +Ntp1055 +Rp1056 +(dp1057 +g201 +g176 +(g177 +(I0 +tp1058 +g179 +tp1059 +Rp1060 +(I1 +(I1 +tp1061 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1062 +tp1063 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1064 +Rp1065 +(dp1066 +g201 +g176 +(g177 +(I0 +tp1067 +g179 +tp1068 +Rp1069 +(I1 +(I2 +tp1070 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1071 +tp1072 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1073 +Rp1074 +(dp1075 +g201 +g176 +(g177 +(I0 +tp1076 +g179 +tp1077 +Rp1078 +(I1 +(I2 +tp1079 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1080 +tp1081 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp1082 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1083 +g179 +tp1084 +Rp1085 +(I1 +(I1 +I1 +I1 +tp1086 +g38 +I00 +S'\xe4\x95g5\x8f\x89\xd6?' +p1087 +tp1088 +bsg238 +g176 +(g177 +(I0 +tp1089 +g179 +tp1090 +Rp1091 +(I1 +(I1 +I1 +I1 +tp1092 +g38 +I00 +S'%\xad\x83\xf7\xf4M1?' +p1093 +tp1094 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1095 +g179 +tp1096 +Rp1097 +(I1 +(I1 +I1 +I1 +tp1098 +g38 +I00 +S'?,_H%\x00\xb0?' +p1099 +tp1100 +bsg252 +g586 +sg48 +(lp1101 +g0 +(g52 +g2 +Ntp1102 +Rp1103 +(dp1104 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp1105 +g179 +tp1106 +Rp1107 +(I1 +(I1 +I1 +I1 +tp1108 +g38 +I00 +S'9\xd6\xc5m4\x80\x16@' +p1109 +tp1110 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp1111 +g600 +asg113 +I10027 +sg280 +I01 +sbaatp1112 +Rp1113 +sg337 +I00 +sg338 +Nsbaa(lp1114 +g604 +ag0 +(g605 +g2 +Ntp1115 +Rp1116 +(dp1117 +g17 +g739 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1118 +(lp1119 +g611 +ag0 +(g190 +g2 +Ntp1120 +Rp1121 +(dp1122 +g194 +I01 +sg195 +(lp1123 +g0 +(g197 +g2 +Ntp1124 +Rp1125 +(dp1126 +g201 +g176 +(g177 +(I0 +tp1127 +g179 +tp1128 +Rp1129 +(I1 +(I1 +tp1130 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1131 +tp1132 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1133 +Rp1134 +(dp1135 +g201 +g176 +(g177 +(I0 +tp1136 +g179 +tp1137 +Rp1138 +(I1 +(I2 +tp1139 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1140 +tp1141 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp1142 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1143 +g179 +tp1144 +Rp1145 +(I1 +(I1 +I1 +I1 +tp1146 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1147 +tp1148 +bsg238 +g176 +(g177 +(I0 +tp1149 +g179 +tp1150 +Rp1151 +(I1 +(I1 +I1 +I1 +tp1152 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1153 +tp1154 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1155 +g179 +tp1156 +Rp1157 +(I1 +(I1 +I1 +I1 +tp1158 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1159 +tp1160 +bsg252 +g513 +sg48 +(lp1161 +g0 +(g52 +g2 +Ntp1162 +Rp1163 +(dp1164 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp1165 +g179 +tp1166 +Rp1167 +(I1 +(I1 +I1 +I1 +tp1168 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1169 +tp1170 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp1171 +g664 +asg113 +I10030 +sg280 +I01 +sbaa(lp1172 +g666 +ag0 +(g190 +g2 +Ntp1173 +Rp1174 +(dp1175 +g194 +I01 +sg195 +(lp1176 +g0 +(g197 +g2 +Ntp1177 +Rp1178 +(dp1179 +g201 +g176 +(g177 +(I0 +tp1180 +g179 +tp1181 +Rp1182 +(I1 +(I1 +tp1183 +g208 +I00 +S"\x11'\x00\x00\x00\x00\x00\x00" +p1184 +tp1185 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1186 +Rp1187 +(dp1188 +g201 +g176 +(g177 +(I0 +tp1189 +g179 +tp1190 +Rp1191 +(I1 +(I2 +tp1192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1193 +tp1194 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp1195 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1196 +g179 +tp1197 +Rp1198 +(I1 +(I1 +I1 +I1 +tp1199 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1200 +tp1201 +bsg238 +g176 +(g177 +(I0 +tp1202 +g179 +tp1203 +Rp1204 +(I1 +(I1 +I1 +I1 +tp1205 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1206 +tp1207 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1208 +g179 +tp1209 +Rp1210 +(I1 +(I1 +I1 +I1 +tp1211 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1212 +tp1213 +bsg252 +g713 +sg48 +(lp1214 +g0 +(g52 +g2 +Ntp1215 +Rp1216 +(dp1217 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp1218 +g179 +tp1219 +Rp1220 +(I1 +(I1 +I1 +I1 +tp1221 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p1222 +tp1223 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp1224 +g727 +asg113 +I10031 +sg280 +I01 +sbaatp1225 +Rp1226 +sg337 +I00 +sg338 +Nsbaatp1227 +Rp1228 +aa(lp1229 +I10002 +ag7 +((lp1230 +(lp1231 +g12 +ag0 +(g13 +g2 +Ntp1232 +Rp1233 +(dp1234 +g17 +g0 +(g18 +g2 +Ntp1235 +Rp1236 +(dp1237 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g0 +(g27 +g2 +Ntp1238 +Rp1239 +(dp1240 +g31 +g32 +sg33 +g34 +(g38 +S'\xe1\xde<\xa20\x92\xb1?' +p1241 +tp1242 +Rp1243 +sg44 +(lp1244 +sg46 +V3.1 w/o enriched UO2 +p1245 +sg48 +g7 +((lp1246 +(lp1247 +VU-235 +p1248 +a(g0 +(g52 +g2 +Ntp1249 +Rp1250 +(dp1251 +g56 +V71c +p1252 +sg58 +Nsg59 +Nsg46 +g1248 +sbg34 +(g38 +S'\xa2\x96#\xba \x88G?' +p1253 +tp1254 +Rp1255 +g63 +tp1256 +aa(lp1257 +VU-238 +p1258 +a(g0 +(g52 +g2 +Ntp1259 +Rp1260 +(dp1261 +g56 +V71c +p1262 +sg58 +Nsg59 +Nsg46 +g1258 +sbg34 +(g38 +S'\x9a\xe7\xd2\t\xb2\xaf\x96?' +p1263 +tp1264 +Rp1265 +g63 +tp1266 +aa(lp1267 +VO-16 +p1268 +a(g0 +(g52 +g2 +Ntp1269 +Rp1270 +(dp1271 +g56 +V71c +p1272 +sg58 +Nsg59 +Nsg46 +g1268 +sbg34 +(g38 +S'\x9b\xbb\xa7\xbcgn\xa7?' +p1273 +tp1274 +Rp1275 +g63 +tp1276 +aatp1277 +Rp1278 +sg107 +g7 +((lp1279 +tp1280 +Rp1281 +sg111 +I00 +sg112 +Nsg113 +I10000 +sbsg114 +Nsg46 +Vfuel +p1282 +sg116 +g0 +(g117 +g2 +Ntp1283 +Rp1284 +(dp1285 +g121 +(lp1286 +g0 +(g123 +g2 +Ntp1287 +Rp1288 +(dp1289 +g127 +g0 +(g128 +g2 +Ntp1290 +Rp1291 +(dp1292 +g23 +g132 +sg133 +(dp1293 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xe3?' +p1294 +tp1295 +Rp1296 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p1297 +sg113 +I8 +sg146 +(lp1298 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp1299 +Rp1300 +(dp1301 +g127 +g0 +(g128 +g2 +Ntp1302 +Rp1303 +(dp1304 +g23 +g132 +sg133 +(dp1305 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xe4?' +p1306 +tp1307 +Rp1308 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p1309 +sg113 +I7 +sg146 +(lp1310 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10002 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1311 +(lp1312 +g189 +ag0 +(g190 +g2 +Ntp1313 +Rp1314 +(dp1315 +g194 +I01 +sg195 +(lp1316 +g0 +(g197 +g2 +Ntp1317 +Rp1318 +(dp1319 +g201 +g176 +(g177 +(I0 +tp1320 +g179 +tp1321 +Rp1322 +(I1 +(I1 +tp1323 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1324 +tp1325 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1326 +Rp1327 +(dp1328 +g201 +g176 +(g177 +(I0 +tp1329 +g179 +tp1330 +Rp1331 +(I1 +(I2 +tp1332 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1333 +tp1334 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1335 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1336 +g179 +tp1337 +Rp1338 +(I1 +(I1 +I1 +I1 +tp1339 +g38 +I00 +S'\xec@\xe3r\xdd\x808@' +p1340 +tp1341 +bsg238 +g176 +(g177 +(I0 +tp1342 +g179 +tp1343 +Rp1344 +(I1 +(I1 +I1 +I1 +tp1345 +g38 +I00 +S'\xd2\xa8=X\xe1\x1aB?' +p1346 +tp1347 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1348 +g179 +tp1349 +Rp1350 +(I1 +(I1 +I1 +I1 +tp1351 +g38 +I00 +S'\xe8\xc6\xd67@\xb2\xe0?' +p1352 +tp1353 +bsg252 +g260 +sg48 +(lp1354 +g0 +(g52 +g2 +Ntp1355 +Rp1356 +(dp1357 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1358 +g179 +tp1359 +Rp1360 +(I1 +(I1 +I1 +I1 +tp1361 +g38 +I00 +S'\xb6\x07\x86N\xaazG@' +p1362 +tp1363 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1364 +g279 +asg113 +I10034 +sg280 +I01 +sbaa(lp1365 +g12 +ag0 +(g190 +g2 +Ntp1366 +Rp1367 +(dp1368 +g194 +I01 +sg195 +(lp1369 +g0 +(g197 +g2 +Ntp1370 +Rp1371 +(dp1372 +g201 +g176 +(g177 +(I0 +tp1373 +g179 +tp1374 +Rp1375 +(I1 +(I1 +tp1376 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1377 +tp1378 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1379 +Rp1380 +(dp1381 +g201 +g176 +(g177 +(I0 +tp1382 +g179 +tp1383 +Rp1384 +(I1 +(I2 +tp1385 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1386 +tp1387 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1388 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1389 +g179 +tp1390 +Rp1391 +(I1 +(I1 +I1 +I1 +tp1392 +g38 +I00 +S'\x95\xfe\x82\x86\x84r\x0f@' +p1393 +tp1394 +bsg238 +g176 +(g177 +(I0 +tp1395 +g179 +tp1396 +Rp1397 +(I1 +(I1 +I1 +I1 +tp1398 +g38 +I00 +S'\xbc(\x1a-\x16K0?' +p1399 +tp1400 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1401 +g179 +tp1402 +Rp1403 +(I1 +(I1 +I1 +I1 +tp1404 +g38 +I00 +S'\xd2o"t\xc1\xbf\xca?' +p1405 +tp1406 +bsg252 +g260 +sg48 +(lp1407 +g0 +(g52 +g2 +Ntp1408 +Rp1409 +(dp1410 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1411 +g179 +tp1412 +Rp1413 +(I1 +(I1 +I1 +I1 +tp1414 +g38 +I00 +S'\xa06\xa8\x05\xd4\xce2@' +p1415 +tp1416 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1417 +g334 +asg113 +I10035 +sg280 +I01 +sbaatp1418 +Rp1419 +sg337 +I00 +sg338 +Nsbaa(lp1420 +g340 +ag0 +(g341 +g2 +Ntp1421 +Rp1422 +(dp1423 +g17 +g1236 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1424 +(lp1425 +g189 +ag0 +(g190 +g2 +Ntp1426 +Rp1427 +(dp1428 +g194 +I01 +sg195 +(lp1429 +g0 +(g197 +g2 +Ntp1430 +Rp1431 +(dp1432 +g201 +g176 +(g177 +(I0 +tp1433 +g179 +tp1434 +Rp1435 +(I1 +(I1 +tp1436 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1437 +tp1438 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1439 +Rp1440 +(dp1441 +g201 +g176 +(g177 +(I0 +tp1442 +g179 +tp1443 +Rp1444 +(I1 +(I2 +tp1445 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1446 +tp1447 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1448 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1449 +g179 +tp1450 +Rp1451 +(I1 +(I1 +I1 +I1 +tp1452 +g38 +I00 +S'\xec@\xe3r\xdd\x808@' +p1453 +tp1454 +bsg238 +g176 +(g177 +(I0 +tp1455 +g179 +tp1456 +Rp1457 +(I1 +(I1 +I1 +I1 +tp1458 +g38 +I00 +S'\xd2\xa8=X\xe1\x1aB?' +p1459 +tp1460 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1461 +g179 +tp1462 +Rp1463 +(I1 +(I1 +I1 +I1 +tp1464 +g38 +I00 +S'\xe8\xc6\xd67@\xb2\xe0?' +p1465 +tp1466 +bsg252 +g260 +sg48 +(lp1467 +g0 +(g52 +g2 +Ntp1468 +Rp1469 +(dp1470 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1471 +g179 +tp1472 +Rp1473 +(I1 +(I1 +I1 +I1 +tp1474 +g38 +I00 +S'\xb6\x07\x86N\xaazG@' +p1475 +tp1476 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1477 +g279 +asg113 +I10038 +sg280 +I01 +sbaa(lp1478 +g401 +ag0 +(g190 +g2 +Ntp1479 +Rp1480 +(dp1481 +g194 +I01 +sg195 +(lp1482 +g0 +(g197 +g2 +Ntp1483 +Rp1484 +(dp1485 +g201 +g176 +(g177 +(I0 +tp1486 +g179 +tp1487 +Rp1488 +(I1 +(I1 +tp1489 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1490 +tp1491 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1492 +Rp1493 +(dp1494 +g201 +g176 +(g177 +(I0 +tp1495 +g179 +tp1496 +Rp1497 +(I1 +(I2 +tp1498 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1499 +tp1500 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1501 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1502 +g179 +tp1503 +Rp1504 +(I1 +(I1 +I1 +I1 +tp1505 +g38 +I00 +S']E\x83gz\x8f\xa1?' +p1506 +tp1507 +bsg238 +g176 +(g177 +(I0 +tp1508 +g179 +tp1509 +Rp1510 +(I1 +(I1 +I1 +I1 +tp1511 +g38 +I00 +S'yG\xbc\xb2\xc1\x9f\x07?' +p1512 +tp1513 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1514 +g179 +tp1515 +Rp1516 +(I1 +(I1 +I1 +I1 +tp1517 +g38 +I00 +S').S\xa86\xfc\x93?' +p1518 +tp1519 +bsg252 +g260 +sg48 +(lp1520 +g0 +(g52 +g2 +Ntp1521 +Rp1522 +(dp1523 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1524 +g179 +tp1525 +Rp1526 +(I1 +(I1 +I1 +I1 +tp1527 +g38 +I00 +S'\xe9\xf8\xb4\xdc\xac\x1a\xfc?' +p1528 +tp1529 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1530 +g454 +asg113 +I10039 +sg280 +I01 +sbaatp1531 +Rp1532 +sg337 +I00 +sg338 +Nsbaa(lp1533 +g458 +ag0 +(g459 +g2 +Ntp1534 +Rp1535 +(dp1536 +g17 +g1236 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1537 +(lp1538 +g189 +ag0 +(g190 +g2 +Ntp1539 +Rp1540 +(dp1541 +g194 +I01 +sg195 +(lp1542 +g0 +(g197 +g2 +Ntp1543 +Rp1544 +(dp1545 +g201 +g176 +(g177 +(I0 +tp1546 +g179 +tp1547 +Rp1548 +(I1 +(I1 +tp1549 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1550 +tp1551 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1552 +Rp1553 +(dp1554 +g201 +g176 +(g177 +(I0 +tp1555 +g179 +tp1556 +Rp1557 +(I1 +(I2 +tp1558 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1559 +tp1560 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp1561 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1562 +g179 +tp1563 +Rp1564 +(I1 +(I1 +I1 +I1 +tp1565 +g38 +I00 +S'\x9f\xf8\\\x85_\x858@' +p1566 +tp1567 +bsg238 +g176 +(g177 +(I0 +tp1568 +g179 +tp1569 +Rp1570 +(I1 +(I1 +I1 +I1 +tp1571 +g38 +I00 +S'\xef\xc8\xbf\x8a\x06\x90Z?' +p1572 +tp1573 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1574 +g179 +tp1575 +Rp1576 +(I1 +(I1 +I1 +I1 +tp1577 +g38 +I00 +S'v\xc0o\xe9)\xb2\xe0?' +p1578 +tp1579 +bsg252 +g513 +sg48 +(lp1580 +g0 +(g52 +g2 +Ntp1581 +Rp1582 +(dp1583 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp1584 +g179 +tp1585 +Rp1586 +(I1 +(I1 +I1 +I1 +tp1587 +g38 +I00 +S'\xa6&E\xf0\x8azG@' +p1588 +tp1589 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp1590 +g527 +asg113 +I10042 +sg280 +I01 +sbaa(lp1591 +g529 +ag0 +(g190 +g2 +Ntp1592 +Rp1593 +(dp1594 +g194 +I01 +sg195 +(lp1595 +g0 +(g197 +g2 +Ntp1596 +Rp1597 +(dp1598 +g201 +g176 +(g177 +(I0 +tp1599 +g179 +tp1600 +Rp1601 +(I1 +(I1 +tp1602 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1603 +tp1604 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1605 +Rp1606 +(dp1607 +g201 +g176 +(g177 +(I0 +tp1608 +g179 +tp1609 +Rp1610 +(I1 +(I2 +tp1611 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1612 +tp1613 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1614 +Rp1615 +(dp1616 +g201 +g176 +(g177 +(I0 +tp1617 +g179 +tp1618 +Rp1619 +(I1 +(I2 +tp1620 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1621 +tp1622 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp1623 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1624 +g179 +tp1625 +Rp1626 +(I1 +(I1 +I1 +I1 +tp1627 +g38 +I00 +S'-\x99RM\xff\x80\x0b@' +p1628 +tp1629 +bsg238 +g176 +(g177 +(I0 +tp1630 +g179 +tp1631 +Rp1632 +(I1 +(I1 +I1 +I1 +tp1633 +g38 +I00 +S'3r\xc7\xe6}\xbbD?' +p1634 +tp1635 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1636 +g179 +tp1637 +Rp1638 +(I1 +(I1 +I1 +I1 +tp1639 +g38 +I00 +S'\xae\xc71\x7fr\x01\xc9?' +p1640 +tp1641 +bsg252 +g586 +sg48 +(lp1642 +g0 +(g52 +g2 +Ntp1643 +Rp1644 +(dp1645 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp1646 +g179 +tp1647 +Rp1648 +(I1 +(I1 +I1 +I1 +tp1649 +g38 +I00 +S'f\x00o\x81\x04\x951@' +p1650 +tp1651 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp1652 +g600 +asg113 +I10043 +sg280 +I01 +sbaatp1653 +Rp1654 +sg337 +I00 +sg338 +Nsbaa(lp1655 +g604 +ag0 +(g605 +g2 +Ntp1656 +Rp1657 +(dp1658 +g17 +g1236 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1659 +(lp1660 +g611 +ag0 +(g190 +g2 +Ntp1661 +Rp1662 +(dp1663 +g194 +I01 +sg195 +(lp1664 +g0 +(g197 +g2 +Ntp1665 +Rp1666 +(dp1667 +g201 +g176 +(g177 +(I0 +tp1668 +g179 +tp1669 +Rp1670 +(I1 +(I1 +tp1671 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1672 +tp1673 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1674 +Rp1675 +(dp1676 +g201 +g176 +(g177 +(I0 +tp1677 +g179 +tp1678 +Rp1679 +(I1 +(I2 +tp1680 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1681 +tp1682 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp1683 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1684 +g179 +tp1685 +Rp1686 +(I1 +(I1 +I1 +I1 +tp1687 +g38 +I00 +S'\xf6\x92:T\xec\x9c\xa1?' +p1688 +tp1689 +bsg238 +g176 +(g177 +(I0 +tp1690 +g179 +tp1691 +Rp1692 +(I1 +(I1 +I1 +I1 +tp1693 +g38 +I00 +S"\xe1|\x81\xc4M\x15'?" +p1694 +tp1695 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1696 +g179 +tp1697 +Rp1698 +(I1 +(I1 +I1 +I1 +tp1699 +g38 +I00 +S'\x08\x8f\xe3\xc3\x88\xf2\x93?' +p1700 +tp1701 +bsg252 +g513 +sg48 +(lp1702 +g0 +(g52 +g2 +Ntp1703 +Rp1704 +(dp1705 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp1706 +g179 +tp1707 +Rp1708 +(I1 +(I1 +I1 +I1 +tp1709 +g38 +I00 +S'#\x01xS\x10\r\xfc?' +p1710 +tp1711 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp1712 +g664 +asg113 +I10046 +sg280 +I01 +sbaa(lp1713 +g666 +ag0 +(g190 +g2 +Ntp1714 +Rp1715 +(dp1716 +g194 +I01 +sg195 +(lp1717 +g0 +(g197 +g2 +Ntp1718 +Rp1719 +(dp1720 +g201 +g176 +(g177 +(I0 +tp1721 +g179 +tp1722 +Rp1723 +(I1 +(I1 +tp1724 +g208 +I00 +S"\x12'\x00\x00\x00\x00\x00\x00" +p1725 +tp1726 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1727 +Rp1728 +(dp1729 +g201 +g176 +(g177 +(I0 +tp1730 +g179 +tp1731 +Rp1732 +(I1 +(I2 +tp1733 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1734 +tp1735 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp1736 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1737 +g179 +tp1738 +Rp1739 +(I1 +(I1 +I1 +I1 +tp1740 +g38 +I00 +S'\xf7\x92:T\xec\x9c\xa1?' +p1741 +tp1742 +bsg238 +g176 +(g177 +(I0 +tp1743 +g179 +tp1744 +Rp1745 +(I1 +(I1 +I1 +I1 +tp1746 +g38 +I00 +S"a}\x81\xc4M\x15'?" +p1747 +tp1748 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1749 +g179 +tp1750 +Rp1751 +(I1 +(I1 +I1 +I1 +tp1752 +g38 +I00 +S'\x08\x8f\xe3\xc3\x88\xf2\x93?' +p1753 +tp1754 +bsg252 +g713 +sg48 +(lp1755 +g0 +(g52 +g2 +Ntp1756 +Rp1757 +(dp1758 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp1759 +g179 +tp1760 +Rp1761 +(I1 +(I1 +I1 +I1 +tp1762 +g38 +I00 +S'#\x01xS\x10\r\xfc?' +p1763 +tp1764 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp1765 +g727 +asg113 +I10047 +sg280 +I01 +sbaatp1766 +Rp1767 +sg337 +I00 +sg338 +Nsbaatp1768 +Rp1769 +aa(lp1770 +I10003 +ag7 +((lp1771 +(lp1772 +g12 +ag0 +(g13 +g2 +Ntp1773 +Rp1774 +(dp1775 +g17 +g0 +(g18 +g2 +Ntp1776 +Rp1777 +(dp1778 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g0 +(g27 +g2 +Ntp1779 +Rp1780 +(dp1781 +g31 +g32 +sg33 +g34 +(g38 +S'\x90\xdd\x03,\xda\xf6\xb0?' +p1782 +tp1783 +Rp1784 +sg44 +(lp1785 +(VHH2O +p1786 +V71t +p1787 +tp1788 +asg46 +VBorated Water +p1789 +sg48 +g7 +((lp1790 +(lp1791 +VH-1 +p1792 +a(g0 +(g52 +g2 +Ntp1793 +Rp1794 +(dp1795 +g56 +V71c +p1796 +sg58 +Nsg59 +Nsg46 +g1792 +sbg34 +(g38 +S'\xe6E\x81\x99J\x9a\xa6?' +p1797 +tp1798 +Rp1799 +g63 +tp1800 +aa(lp1801 +VO-16 +p1802 +a(g0 +(g52 +g2 +Ntp1803 +Rp1804 +(dp1805 +g56 +V71c +p1806 +sg58 +Nsg59 +Nsg46 +g1802 +sbg34 +(g38 +S'\x8e\xf2\x82>G\x9a\x96?' +p1807 +tp1808 +Rp1809 +g63 +tp1810 +aa(lp1811 +VB-10 +p1812 +a(g0 +(g52 +g2 +Ntp1813 +Rp1814 +(dp1815 +g56 +V71c +p1816 +sg58 +Nsg59 +Nsg46 +g1812 +sbg34 +(g38 +S'\xd8!]\xe2\xe4\xf9\xe3>' +p1817 +tp1818 +Rp1819 +g63 +tp1820 +aa(lp1821 +VB-11 +p1822 +a(g0 +(g52 +g2 +Ntp1823 +Rp1824 +(dp1825 +g56 +V71c +p1826 +sg58 +Nsg59 +Nsg46 +g1822 +sbg34 +(g38 +S'\x18\x8bX\xdb\x03\x1a\x04?' +p1827 +tp1828 +Rp1829 +g63 +tp1830 +aatp1831 +Rp1832 +sg107 +g7 +((lp1833 +tp1834 +Rp1835 +sg111 +I00 +sg112 +Nsg113 +I10002 +sbsg114 +Nsg46 +Vwater +p1836 +sg116 +g0 +(g117 +g2 +Ntp1837 +Rp1838 +(dp1839 +g121 +(lp1840 +g0 +(g123 +g2 +Ntp1841 +Rp1842 +(dp1843 +g127 +g0 +(g128 +g2 +Ntp1844 +Rp1845 +(dp1846 +g23 +g132 +sg133 +(dp1847 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xaeG\xe1z\x14.\x12@' +p1848 +tp1849 +Rp1850 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p1851 +sg113 +I9 +sg146 +(lp1852 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp1853 +Rp1854 +(dp1855 +g127 +g0 +(g128 +g2 +Ntp1856 +Rp1857 +(dp1858 +g23 +g132 +sg133 +(dp1859 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'q=\n\xd7\xa3p\x12@' +p1860 +tp1861 +Rp1862 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p1863 +sg113 +I10 +sg146 +(lp1864 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10003 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1865 +(lp1866 +g189 +ag0 +(g190 +g2 +Ntp1867 +Rp1868 +(dp1869 +g194 +I01 +sg195 +(lp1870 +g0 +(g197 +g2 +Ntp1871 +Rp1872 +(dp1873 +g201 +g176 +(g177 +(I0 +tp1874 +g179 +tp1875 +Rp1876 +(I1 +(I1 +tp1877 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1878 +tp1879 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1880 +Rp1881 +(dp1882 +g201 +g176 +(g177 +(I0 +tp1883 +g179 +tp1884 +Rp1885 +(I1 +(I2 +tp1886 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1887 +tp1888 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1889 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1890 +g179 +tp1891 +Rp1892 +(I1 +(I1 +I1 +I1 +tp1893 +g38 +I00 +S'\xf2\x85@Y\xb4MI@' +p1894 +tp1895 +bsg238 +g176 +(g177 +(I0 +tp1896 +g179 +tp1897 +Rp1898 +(I1 +(I1 +I1 +I1 +tp1899 +g38 +I00 +S'\xe5\xf7Rs\xb3(F?' +p1900 +tp1901 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1902 +g179 +tp1903 +Rp1904 +(I1 +(I1 +I1 +I1 +tp1905 +g38 +I00 +S'\xd7k\xc7x\xb0\xfe\xe7?' +p1906 +tp1907 +bsg252 +g260 +sg48 +(lp1908 +g0 +(g52 +g2 +Ntp1909 +Rp1910 +(dp1911 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1912 +g179 +tp1913 +Rp1914 +(I1 +(I1 +I1 +I1 +tp1915 +g38 +I00 +S'\xd37\xec\x14\x14\xdfP@' +p1916 +tp1917 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1918 +g279 +asg113 +I10050 +sg280 +I01 +sbaa(lp1919 +g12 +ag0 +(g190 +g2 +Ntp1920 +Rp1921 +(dp1922 +g194 +I01 +sg195 +(lp1923 +g0 +(g197 +g2 +Ntp1924 +Rp1925 +(dp1926 +g201 +g176 +(g177 +(I0 +tp1927 +g179 +tp1928 +Rp1929 +(I1 +(I1 +tp1930 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1931 +tp1932 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1933 +Rp1934 +(dp1935 +g201 +g176 +(g177 +(I0 +tp1936 +g179 +tp1937 +Rp1938 +(I1 +(I2 +tp1939 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p1940 +tp1941 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp1942 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp1943 +g179 +tp1944 +Rp1945 +(I1 +(I1 +I1 +I1 +tp1946 +g38 +I00 +S'&\xd0\x1f\x98\x97IN@' +p1947 +tp1948 +bsg238 +g176 +(g177 +(I0 +tp1949 +g179 +tp1950 +Rp1951 +(I1 +(I1 +I1 +I1 +tp1952 +g38 +I00 +S'#\x0bR\xf2\xa8SR?' +p1953 +tp1954 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp1955 +g179 +tp1956 +Rp1957 +(I1 +(I1 +I1 +I1 +tp1958 +g38 +I00 +S"\x17/\xc8\x85'@\xea?" +p1959 +tp1960 +bsg252 +g260 +sg48 +(lp1961 +g0 +(g52 +g2 +Ntp1962 +Rp1963 +(dp1964 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp1965 +g179 +tp1966 +Rp1967 +(I1 +(I1 +I1 +I1 +tp1968 +g38 +I00 +S'\x1c\xc1\x10\xca\x1buR@' +p1969 +tp1970 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp1971 +g334 +asg113 +I10051 +sg280 +I01 +sbaatp1972 +Rp1973 +sg337 +I00 +sg338 +Nsbaa(lp1974 +g340 +ag0 +(g341 +g2 +Ntp1975 +Rp1976 +(dp1977 +g17 +g1777 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp1978 +(lp1979 +g189 +ag0 +(g190 +g2 +Ntp1980 +Rp1981 +(dp1982 +g194 +I01 +sg195 +(lp1983 +g0 +(g197 +g2 +Ntp1984 +Rp1985 +(dp1986 +g201 +g176 +(g177 +(I0 +tp1987 +g179 +tp1988 +Rp1989 +(I1 +(I1 +tp1990 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p1991 +tp1992 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp1993 +Rp1994 +(dp1995 +g201 +g176 +(g177 +(I0 +tp1996 +g179 +tp1997 +Rp1998 +(I1 +(I2 +tp1999 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2000 +tp2001 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2002 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2003 +g179 +tp2004 +Rp2005 +(I1 +(I1 +I1 +I1 +tp2006 +g38 +I00 +S'\xf2\x85@Y\xb4MI@' +p2007 +tp2008 +bsg238 +g176 +(g177 +(I0 +tp2009 +g179 +tp2010 +Rp2011 +(I1 +(I1 +I1 +I1 +tp2012 +g38 +I00 +S'\xe5\xf7Rs\xb3(F?' +p2013 +tp2014 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2015 +g179 +tp2016 +Rp2017 +(I1 +(I1 +I1 +I1 +tp2018 +g38 +I00 +S'\xd7k\xc7x\xb0\xfe\xe7?' +p2019 +tp2020 +bsg252 +g260 +sg48 +(lp2021 +g0 +(g52 +g2 +Ntp2022 +Rp2023 +(dp2024 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2025 +g179 +tp2026 +Rp2027 +(I1 +(I1 +I1 +I1 +tp2028 +g38 +I00 +S'\xd37\xec\x14\x14\xdfP@' +p2029 +tp2030 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2031 +g279 +asg113 +I10054 +sg280 +I01 +sbaa(lp2032 +g401 +ag0 +(g190 +g2 +Ntp2033 +Rp2034 +(dp2035 +g194 +I01 +sg195 +(lp2036 +g0 +(g197 +g2 +Ntp2037 +Rp2038 +(dp2039 +g201 +g176 +(g177 +(I0 +tp2040 +g179 +tp2041 +Rp2042 +(I1 +(I1 +tp2043 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2044 +tp2045 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2046 +Rp2047 +(dp2048 +g201 +g176 +(g177 +(I0 +tp2049 +g179 +tp2050 +Rp2051 +(I1 +(I2 +tp2052 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2053 +tp2054 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2055 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2056 +g179 +tp2057 +Rp2058 +(I1 +(I1 +I1 +I1 +tp2059 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2060 +tp2061 +bsg238 +g176 +(g177 +(I0 +tp2062 +g179 +tp2063 +Rp2064 +(I1 +(I1 +I1 +I1 +tp2065 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2066 +tp2067 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2068 +g179 +tp2069 +Rp2070 +(I1 +(I1 +I1 +I1 +tp2071 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2072 +tp2073 +bsg252 +g260 +sg48 +(lp2074 +g0 +(g52 +g2 +Ntp2075 +Rp2076 +(dp2077 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2078 +g179 +tp2079 +Rp2080 +(I1 +(I1 +I1 +I1 +tp2081 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2082 +tp2083 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2084 +g454 +asg113 +I10055 +sg280 +I01 +sbaatp2085 +Rp2086 +sg337 +I00 +sg338 +Nsbaa(lp2087 +g458 +ag0 +(g459 +g2 +Ntp2088 +Rp2089 +(dp2090 +g17 +g1777 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2091 +(lp2092 +g189 +ag0 +(g190 +g2 +Ntp2093 +Rp2094 +(dp2095 +g194 +I01 +sg195 +(lp2096 +g0 +(g197 +g2 +Ntp2097 +Rp2098 +(dp2099 +g201 +g176 +(g177 +(I0 +tp2100 +g179 +tp2101 +Rp2102 +(I1 +(I1 +tp2103 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2104 +tp2105 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2106 +Rp2107 +(dp2108 +g201 +g176 +(g177 +(I0 +tp2109 +g179 +tp2110 +Rp2111 +(I1 +(I2 +tp2112 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2113 +tp2114 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp2115 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2116 +g179 +tp2117 +Rp2118 +(I1 +(I1 +I1 +I1 +tp2119 +g38 +I00 +S'\x1aq\x90\x01]dI@' +p2120 +tp2121 +bsg238 +g176 +(g177 +(I0 +tp2122 +g179 +tp2123 +Rp2124 +(I1 +(I1 +I1 +I1 +tp2125 +g38 +I00 +S'NT\x80\xf5\x9f\xd7V?' +p2126 +tp2127 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2128 +g179 +tp2129 +Rp2130 +(I1 +(I1 +I1 +I1 +tp2131 +g38 +I00 +S'";:\xe9\xb3\x08\xe8?' +p2132 +tp2133 +bsg252 +g513 +sg48 +(lp2134 +g0 +(g52 +g2 +Ntp2135 +Rp2136 +(dp2137 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp2138 +g179 +tp2139 +Rp2140 +(I1 +(I1 +I1 +I1 +tp2141 +g38 +I00 +S'\x94\xf1\xfc\x7f\x1e\xe6P@' +p2142 +tp2143 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp2144 +g527 +asg113 +I10058 +sg280 +I01 +sbaa(lp2145 +g529 +ag0 +(g190 +g2 +Ntp2146 +Rp2147 +(dp2148 +g194 +I01 +sg195 +(lp2149 +g0 +(g197 +g2 +Ntp2150 +Rp2151 +(dp2152 +g201 +g176 +(g177 +(I0 +tp2153 +g179 +tp2154 +Rp2155 +(I1 +(I1 +tp2156 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2157 +tp2158 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2159 +Rp2160 +(dp2161 +g201 +g176 +(g177 +(I0 +tp2162 +g179 +tp2163 +Rp2164 +(I1 +(I2 +tp2165 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2166 +tp2167 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2168 +Rp2169 +(dp2170 +g201 +g176 +(g177 +(I0 +tp2171 +g179 +tp2172 +Rp2173 +(I1 +(I2 +tp2174 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2175 +tp2176 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp2177 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2178 +g179 +tp2179 +Rp2180 +(I1 +(I1 +I1 +I1 +tp2181 +g38 +I00 +S'\x1e\x91\x19\x1ccoM@' +p2182 +tp2183 +bsg238 +g176 +(g177 +(I0 +tp2184 +g179 +tp2185 +Rp2186 +(I1 +(I1 +I1 +I1 +tp2187 +g38 +I00 +S"\x8d\xe2S\x9b\x11'V?" +p2188 +tp2189 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2190 +g179 +tp2191 +Rp2192 +(I1 +(I1 +I1 +I1 +tp2193 +g38 +I00 +S'K\x19t\x91\xa4\xe0\xe9?' +p2194 +tp2195 +bsg252 +g586 +sg48 +(lp2196 +g0 +(g52 +g2 +Ntp2197 +Rp2198 +(dp2199 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp2200 +g179 +tp2201 +Rp2202 +(I1 +(I1 +I1 +I1 +tp2203 +g38 +I00 +S'\xc9\xa1E\xb6\xf31R@' +p2204 +tp2205 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp2206 +g600 +asg113 +I10059 +sg280 +I01 +sbaatp2207 +Rp2208 +sg337 +I00 +sg338 +Nsbaa(lp2209 +g604 +ag0 +(g605 +g2 +Ntp2210 +Rp2211 +(dp2212 +g17 +g1777 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2213 +(lp2214 +g611 +ag0 +(g190 +g2 +Ntp2215 +Rp2216 +(dp2217 +g194 +I01 +sg195 +(lp2218 +g0 +(g197 +g2 +Ntp2219 +Rp2220 +(dp2221 +g201 +g176 +(g177 +(I0 +tp2222 +g179 +tp2223 +Rp2224 +(I1 +(I1 +tp2225 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2226 +tp2227 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2228 +Rp2229 +(dp2230 +g201 +g176 +(g177 +(I0 +tp2231 +g179 +tp2232 +Rp2233 +(I1 +(I2 +tp2234 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2235 +tp2236 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp2237 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2238 +g179 +tp2239 +Rp2240 +(I1 +(I1 +I1 +I1 +tp2241 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2242 +tp2243 +bsg238 +g176 +(g177 +(I0 +tp2244 +g179 +tp2245 +Rp2246 +(I1 +(I1 +I1 +I1 +tp2247 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2248 +tp2249 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2250 +g179 +tp2251 +Rp2252 +(I1 +(I1 +I1 +I1 +tp2253 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2254 +tp2255 +bsg252 +g513 +sg48 +(lp2256 +g0 +(g52 +g2 +Ntp2257 +Rp2258 +(dp2259 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp2260 +g179 +tp2261 +Rp2262 +(I1 +(I1 +I1 +I1 +tp2263 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2264 +tp2265 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp2266 +g664 +asg113 +I10062 +sg280 +I01 +sbaa(lp2267 +g666 +ag0 +(g190 +g2 +Ntp2268 +Rp2269 +(dp2270 +g194 +I01 +sg195 +(lp2271 +g0 +(g197 +g2 +Ntp2272 +Rp2273 +(dp2274 +g201 +g176 +(g177 +(I0 +tp2275 +g179 +tp2276 +Rp2277 +(I1 +(I1 +tp2278 +g208 +I00 +S"\x13'\x00\x00\x00\x00\x00\x00" +p2279 +tp2280 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2281 +Rp2282 +(dp2283 +g201 +g176 +(g177 +(I0 +tp2284 +g179 +tp2285 +Rp2286 +(I1 +(I2 +tp2287 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2288 +tp2289 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp2290 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2291 +g179 +tp2292 +Rp2293 +(I1 +(I1 +I1 +I1 +tp2294 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2295 +tp2296 +bsg238 +g176 +(g177 +(I0 +tp2297 +g179 +tp2298 +Rp2299 +(I1 +(I1 +I1 +I1 +tp2300 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2301 +tp2302 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2303 +g179 +tp2304 +Rp2305 +(I1 +(I1 +I1 +I1 +tp2306 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2307 +tp2308 +bsg252 +g713 +sg48 +(lp2309 +g0 +(g52 +g2 +Ntp2310 +Rp2311 +(dp2312 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp2313 +g179 +tp2314 +Rp2315 +(I1 +(I1 +I1 +I1 +tp2316 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p2317 +tp2318 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp2319 +g727 +asg113 +I10063 +sg280 +I01 +sbaatp2320 +Rp2321 +sg337 +I00 +sg338 +Nsbaatp2322 +Rp2323 +aa(lp2324 +I10004 +ag7 +((lp2325 +(lp2326 +g12 +ag0 +(g13 +g2 +Ntp2327 +Rp2328 +(dp2329 +g17 +g0 +(g18 +g2 +Ntp2330 +Rp2331 +(dp2332 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p2333 +sg116 +g0 +(g117 +g2 +Ntp2334 +Rp2335 +(dp2336 +g121 +(lp2337 +g0 +(g123 +g2 +Ntp2338 +Rp2339 +(dp2340 +g127 +g0 +(g128 +g2 +Ntp2341 +Rp2342 +(dp2343 +g23 +g132 +sg133 +(dp2344 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xe9?' +p2345 +tp2346 +Rp2347 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p2348 +sg113 +I11 +sg146 +(lp2349 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp2350 +Rp2351 +(dp2352 +g127 +g0 +(g128 +g2 +Ntp2353 +Rp2354 +(dp2355 +g23 +g132 +sg133 +(dp2356 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xe8?' +p2357 +tp2358 +Rp2359 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p2360 +sg113 +I12 +sg146 +(lp2361 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10004 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2362 +(lp2363 +g189 +ag0 +(g190 +g2 +Ntp2364 +Rp2365 +(dp2366 +g194 +I01 +sg195 +(lp2367 +g0 +(g197 +g2 +Ntp2368 +Rp2369 +(dp2370 +g201 +g176 +(g177 +(I0 +tp2371 +g179 +tp2372 +Rp2373 +(I1 +(I1 +tp2374 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2375 +tp2376 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2377 +Rp2378 +(dp2379 +g201 +g176 +(g177 +(I0 +tp2380 +g179 +tp2381 +Rp2382 +(I1 +(I2 +tp2383 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2384 +tp2385 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2386 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2387 +g179 +tp2388 +Rp2389 +(I1 +(I1 +I1 +I1 +tp2390 +g38 +I00 +S'y-\x89\xfc\xb6d8@' +p2391 +tp2392 +bsg238 +g176 +(g177 +(I0 +tp2393 +g179 +tp2394 +Rp2395 +(I1 +(I1 +I1 +I1 +tp2396 +g38 +I00 +S'\x16C.Zu\xa8B?' +p2397 +tp2398 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2399 +g179 +tp2400 +Rp2401 +(I1 +(I1 +I1 +I1 +tp2402 +g38 +I00 +S'\x9e\x08\x0e\x9f\xa2\xa8\xe0?' +p2403 +tp2404 +bsg252 +g260 +sg48 +(lp2405 +g0 +(g52 +g2 +Ntp2406 +Rp2407 +(dp2408 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2409 +g179 +tp2410 +Rp2411 +(I1 +(I1 +I1 +I1 +tp2412 +g38 +I00 +S'\x1e\xbc\xab\xaf$mG@' +p2413 +tp2414 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2415 +g279 +asg113 +I10066 +sg280 +I01 +sbaa(lp2416 +g12 +ag0 +(g190 +g2 +Ntp2417 +Rp2418 +(dp2419 +g194 +I01 +sg195 +(lp2420 +g0 +(g197 +g2 +Ntp2421 +Rp2422 +(dp2423 +g201 +g176 +(g177 +(I0 +tp2424 +g179 +tp2425 +Rp2426 +(I1 +(I1 +tp2427 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2428 +tp2429 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2430 +Rp2431 +(dp2432 +g201 +g176 +(g177 +(I0 +tp2433 +g179 +tp2434 +Rp2435 +(I1 +(I2 +tp2436 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2437 +tp2438 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2439 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2440 +g179 +tp2441 +Rp2442 +(I1 +(I1 +I1 +I1 +tp2443 +g38 +I00 +S'\x03\x13\xac\xd3\xc8\x80\x0f@' +p2444 +tp2445 +bsg238 +g176 +(g177 +(I0 +tp2446 +g179 +tp2447 +Rp2448 +(I1 +(I1 +I1 +I1 +tp2449 +g38 +I00 +S'\xfcM\x0b\xc3\xe3Z/?' +p2450 +tp2451 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2452 +g179 +tp2453 +Rp2454 +(I1 +(I1 +I1 +I1 +tp2455 +g38 +I00 +S'I\xc8vv\xda\xc5\xca?' +p2456 +tp2457 +bsg252 +g260 +sg48 +(lp2458 +g0 +(g52 +g2 +Ntp2459 +Rp2460 +(dp2461 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2462 +g179 +tp2463 +Rp2464 +(I1 +(I1 +I1 +I1 +tp2465 +g38 +I00 +S'\xd3\x84K\x9b\x1d\xd32@' +p2466 +tp2467 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2468 +g334 +asg113 +I10067 +sg280 +I01 +sbaatp2469 +Rp2470 +sg337 +I00 +sg338 +Nsbaa(lp2471 +g340 +ag0 +(g341 +g2 +Ntp2472 +Rp2473 +(dp2474 +g17 +g2331 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2475 +(lp2476 +g189 +ag0 +(g190 +g2 +Ntp2477 +Rp2478 +(dp2479 +g194 +I01 +sg195 +(lp2480 +g0 +(g197 +g2 +Ntp2481 +Rp2482 +(dp2483 +g201 +g176 +(g177 +(I0 +tp2484 +g179 +tp2485 +Rp2486 +(I1 +(I1 +tp2487 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2488 +tp2489 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2490 +Rp2491 +(dp2492 +g201 +g176 +(g177 +(I0 +tp2493 +g179 +tp2494 +Rp2495 +(I1 +(I2 +tp2496 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2497 +tp2498 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2499 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2500 +g179 +tp2501 +Rp2502 +(I1 +(I1 +I1 +I1 +tp2503 +g38 +I00 +S'y-\x89\xfc\xb6d8@' +p2504 +tp2505 +bsg238 +g176 +(g177 +(I0 +tp2506 +g179 +tp2507 +Rp2508 +(I1 +(I1 +I1 +I1 +tp2509 +g38 +I00 +S'\x16C.Zu\xa8B?' +p2510 +tp2511 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2512 +g179 +tp2513 +Rp2514 +(I1 +(I1 +I1 +I1 +tp2515 +g38 +I00 +S'\x9e\x08\x0e\x9f\xa2\xa8\xe0?' +p2516 +tp2517 +bsg252 +g260 +sg48 +(lp2518 +g0 +(g52 +g2 +Ntp2519 +Rp2520 +(dp2521 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2522 +g179 +tp2523 +Rp2524 +(I1 +(I1 +I1 +I1 +tp2525 +g38 +I00 +S'\x1e\xbc\xab\xaf$mG@' +p2526 +tp2527 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2528 +g279 +asg113 +I10070 +sg280 +I01 +sbaa(lp2529 +g401 +ag0 +(g190 +g2 +Ntp2530 +Rp2531 +(dp2532 +g194 +I01 +sg195 +(lp2533 +g0 +(g197 +g2 +Ntp2534 +Rp2535 +(dp2536 +g201 +g176 +(g177 +(I0 +tp2537 +g179 +tp2538 +Rp2539 +(I1 +(I1 +tp2540 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2541 +tp2542 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2543 +Rp2544 +(dp2545 +g201 +g176 +(g177 +(I0 +tp2546 +g179 +tp2547 +Rp2548 +(I1 +(I2 +tp2549 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2550 +tp2551 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2552 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2553 +g179 +tp2554 +Rp2555 +(I1 +(I1 +I1 +I1 +tp2556 +g38 +I00 +S'r"O\x0c$\xdc\xa2?' +p2557 +tp2558 +bsg238 +g176 +(g177 +(I0 +tp2559 +g179 +tp2560 +Rp2561 +(I1 +(I1 +I1 +I1 +tp2562 +g38 +I00 +S'\xd7\x88\x06\xc7\xbf\x89\x06?' +p2563 +tp2564 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2565 +g179 +tp2566 +Rp2567 +(I1 +(I1 +I1 +I1 +tp2568 +g38 +I00 +S'\x0b\xd48YS\xb6\x94?' +p2569 +tp2570 +bsg252 +g260 +sg48 +(lp2571 +g0 +(g52 +g2 +Ntp2572 +Rp2573 +(dp2574 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2575 +g179 +tp2576 +Rp2577 +(I1 +(I1 +I1 +I1 +tp2578 +g38 +I00 +S'/\xeaw5e \xfd?' +p2579 +tp2580 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2581 +g454 +asg113 +I10071 +sg280 +I01 +sbaatp2582 +Rp2583 +sg337 +I00 +sg338 +Nsbaa(lp2584 +g458 +ag0 +(g459 +g2 +Ntp2585 +Rp2586 +(dp2587 +g17 +g2331 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2588 +(lp2589 +g189 +ag0 +(g190 +g2 +Ntp2590 +Rp2591 +(dp2592 +g194 +I01 +sg195 +(lp2593 +g0 +(g197 +g2 +Ntp2594 +Rp2595 +(dp2596 +g201 +g176 +(g177 +(I0 +tp2597 +g179 +tp2598 +Rp2599 +(I1 +(I1 +tp2600 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2601 +tp2602 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2603 +Rp2604 +(dp2605 +g201 +g176 +(g177 +(I0 +tp2606 +g179 +tp2607 +Rp2608 +(I1 +(I2 +tp2609 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2610 +tp2611 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp2612 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2613 +g179 +tp2614 +Rp2615 +(I1 +(I1 +I1 +I1 +tp2616 +g38 +I00 +S'?/\xc9S\x8fM8@' +p2617 +tp2618 +bsg238 +g176 +(g177 +(I0 +tp2619 +g179 +tp2620 +Rp2621 +(I1 +(I1 +I1 +I1 +tp2622 +g38 +I00 +S']@\x1f\x1bd\xfaY?' +p2623 +tp2624 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2625 +g179 +tp2626 +Rp2627 +(I1 +(I1 +I1 +I1 +tp2628 +g38 +I00 +S'2\xfb\xe1\x1a/\x9f\xe0?' +p2629 +tp2630 +bsg252 +g513 +sg48 +(lp2631 +g0 +(g52 +g2 +Ntp2632 +Rp2633 +(dp2634 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp2635 +g179 +tp2636 +Rp2637 +(I1 +(I1 +I1 +I1 +tp2638 +g38 +I00 +S'>\xc9\xcd=\xda_G@' +p2639 +tp2640 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp2641 +g527 +asg113 +I10074 +sg280 +I01 +sbaa(lp2642 +g529 +ag0 +(g190 +g2 +Ntp2643 +Rp2644 +(dp2645 +g194 +I01 +sg195 +(lp2646 +g0 +(g197 +g2 +Ntp2647 +Rp2648 +(dp2649 +g201 +g176 +(g177 +(I0 +tp2650 +g179 +tp2651 +Rp2652 +(I1 +(I1 +tp2653 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2654 +tp2655 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2656 +Rp2657 +(dp2658 +g201 +g176 +(g177 +(I0 +tp2659 +g179 +tp2660 +Rp2661 +(I1 +(I2 +tp2662 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2663 +tp2664 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2665 +Rp2666 +(dp2667 +g201 +g176 +(g177 +(I0 +tp2668 +g179 +tp2669 +Rp2670 +(I1 +(I2 +tp2671 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2672 +tp2673 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp2674 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2675 +g179 +tp2676 +Rp2677 +(I1 +(I1 +I1 +I1 +tp2678 +g38 +I00 +S'U\xe3\x08\xc6\x7fI\x0b@' +p2679 +tp2680 +bsg238 +g176 +(g177 +(I0 +tp2681 +g179 +tp2682 +Rp2683 +(I1 +(I1 +I1 +I1 +tp2684 +g38 +I00 +S'\xd4C!\xb8\xbe+C?' +p2685 +tp2686 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2687 +g179 +tp2688 +Rp2689 +(I1 +(I1 +I1 +I1 +tp2690 +g38 +I00 +S'\xb5\x04\xb7y\x94\xe8\xc8?' +p2691 +tp2692 +bsg252 +g586 +sg48 +(lp2693 +g0 +(g52 +g2 +Ntp2694 +Rp2695 +(dp2696 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp2697 +g179 +tp2698 +Rp2699 +(I1 +(I1 +I1 +I1 +tp2700 +g38 +I00 +S'O\xaf\x94e\x88\x831@' +p2701 +tp2702 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp2703 +g600 +asg113 +I10075 +sg280 +I01 +sbaatp2704 +Rp2705 +sg337 +I00 +sg338 +Nsbaa(lp2706 +g604 +ag0 +(g605 +g2 +Ntp2707 +Rp2708 +(dp2709 +g17 +g2331 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2710 +(lp2711 +g611 +ag0 +(g190 +g2 +Ntp2712 +Rp2713 +(dp2714 +g194 +I01 +sg195 +(lp2715 +g0 +(g197 +g2 +Ntp2716 +Rp2717 +(dp2718 +g201 +g176 +(g177 +(I0 +tp2719 +g179 +tp2720 +Rp2721 +(I1 +(I1 +tp2722 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2723 +tp2724 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2725 +Rp2726 +(dp2727 +g201 +g176 +(g177 +(I0 +tp2728 +g179 +tp2729 +Rp2730 +(I1 +(I2 +tp2731 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2732 +tp2733 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp2734 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2735 +g179 +tp2736 +Rp2737 +(I1 +(I1 +I1 +I1 +tp2738 +g38 +I00 +S'{\x08\x0c\xd8\xc5\x05\xa3?' +p2739 +tp2740 +bsg238 +g176 +(g177 +(I0 +tp2741 +g179 +tp2742 +Rp2743 +(I1 +(I1 +I1 +I1 +tp2744 +g38 +I00 +S"0\xa9\xed\xe2\xd5$'?" +p2745 +tp2746 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2747 +g179 +tp2748 +Rp2749 +(I1 +(I1 +I1 +I1 +tp2750 +g38 +I00 +S'\x12*\x83\xaeF\xbc\x94?' +p2751 +tp2752 +bsg252 +g513 +sg48 +(lp2753 +g0 +(g52 +g2 +Ntp2754 +Rp2755 +(dp2756 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp2757 +g179 +tp2758 +Rp2759 +(I1 +(I1 +I1 +I1 +tp2760 +g38 +I00 +S')she\xc3(\xfd?' +p2761 +tp2762 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp2763 +g664 +asg113 +I10078 +sg280 +I01 +sbaa(lp2764 +g666 +ag0 +(g190 +g2 +Ntp2765 +Rp2766 +(dp2767 +g194 +I01 +sg195 +(lp2768 +g0 +(g197 +g2 +Ntp2769 +Rp2770 +(dp2771 +g201 +g176 +(g177 +(I0 +tp2772 +g179 +tp2773 +Rp2774 +(I1 +(I1 +tp2775 +g208 +I00 +S"\x14'\x00\x00\x00\x00\x00\x00" +p2776 +tp2777 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2778 +Rp2779 +(dp2780 +g201 +g176 +(g177 +(I0 +tp2781 +g179 +tp2782 +Rp2783 +(I1 +(I2 +tp2784 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2785 +tp2786 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp2787 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2788 +g179 +tp2789 +Rp2790 +(I1 +(I1 +I1 +I1 +tp2791 +g38 +I00 +S'|\x08\x0c\xd8\xc5\x05\xa3?' +p2792 +tp2793 +bsg238 +g176 +(g177 +(I0 +tp2794 +g179 +tp2795 +Rp2796 +(I1 +(I1 +I1 +I1 +tp2797 +g38 +I00 +S"n\xaa\xed\xe2\xd5$'?" +p2798 +tp2799 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2800 +g179 +tp2801 +Rp2802 +(I1 +(I1 +I1 +I1 +tp2803 +g38 +I00 +S'\x11*\x83\xaeF\xbc\x94?' +p2804 +tp2805 +bsg252 +g713 +sg48 +(lp2806 +g0 +(g52 +g2 +Ntp2807 +Rp2808 +(dp2809 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp2810 +g179 +tp2811 +Rp2812 +(I1 +(I1 +I1 +I1 +tp2813 +g38 +I00 +S'(she\xc3(\xfd?' +p2814 +tp2815 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp2816 +g727 +asg113 +I10079 +sg280 +I01 +sbaatp2817 +Rp2818 +sg337 +I00 +sg338 +Nsbaatp2819 +Rp2820 +aa(lp2821 +I10005 +ag7 +((lp2822 +(lp2823 +g12 +ag0 +(g13 +g2 +Ntp2824 +Rp2825 +(dp2826 +g17 +g0 +(g18 +g2 +Ntp2827 +Rp2828 +(dp2829 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p2830 +sg116 +g0 +(g117 +g2 +Ntp2831 +Rp2832 +(dp2833 +g121 +(lp2834 +g0 +(g123 +g2 +Ntp2835 +Rp2836 +(dp2837 +g127 +g0 +(g128 +g2 +Ntp2838 +Rp2839 +(dp2840 +g23 +g132 +sg133 +(dp2841 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xf2?' +p2842 +tp2843 +Rp2844 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p2845 +sg113 +I13 +sg146 +(lp2846 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp2847 +Rp2848 +(dp2849 +g127 +g0 +(g128 +g2 +Ntp2850 +Rp2851 +(dp2852 +g23 +g132 +sg133 +(dp2853 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xf1?' +p2854 +tp2855 +Rp2856 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p2857 +sg113 +I14 +sg146 +(lp2858 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10005 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2859 +(lp2860 +g189 +ag0 +(g190 +g2 +Ntp2861 +Rp2862 +(dp2863 +g194 +I01 +sg195 +(lp2864 +g0 +(g197 +g2 +Ntp2865 +Rp2866 +(dp2867 +g201 +g176 +(g177 +(I0 +tp2868 +g179 +tp2869 +Rp2870 +(I1 +(I1 +tp2871 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p2872 +tp2873 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2874 +Rp2875 +(dp2876 +g201 +g176 +(g177 +(I0 +tp2877 +g179 +tp2878 +Rp2879 +(I1 +(I2 +tp2880 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2881 +tp2882 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2883 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2884 +g179 +tp2885 +Rp2886 +(I1 +(I1 +I1 +I1 +tp2887 +g38 +I00 +S'\xd4\x9a\x83Z\x91\x848@' +p2888 +tp2889 +bsg238 +g176 +(g177 +(I0 +tp2890 +g179 +tp2891 +Rp2892 +(I1 +(I1 +I1 +I1 +tp2893 +g38 +I00 +S'{\xc9e\xa0w\x06C?' +p2894 +tp2895 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2896 +g179 +tp2897 +Rp2898 +(I1 +(I1 +I1 +I1 +tp2899 +g38 +I00 +S'\x83B%u}\xb3\xe0?' +p2900 +tp2901 +bsg252 +g260 +sg48 +(lp2902 +g0 +(g52 +g2 +Ntp2903 +Rp2904 +(dp2905 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2906 +g179 +tp2907 +Rp2908 +(I1 +(I1 +I1 +I1 +tp2909 +g38 +I00 +S'\x88e\xbclh|G@' +p2910 +tp2911 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2912 +g279 +asg113 +I10082 +sg280 +I01 +sbaa(lp2913 +g12 +ag0 +(g190 +g2 +Ntp2914 +Rp2915 +(dp2916 +g194 +I01 +sg195 +(lp2917 +g0 +(g197 +g2 +Ntp2918 +Rp2919 +(dp2920 +g201 +g176 +(g177 +(I0 +tp2921 +g179 +tp2922 +Rp2923 +(I1 +(I1 +tp2924 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p2925 +tp2926 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2927 +Rp2928 +(dp2929 +g201 +g176 +(g177 +(I0 +tp2930 +g179 +tp2931 +Rp2932 +(I1 +(I2 +tp2933 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2934 +tp2935 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2936 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2937 +g179 +tp2938 +Rp2939 +(I1 +(I1 +I1 +I1 +tp2940 +g38 +I00 +S'C\x82VR\xf3\x1f\x10@' +p2941 +tp2942 +bsg238 +g176 +(g177 +(I0 +tp2943 +g179 +tp2944 +Rp2945 +(I1 +(I1 +I1 +I1 +tp2946 +g38 +I00 +S'v/\x9dC\x9d\x060?' +p2947 +tp2948 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp2949 +g179 +tp2950 +Rp2951 +(I1 +(I1 +I1 +I1 +tp2952 +g38 +I00 +S'w\n\xb5a\x94\x16\xcb?' +p2953 +tp2954 +bsg252 +g260 +sg48 +(lp2955 +g0 +(g52 +g2 +Ntp2956 +Rp2957 +(dp2958 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp2959 +g179 +tp2960 +Rp2961 +(I1 +(I1 +I1 +I1 +tp2962 +g38 +I00 +S'\\K\xb3T\xe0\x0b3@' +p2963 +tp2964 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp2965 +g334 +asg113 +I10083 +sg280 +I01 +sbaatp2966 +Rp2967 +sg337 +I00 +sg338 +Nsbaa(lp2968 +g340 +ag0 +(g341 +g2 +Ntp2969 +Rp2970 +(dp2971 +g17 +g2828 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp2972 +(lp2973 +g189 +ag0 +(g190 +g2 +Ntp2974 +Rp2975 +(dp2976 +g194 +I01 +sg195 +(lp2977 +g0 +(g197 +g2 +Ntp2978 +Rp2979 +(dp2980 +g201 +g176 +(g177 +(I0 +tp2981 +g179 +tp2982 +Rp2983 +(I1 +(I1 +tp2984 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p2985 +tp2986 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp2987 +Rp2988 +(dp2989 +g201 +g176 +(g177 +(I0 +tp2990 +g179 +tp2991 +Rp2992 +(I1 +(I2 +tp2993 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p2994 +tp2995 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp2996 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp2997 +g179 +tp2998 +Rp2999 +(I1 +(I1 +I1 +I1 +tp3000 +g38 +I00 +S'\xd4\x9a\x83Z\x91\x848@' +p3001 +tp3002 +bsg238 +g176 +(g177 +(I0 +tp3003 +g179 +tp3004 +Rp3005 +(I1 +(I1 +I1 +I1 +tp3006 +g38 +I00 +S'{\xc9e\xa0w\x06C?' +p3007 +tp3008 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3009 +g179 +tp3010 +Rp3011 +(I1 +(I1 +I1 +I1 +tp3012 +g38 +I00 +S'\x83B%u}\xb3\xe0?' +p3013 +tp3014 +bsg252 +g260 +sg48 +(lp3015 +g0 +(g52 +g2 +Ntp3016 +Rp3017 +(dp3018 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3019 +g179 +tp3020 +Rp3021 +(I1 +(I1 +I1 +I1 +tp3022 +g38 +I00 +S'\x88e\xbclh|G@' +p3023 +tp3024 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3025 +g279 +asg113 +I10086 +sg280 +I01 +sbaa(lp3026 +g401 +ag0 +(g190 +g2 +Ntp3027 +Rp3028 +(dp3029 +g194 +I01 +sg195 +(lp3030 +g0 +(g197 +g2 +Ntp3031 +Rp3032 +(dp3033 +g201 +g176 +(g177 +(I0 +tp3034 +g179 +tp3035 +Rp3036 +(I1 +(I1 +tp3037 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p3038 +tp3039 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3040 +Rp3041 +(dp3042 +g201 +g176 +(g177 +(I0 +tp3043 +g179 +tp3044 +Rp3045 +(I1 +(I2 +tp3046 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3047 +tp3048 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3049 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3050 +g179 +tp3051 +Rp3052 +(I1 +(I1 +I1 +I1 +tp3053 +g38 +I00 +S'\xf7a\xb55\xeeW\xa8?' +p3054 +tp3055 +bsg238 +g176 +(g177 +(I0 +tp3056 +g179 +tp3057 +Rp3058 +(I1 +(I1 +I1 +I1 +tp3059 +g38 +I00 +S'\xa5\xf8\xe1\xe5\xf1\x8c\x0c?' +p3060 +tp3061 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3062 +g179 +tp3063 +Rp3064 +(I1 +(I1 +I1 +I1 +tp3065 +g38 +I00 +S'6\xe3\x8dk\xbe\x87\x97?' +p3066 +tp3067 +bsg252 +g260 +sg48 +(lp3068 +g0 +(g52 +g2 +Ntp3069 +Rp3070 +(dp3071 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3072 +g179 +tp3073 +Rp3074 +(I1 +(I1 +I1 +I1 +tp3075 +g38 +I00 +S'\xc2\xc3\x9f\xe3q\x8b\x00@' +p3076 +tp3077 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3078 +g454 +asg113 +I10087 +sg280 +I01 +sbaatp3079 +Rp3080 +sg337 +I00 +sg338 +Nsbaa(lp3081 +g458 +ag0 +(g459 +g2 +Ntp3082 +Rp3083 +(dp3084 +g17 +g2828 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3085 +(lp3086 +g189 +ag0 +(g190 +g2 +Ntp3087 +Rp3088 +(dp3089 +g194 +I01 +sg195 +(lp3090 +g0 +(g197 +g2 +Ntp3091 +Rp3092 +(dp3093 +g201 +g176 +(g177 +(I0 +tp3094 +g179 +tp3095 +Rp3096 +(I1 +(I1 +tp3097 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p3098 +tp3099 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3100 +Rp3101 +(dp3102 +g201 +g176 +(g177 +(I0 +tp3103 +g179 +tp3104 +Rp3105 +(I1 +(I2 +tp3106 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3107 +tp3108 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp3109 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3110 +g179 +tp3111 +Rp3112 +(I1 +(I1 +I1 +I1 +tp3113 +g38 +I00 +S'\xe0\x82A\x94F\x7f8@' +p3114 +tp3115 +bsg238 +g176 +(g177 +(I0 +tp3116 +g179 +tp3117 +Rp3118 +(I1 +(I1 +I1 +I1 +tp3119 +g38 +I00 +S'\x1d;\xf1\xdd\xbdxT?' +p3120 +tp3121 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3122 +g179 +tp3123 +Rp3124 +(I1 +(I1 +I1 +I1 +tp3125 +g38 +I00 +S'\xe9\x83O\xe2\xd4\xb0\xe0?' +p3126 +tp3127 +bsg252 +g513 +sg48 +(lp3128 +g0 +(g52 +g2 +Ntp3129 +Rp3130 +(dp3131 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp3132 +g179 +tp3133 +Rp3134 +(I1 +(I1 +I1 +I1 +tp3135 +g38 +I00 +S'\x80\xd1?^\xabxG@' +p3136 +tp3137 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp3138 +g527 +asg113 +I10090 +sg280 +I01 +sbaa(lp3139 +g529 +ag0 +(g190 +g2 +Ntp3140 +Rp3141 +(dp3142 +g194 +I01 +sg195 +(lp3143 +g0 +(g197 +g2 +Ntp3144 +Rp3145 +(dp3146 +g201 +g176 +(g177 +(I0 +tp3147 +g179 +tp3148 +Rp3149 +(I1 +(I1 +tp3150 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p3151 +tp3152 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3153 +Rp3154 +(dp3155 +g201 +g176 +(g177 +(I0 +tp3156 +g179 +tp3157 +Rp3158 +(I1 +(I2 +tp3159 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3160 +tp3161 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3162 +Rp3163 +(dp3164 +g201 +g176 +(g177 +(I0 +tp3165 +g179 +tp3166 +Rp3167 +(I1 +(I2 +tp3168 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3169 +tp3170 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp3171 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3172 +g179 +tp3173 +Rp3174 +(I1 +(I1 +I1 +I1 +tp3175 +g38 +I00 +S'5\xd6\x1f\xdd\xdf\x9b\x0b@' +p3176 +tp3177 +bsg238 +g176 +(g177 +(I0 +tp3178 +g179 +tp3179 +Rp3180 +(I1 +(I1 +I1 +I1 +tp3181 +g38 +I00 +S'\xce\xa4\xbd\xb0\x1b\xe6??' +p3182 +tp3183 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3184 +g179 +tp3185 +Rp3186 +(I1 +(I1 +I1 +I1 +tp3187 +g38 +I00 +S'by}\xd3\xe1\x0e\xc9?' +p3188 +tp3189 +bsg252 +g586 +sg48 +(lp3190 +g0 +(g52 +g2 +Ntp3191 +Rp3192 +(dp3193 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp3194 +g179 +tp3195 +Rp3196 +(I1 +(I1 +I1 +I1 +tp3197 +g38 +I00 +S'Y9\xb4\xc8v\x9e1@' +p3198 +tp3199 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp3200 +g600 +asg113 +I10091 +sg280 +I01 +sbaatp3201 +Rp3202 +sg337 +I00 +sg338 +Nsbaa(lp3203 +g604 +ag0 +(g605 +g2 +Ntp3204 +Rp3205 +(dp3206 +g17 +g2828 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3207 +(lp3208 +g611 +ag0 +(g190 +g2 +Ntp3209 +Rp3210 +(dp3211 +g194 +I01 +sg195 +(lp3212 +g0 +(g197 +g2 +Ntp3213 +Rp3214 +(dp3215 +g201 +g176 +(g177 +(I0 +tp3216 +g179 +tp3217 +Rp3218 +(I1 +(I1 +tp3219 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p3220 +tp3221 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3222 +Rp3223 +(dp3224 +g201 +g176 +(g177 +(I0 +tp3225 +g179 +tp3226 +Rp3227 +(I1 +(I2 +tp3228 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3229 +tp3230 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp3231 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3232 +g179 +tp3233 +Rp3234 +(I1 +(I1 +I1 +I1 +tp3235 +g38 +I00 +S'\n\n\xcf:\xc2\xcd\xa7?' +p3236 +tp3237 +bsg238 +g176 +(g177 +(I0 +tp3238 +g179 +tp3239 +Rp3240 +(I1 +(I1 +I1 +I1 +tp3241 +g38 +I00 +S'|\xb9R\x1b2\xe1*?' +p3242 +tp3243 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3244 +g179 +tp3245 +Rp3246 +(I1 +(I1 +I1 +I1 +tp3247 +g38 +I00 +S"\x11w'\x8et0\x97?" +p3248 +tp3249 +bsg252 +g513 +sg48 +(lp3250 +g0 +(g52 +g2 +Ntp3251 +Rp3252 +(dp3253 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp3254 +g179 +tp3255 +Rp3256 +(I1 +(I1 +I1 +I1 +tp3257 +g38 +I00 +S'\xb8\xbf\xf3\xf3\x11N\x00@' +p3258 +tp3259 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp3260 +g664 +asg113 +I10094 +sg280 +I01 +sbaa(lp3261 +g666 +ag0 +(g190 +g2 +Ntp3262 +Rp3263 +(dp3264 +g194 +I01 +sg195 +(lp3265 +g0 +(g197 +g2 +Ntp3266 +Rp3267 +(dp3268 +g201 +g176 +(g177 +(I0 +tp3269 +g179 +tp3270 +Rp3271 +(I1 +(I1 +tp3272 +g208 +I00 +S"\x15'\x00\x00\x00\x00\x00\x00" +p3273 +tp3274 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3275 +Rp3276 +(dp3277 +g201 +g176 +(g177 +(I0 +tp3278 +g179 +tp3279 +Rp3280 +(I1 +(I2 +tp3281 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3282 +tp3283 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp3284 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3285 +g179 +tp3286 +Rp3287 +(I1 +(I1 +I1 +I1 +tp3288 +g38 +I00 +S'\n\n\xcf:\xc2\xcd\xa7?' +p3289 +tp3290 +bsg238 +g176 +(g177 +(I0 +tp3291 +g179 +tp3292 +Rp3293 +(I1 +(I1 +I1 +I1 +tp3294 +g38 +I00 +S'\xa1\xb8R\x1b2\xe1*?' +p3295 +tp3296 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3297 +g179 +tp3298 +Rp3299 +(I1 +(I1 +I1 +I1 +tp3300 +g38 +I00 +S"\x12w'\x8et0\x97?" +p3301 +tp3302 +bsg252 +g713 +sg48 +(lp3303 +g0 +(g52 +g2 +Ntp3304 +Rp3305 +(dp3306 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp3307 +g179 +tp3308 +Rp3309 +(I1 +(I1 +I1 +I1 +tp3310 +g38 +I00 +S'\xb9\xbf\xf3\xf3\x11N\x00@' +p3311 +tp3312 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp3313 +g727 +asg113 +I10095 +sg280 +I01 +sbaatp3314 +Rp3315 +sg337 +I00 +sg338 +Nsbaatp3316 +Rp3317 +aa(lp3318 +I10006 +ag7 +((lp3319 +(lp3320 +g12 +ag0 +(g13 +g2 +Ntp3321 +Rp3322 +(dp3323 +g17 +g0 +(g18 +g2 +Ntp3324 +Rp3325 +(dp3326 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p3327 +sg116 +g0 +(g117 +g2 +Ntp3328 +Rp3329 +(dp3330 +g121 +(lp3331 +g0 +(g123 +g2 +Ntp3332 +Rp3333 +(dp3334 +g127 +g0 +(g128 +g2 +Ntp3335 +Rp3336 +(dp3337 +g23 +g132 +sg133 +(dp3338 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00@' +p3339 +tp3340 +Rp3341 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p3342 +sg113 +I1 +sg146 +(lp3343 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp3344 +Rp3345 +(dp3346 +g127 +g0 +(g128 +g2 +Ntp3347 +Rp3348 +(dp3349 +g23 +g132 +sg133 +(dp3350 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xff?' +p3351 +tp3352 +Rp3353 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p3354 +sg113 +I15 +sg146 +(lp3355 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10006 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3356 +(lp3357 +g189 +ag0 +(g190 +g2 +Ntp3358 +Rp3359 +(dp3360 +g194 +I01 +sg195 +(lp3361 +g0 +(g197 +g2 +Ntp3362 +Rp3363 +(dp3364 +g201 +g176 +(g177 +(I0 +tp3365 +g179 +tp3366 +Rp3367 +(I1 +(I1 +tp3368 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3369 +tp3370 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3371 +Rp3372 +(dp3373 +g201 +g176 +(g177 +(I0 +tp3374 +g179 +tp3375 +Rp3376 +(I1 +(I2 +tp3377 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3378 +tp3379 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3380 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3381 +g179 +tp3382 +Rp3383 +(I1 +(I1 +I1 +I1 +tp3384 +g38 +I00 +S'\xb9\xeb_L\x13}8@' +p3385 +tp3386 +bsg238 +g176 +(g177 +(I0 +tp3387 +g179 +tp3388 +Rp3389 +(I1 +(I1 +I1 +I1 +tp3390 +g38 +I00 +S')#T(q\x15A?' +p3391 +tp3392 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3393 +g179 +tp3394 +Rp3395 +(I1 +(I1 +I1 +I1 +tp3396 +g38 +I00 +S'\x8e\xef]\x99\xfb\xb0\xe0?' +p3397 +tp3398 +bsg252 +g260 +sg48 +(lp3399 +g0 +(g52 +g2 +Ntp3400 +Rp3401 +(dp3402 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3403 +g179 +tp3404 +Rp3405 +(I1 +(I1 +I1 +I1 +tp3406 +g38 +I00 +S'\xdf\x18\xac\xcf\xe1xG@' +p3407 +tp3408 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3409 +g279 +asg113 +I10098 +sg280 +I01 +sbaa(lp3410 +g12 +ag0 +(g190 +g2 +Ntp3411 +Rp3412 +(dp3413 +g194 +I01 +sg195 +(lp3414 +g0 +(g197 +g2 +Ntp3415 +Rp3416 +(dp3417 +g201 +g176 +(g177 +(I0 +tp3418 +g179 +tp3419 +Rp3420 +(I1 +(I1 +tp3421 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3422 +tp3423 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3424 +Rp3425 +(dp3426 +g201 +g176 +(g177 +(I0 +tp3427 +g179 +tp3428 +Rp3429 +(I1 +(I2 +tp3430 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3431 +tp3432 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3433 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3434 +g179 +tp3435 +Rp3436 +(I1 +(I1 +I1 +I1 +tp3437 +g38 +I00 +S'\xccM`\xe3 \x95\x14@' +p3438 +tp3439 +bsg238 +g176 +(g177 +(I0 +tp3440 +g179 +tp3441 +Rp3442 +(I1 +(I1 +I1 +I1 +tp3443 +g38 +I00 +S'\xcd\xb6\xefy/P2?' +p3444 +tp3445 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3446 +g179 +tp3447 +Rp3448 +(I1 +(I1 +I1 +I1 +tp3449 +g38 +I00 +S'.\x87\x7f\x18\xb0\x9a\xce?' +p3450 +tp3451 +bsg252 +g260 +sg48 +(lp3452 +g0 +(g52 +g2 +Ntp3453 +Rp3454 +(dp3455 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3456 +g179 +tp3457 +Rp3458 +(I1 +(I1 +I1 +I1 +tp3459 +g38 +I00 +S'\x0c\xab9\xd1\xc3\x845@' +p3460 +tp3461 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3462 +g334 +asg113 +I10099 +sg280 +I01 +sbaatp3463 +Rp3464 +sg337 +I00 +sg338 +Nsbaa(lp3465 +g340 +ag0 +(g341 +g2 +Ntp3466 +Rp3467 +(dp3468 +g17 +g3325 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3469 +(lp3470 +g189 +ag0 +(g190 +g2 +Ntp3471 +Rp3472 +(dp3473 +g194 +I01 +sg195 +(lp3474 +g0 +(g197 +g2 +Ntp3475 +Rp3476 +(dp3477 +g201 +g176 +(g177 +(I0 +tp3478 +g179 +tp3479 +Rp3480 +(I1 +(I1 +tp3481 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3482 +tp3483 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3484 +Rp3485 +(dp3486 +g201 +g176 +(g177 +(I0 +tp3487 +g179 +tp3488 +Rp3489 +(I1 +(I2 +tp3490 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3491 +tp3492 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3493 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3494 +g179 +tp3495 +Rp3496 +(I1 +(I1 +I1 +I1 +tp3497 +g38 +I00 +S'\xb9\xeb_L\x13}8@' +p3498 +tp3499 +bsg238 +g176 +(g177 +(I0 +tp3500 +g179 +tp3501 +Rp3502 +(I1 +(I1 +I1 +I1 +tp3503 +g38 +I00 +S')#T(q\x15A?' +p3504 +tp3505 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3506 +g179 +tp3507 +Rp3508 +(I1 +(I1 +I1 +I1 +tp3509 +g38 +I00 +S'\x8e\xef]\x99\xfb\xb0\xe0?' +p3510 +tp3511 +bsg252 +g260 +sg48 +(lp3512 +g0 +(g52 +g2 +Ntp3513 +Rp3514 +(dp3515 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3516 +g179 +tp3517 +Rp3518 +(I1 +(I1 +I1 +I1 +tp3519 +g38 +I00 +S'\xdf\x18\xac\xcf\xe1xG@' +p3520 +tp3521 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3522 +g279 +asg113 +I10102 +sg280 +I01 +sbaa(lp3523 +g401 +ag0 +(g190 +g2 +Ntp3524 +Rp3525 +(dp3526 +g194 +I01 +sg195 +(lp3527 +g0 +(g197 +g2 +Ntp3528 +Rp3529 +(dp3530 +g201 +g176 +(g177 +(I0 +tp3531 +g179 +tp3532 +Rp3533 +(I1 +(I1 +tp3534 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3535 +tp3536 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3537 +Rp3538 +(dp3539 +g201 +g176 +(g177 +(I0 +tp3540 +g179 +tp3541 +Rp3542 +(I1 +(I2 +tp3543 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3544 +tp3545 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3546 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3547 +g179 +tp3548 +Rp3549 +(I1 +(I1 +I1 +I1 +tp3550 +g38 +I00 +S'g\xec%\xe5\xb7\xed\xc2?' +p3551 +tp3552 +bsg238 +g176 +(g177 +(I0 +tp3553 +g179 +tp3554 +Rp3555 +(I1 +(I1 +I1 +I1 +tp3556 +g38 +I00 +S'\xba\xb4\xca\xe3\xe5\x80\x14?' +p3557 +tp3558 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3559 +g179 +tp3560 +Rp3561 +(I1 +(I1 +I1 +I1 +tp3562 +g38 +I00 +S"\xf0\x99\xab\xf0'\xc0\xa4?" +p3563 +tp3564 +bsg252 +g260 +sg48 +(lp3565 +g0 +(g52 +g2 +Ntp3566 +Rp3567 +(dp3568 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3569 +g179 +tp3570 +Rp3571 +(I1 +(I1 +I1 +I1 +tp3572 +g38 +I00 +S'zPq*8.\r@' +p3573 +tp3574 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3575 +g454 +asg113 +I10103 +sg280 +I01 +sbaatp3576 +Rp3577 +sg337 +I00 +sg338 +Nsbaa(lp3578 +g458 +ag0 +(g459 +g2 +Ntp3579 +Rp3580 +(dp3581 +g17 +g3325 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3582 +(lp3583 +g189 +ag0 +(g190 +g2 +Ntp3584 +Rp3585 +(dp3586 +g194 +I01 +sg195 +(lp3587 +g0 +(g197 +g2 +Ntp3588 +Rp3589 +(dp3590 +g201 +g176 +(g177 +(I0 +tp3591 +g179 +tp3592 +Rp3593 +(I1 +(I1 +tp3594 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3595 +tp3596 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3597 +Rp3598 +(dp3599 +g201 +g176 +(g177 +(I0 +tp3600 +g179 +tp3601 +Rp3602 +(I1 +(I2 +tp3603 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3604 +tp3605 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp3606 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3607 +g179 +tp3608 +Rp3609 +(I1 +(I1 +I1 +I1 +tp3610 +g38 +I00 +S'\x17\x94\xe7S\xe8\x9c8@' +p3611 +tp3612 +bsg238 +g176 +(g177 +(I0 +tp3613 +g179 +tp3614 +Rp3615 +(I1 +(I1 +I1 +I1 +tp3616 +g38 +I00 +S'\x10?8\xecfrV?' +p3617 +tp3618 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3619 +g179 +tp3620 +Rp3621 +(I1 +(I1 +I1 +I1 +tp3622 +g38 +I00 +S'$\xad\xb9\xfe\xb2\xba\xe0?' +p3623 +tp3624 +bsg252 +g513 +sg48 +(lp3625 +g0 +(g52 +g2 +Ntp3626 +Rp3627 +(dp3628 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp3629 +g179 +tp3630 +Rp3631 +(I1 +(I1 +I1 +I1 +tp3632 +g38 +I00 +S'z\x1b5\xb6\x8b\x86G@' +p3633 +tp3634 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp3635 +g527 +asg113 +I10106 +sg280 +I01 +sbaa(lp3636 +g529 +ag0 +(g190 +g2 +Ntp3637 +Rp3638 +(dp3639 +g194 +I01 +sg195 +(lp3640 +g0 +(g197 +g2 +Ntp3641 +Rp3642 +(dp3643 +g201 +g176 +(g177 +(I0 +tp3644 +g179 +tp3645 +Rp3646 +(I1 +(I1 +tp3647 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3648 +tp3649 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3650 +Rp3651 +(dp3652 +g201 +g176 +(g177 +(I0 +tp3653 +g179 +tp3654 +Rp3655 +(I1 +(I2 +tp3656 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3657 +tp3658 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3659 +Rp3660 +(dp3661 +g201 +g176 +(g177 +(I0 +tp3662 +g179 +tp3663 +Rp3664 +(I1 +(I2 +tp3665 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3666 +tp3667 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp3668 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3669 +g179 +tp3670 +Rp3671 +(I1 +(I1 +I1 +I1 +tp3672 +g38 +I00 +S'\x0c\xd6\xfe\xef\x04\xd2\x0e@' +p3673 +tp3674 +bsg238 +g176 +(g177 +(I0 +tp3675 +g179 +tp3676 +Rp3677 +(I1 +(I1 +I1 +I1 +tp3678 +g38 +I00 +S'2\x7f\xbbojo@?' +p3679 +tp3680 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3681 +g179 +tp3682 +Rp3683 +(I1 +(I1 +I1 +I1 +tp3684 +g38 +I00 +S'..\xf0Q\xcey\xca?' +p3685 +tp3686 +bsg252 +g586 +sg48 +(lp3687 +g0 +(g52 +g2 +Ntp3688 +Rp3689 +(dp3690 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp3691 +g179 +tp3692 +Rp3693 +(I1 +(I1 +I1 +I1 +tp3694 +g38 +I00 +S'x\xe0\x9c\x11\xa5\x9d2@' +p3695 +tp3696 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp3697 +g600 +asg113 +I10107 +sg280 +I01 +sbaatp3698 +Rp3699 +sg337 +I00 +sg338 +Nsbaa(lp3700 +g604 +ag0 +(g605 +g2 +Ntp3701 +Rp3702 +(dp3703 +g17 +g3325 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3704 +(lp3705 +g611 +ag0 +(g190 +g2 +Ntp3706 +Rp3707 +(dp3708 +g194 +I01 +sg195 +(lp3709 +g0 +(g197 +g2 +Ntp3710 +Rp3711 +(dp3712 +g201 +g176 +(g177 +(I0 +tp3713 +g179 +tp3714 +Rp3715 +(I1 +(I1 +tp3716 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3717 +tp3718 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3719 +Rp3720 +(dp3721 +g201 +g176 +(g177 +(I0 +tp3722 +g179 +tp3723 +Rp3724 +(I1 +(I2 +tp3725 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3726 +tp3727 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp3728 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3729 +g179 +tp3730 +Rp3731 +(I1 +(I1 +I1 +I1 +tp3732 +g38 +I00 +S'\xf1\x83\xa6sD\x15\xc3?' +p3733 +tp3734 +bsg238 +g176 +(g177 +(I0 +tp3735 +g179 +tp3736 +Rp3737 +(I1 +(I1 +I1 +I1 +tp3738 +g38 +I00 +S'c\xb19\xd0\x8d\x9b5?' +p3739 +tp3740 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3741 +g179 +tp3742 +Rp3743 +(I1 +(I1 +I1 +I1 +tp3744 +g38 +I00 +S"\xc2'\x85\x90\x12\xc7\xa4?" +p3745 +tp3746 +bsg252 +g513 +sg48 +(lp3747 +g0 +(g52 +g2 +Ntp3748 +Rp3749 +(dp3750 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp3751 +g179 +tp3752 +Rp3753 +(I1 +(I1 +I1 +I1 +tp3754 +g38 +I00 +S'\xe9?;\x1b\xf27\r@' +p3755 +tp3756 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp3757 +g664 +asg113 +I10110 +sg280 +I01 +sbaa(lp3758 +g666 +ag0 +(g190 +g2 +Ntp3759 +Rp3760 +(dp3761 +g194 +I01 +sg195 +(lp3762 +g0 +(g197 +g2 +Ntp3763 +Rp3764 +(dp3765 +g201 +g176 +(g177 +(I0 +tp3766 +g179 +tp3767 +Rp3768 +(I1 +(I1 +tp3769 +g208 +I00 +S"\x16'\x00\x00\x00\x00\x00\x00" +p3770 +tp3771 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3772 +Rp3773 +(dp3774 +g201 +g176 +(g177 +(I0 +tp3775 +g179 +tp3776 +Rp3777 +(I1 +(I2 +tp3778 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3779 +tp3780 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp3781 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3782 +g179 +tp3783 +Rp3784 +(I1 +(I1 +I1 +I1 +tp3785 +g38 +I00 +S'\xf2\x83\xa6sD\x15\xc3?' +p3786 +tp3787 +bsg238 +g176 +(g177 +(I0 +tp3788 +g179 +tp3789 +Rp3790 +(I1 +(I1 +I1 +I1 +tp3791 +g38 +I00 +S'B\xaf9\xd0\x8d\x9b5?' +p3792 +tp3793 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3794 +g179 +tp3795 +Rp3796 +(I1 +(I1 +I1 +I1 +tp3797 +g38 +I00 +S"\xc6'\x85\x90\x12\xc7\xa4?" +p3798 +tp3799 +bsg252 +g713 +sg48 +(lp3800 +g0 +(g52 +g2 +Ntp3801 +Rp3802 +(dp3803 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp3804 +g179 +tp3805 +Rp3806 +(I1 +(I1 +I1 +I1 +tp3807 +g38 +I00 +S'\xee?;\x1b\xf27\r@' +p3808 +tp3809 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp3810 +g727 +asg113 +I10111 +sg280 +I01 +sbaatp3811 +Rp3812 +sg337 +I00 +sg338 +Nsbaatp3813 +Rp3814 +aa(lp3815 +I10007 +ag7 +((lp3816 +(lp3817 +g12 +ag0 +(g13 +g2 +Ntp3818 +Rp3819 +(dp3820 +g17 +g0 +(g18 +g2 +Ntp3821 +Rp3822 +(dp3823 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p3824 +sg116 +g0 +(g117 +g2 +Ntp3825 +Rp3826 +(dp3827 +g121 +(lp3828 +g0 +(g123 +g2 +Ntp3829 +Rp3830 +(dp3831 +g127 +g0 +(g128 +g2 +Ntp3832 +Rp3833 +(dp3834 +g23 +g132 +sg133 +(dp3835 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xc3?' +p3836 +tp3837 +Rp3838 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p3839 +sg113 +I16 +sg146 +(lp3840 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp3841 +Rp3842 +(dp3843 +g127 +g0 +(g128 +g2 +Ntp3844 +Rp3845 +(dp3846 +g23 +g132 +sg133 +(dp3847 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xb9?' +p3848 +tp3849 +Rp3850 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p3851 +sg113 +I17 +sg146 +(lp3852 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10007 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3853 +(lp3854 +g189 +ag0 +(g190 +g2 +Ntp3855 +Rp3856 +(dp3857 +g194 +I01 +sg195 +(lp3858 +g0 +(g197 +g2 +Ntp3859 +Rp3860 +(dp3861 +g201 +g176 +(g177 +(I0 +tp3862 +g179 +tp3863 +Rp3864 +(I1 +(I1 +tp3865 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p3866 +tp3867 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3868 +Rp3869 +(dp3870 +g201 +g176 +(g177 +(I0 +tp3871 +g179 +tp3872 +Rp3873 +(I1 +(I2 +tp3874 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3875 +tp3876 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3877 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3878 +g179 +tp3879 +Rp3880 +(I1 +(I1 +I1 +I1 +tp3881 +g38 +I00 +S'\xd2\x17\xa4B\xe2\\8@' +p3882 +tp3883 +bsg238 +g176 +(g177 +(I0 +tp3884 +g179 +tp3885 +Rp3886 +(I1 +(I1 +I1 +I1 +tp3887 +g38 +I00 +S'$\xf5\xee\x01k)D?' +p3888 +tp3889 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3890 +g179 +tp3891 +Rp3892 +(I1 +(I1 +I1 +I1 +tp3893 +g38 +I00 +S'\x98&m\x0c\xec\xa5\xe0?' +p3894 +tp3895 +bsg252 +g260 +sg48 +(lp3896 +g0 +(g52 +g2 +Ntp3897 +Rp3898 +(dp3899 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3900 +g179 +tp3901 +Rp3902 +(I1 +(I1 +I1 +I1 +tp3903 +g38 +I00 +S'F~y\xf1SiG@' +p3904 +tp3905 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3906 +g279 +asg113 +I10114 +sg280 +I01 +sbaa(lp3907 +g12 +ag0 +(g190 +g2 +Ntp3908 +Rp3909 +(dp3910 +g194 +I01 +sg195 +(lp3911 +g0 +(g197 +g2 +Ntp3912 +Rp3913 +(dp3914 +g201 +g176 +(g177 +(I0 +tp3915 +g179 +tp3916 +Rp3917 +(I1 +(I1 +tp3918 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p3919 +tp3920 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3921 +Rp3922 +(dp3923 +g201 +g176 +(g177 +(I0 +tp3924 +g179 +tp3925 +Rp3926 +(I1 +(I2 +tp3927 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3928 +tp3929 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3930 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3931 +g179 +tp3932 +Rp3933 +(I1 +(I1 +I1 +I1 +tp3934 +g38 +I00 +S'\x02\xc8\xb5v\xa1\x06\x0f@' +p3935 +tp3936 +bsg238 +g176 +(g177 +(I0 +tp3937 +g179 +tp3938 +Rp3939 +(I1 +(I1 +I1 +I1 +tp3940 +g38 +I00 +S'\xc9\xf2T\xf2x\xb51?' +p3941 +tp3942 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp3943 +g179 +tp3944 +Rp3945 +(I1 +(I1 +I1 +I1 +tp3946 +g38 +I00 +S'I\xc2\x07\xd4\xa1\x91\xca?' +p3947 +tp3948 +bsg252 +g260 +sg48 +(lp3949 +g0 +(g52 +g2 +Ntp3950 +Rp3951 +(dp3952 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp3953 +g179 +tp3954 +Rp3955 +(I1 +(I1 +I1 +I1 +tp3956 +g38 +I00 +S'\x9bt\x15\xc9e\xae2@' +p3957 +tp3958 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp3959 +g334 +asg113 +I10115 +sg280 +I01 +sbaatp3960 +Rp3961 +sg337 +I00 +sg338 +Nsbaa(lp3962 +g340 +ag0 +(g341 +g2 +Ntp3963 +Rp3964 +(dp3965 +g17 +g3822 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp3966 +(lp3967 +g189 +ag0 +(g190 +g2 +Ntp3968 +Rp3969 +(dp3970 +g194 +I01 +sg195 +(lp3971 +g0 +(g197 +g2 +Ntp3972 +Rp3973 +(dp3974 +g201 +g176 +(g177 +(I0 +tp3975 +g179 +tp3976 +Rp3977 +(I1 +(I1 +tp3978 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p3979 +tp3980 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp3981 +Rp3982 +(dp3983 +g201 +g176 +(g177 +(I0 +tp3984 +g179 +tp3985 +Rp3986 +(I1 +(I2 +tp3987 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p3988 +tp3989 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp3990 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp3991 +g179 +tp3992 +Rp3993 +(I1 +(I1 +I1 +I1 +tp3994 +g38 +I00 +S'\xd2\x17\xa4B\xe2\\8@' +p3995 +tp3996 +bsg238 +g176 +(g177 +(I0 +tp3997 +g179 +tp3998 +Rp3999 +(I1 +(I1 +I1 +I1 +tp4000 +g38 +I00 +S'$\xf5\xee\x01k)D?' +p4001 +tp4002 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4003 +g179 +tp4004 +Rp4005 +(I1 +(I1 +I1 +I1 +tp4006 +g38 +I00 +S'\x98&m\x0c\xec\xa5\xe0?' +p4007 +tp4008 +bsg252 +g260 +sg48 +(lp4009 +g0 +(g52 +g2 +Ntp4010 +Rp4011 +(dp4012 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4013 +g179 +tp4014 +Rp4015 +(I1 +(I1 +I1 +I1 +tp4016 +g38 +I00 +S'F~y\xf1SiG@' +p4017 +tp4018 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4019 +g279 +asg113 +I10118 +sg280 +I01 +sbaa(lp4020 +g401 +ag0 +(g190 +g2 +Ntp4021 +Rp4022 +(dp4023 +g194 +I01 +sg195 +(lp4024 +g0 +(g197 +g2 +Ntp4025 +Rp4026 +(dp4027 +g201 +g176 +(g177 +(I0 +tp4028 +g179 +tp4029 +Rp4030 +(I1 +(I1 +tp4031 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p4032 +tp4033 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4034 +Rp4035 +(dp4036 +g201 +g176 +(g177 +(I0 +tp4037 +g179 +tp4038 +Rp4039 +(I1 +(I2 +tp4040 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4041 +tp4042 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4043 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4044 +g179 +tp4045 +Rp4046 +(I1 +(I1 +I1 +I1 +tp4047 +g38 +I00 +S'\xc1\x9b\x1c\xf6\x8cj\x9e?' +p4048 +tp4049 +bsg238 +g176 +(g177 +(I0 +tp4050 +g179 +tp4051 +Rp4052 +(I1 +(I1 +I1 +I1 +tp4053 +g38 +I00 +S'\xcfb\xfb\\\x9b\x1f\x0c?' +p4054 +tp4055 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4056 +g179 +tp4057 +Rp4058 +(I1 +(I1 +I1 +I1 +tp4059 +g38 +I00 +S'\x91\xfe#a\x80\x98\x92?' +p4060 +tp4061 +bsg252 +g260 +sg48 +(lp4062 +g0 +(g52 +g2 +Ntp4063 +Rp4064 +(dp4065 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4066 +g179 +tp4067 +Rp4068 +(I1 +(I1 +I1 +I1 +tp4069 +g38 +I00 +S'\xfc\x9d\x9a\x88t&\xfa?' +p4070 +tp4071 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4072 +g454 +asg113 +I10119 +sg280 +I01 +sbaatp4073 +Rp4074 +sg337 +I00 +sg338 +Nsbaa(lp4075 +g458 +ag0 +(g459 +g2 +Ntp4076 +Rp4077 +(dp4078 +g17 +g3822 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4079 +(lp4080 +g189 +ag0 +(g190 +g2 +Ntp4081 +Rp4082 +(dp4083 +g194 +I01 +sg195 +(lp4084 +g0 +(g197 +g2 +Ntp4085 +Rp4086 +(dp4087 +g201 +g176 +(g177 +(I0 +tp4088 +g179 +tp4089 +Rp4090 +(I1 +(I1 +tp4091 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p4092 +tp4093 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4094 +Rp4095 +(dp4096 +g201 +g176 +(g177 +(I0 +tp4097 +g179 +tp4098 +Rp4099 +(I1 +(I2 +tp4100 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4101 +tp4102 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp4103 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4104 +g179 +tp4105 +Rp4106 +(I1 +(I1 +I1 +I1 +tp4107 +g38 +I00 +S'\x1b\x92j\xeb\xc5j8@' +p4108 +tp4109 +bsg238 +g176 +(g177 +(I0 +tp4110 +g179 +tp4111 +Rp4112 +(I1 +(I1 +I1 +I1 +tp4113 +g38 +I00 +S'\xc6/\xe5\xaf\xeb3V?' +p4114 +tp4115 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4116 +g179 +tp4117 +Rp4118 +(I1 +(I1 +I1 +I1 +tp4119 +g38 +I00 +S',ZE#\xa5\xa9\xe0?' +p4120 +tp4121 +bsg252 +g513 +sg48 +(lp4122 +g0 +(g52 +g2 +Ntp4123 +Rp4124 +(dp4125 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp4126 +g179 +tp4127 +Rp4128 +(I1 +(I1 +I1 +I1 +tp4129 +g38 +I00 +S'\xce\x86\x999\x90nG@' +p4130 +tp4131 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp4132 +g527 +asg113 +I10122 +sg280 +I01 +sbaa(lp4133 +g529 +ag0 +(g190 +g2 +Ntp4134 +Rp4135 +(dp4136 +g194 +I01 +sg195 +(lp4137 +g0 +(g197 +g2 +Ntp4138 +Rp4139 +(dp4140 +g201 +g176 +(g177 +(I0 +tp4141 +g179 +tp4142 +Rp4143 +(I1 +(I1 +tp4144 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p4145 +tp4146 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4147 +Rp4148 +(dp4149 +g201 +g176 +(g177 +(I0 +tp4150 +g179 +tp4151 +Rp4152 +(I1 +(I2 +tp4153 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4154 +tp4155 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4156 +Rp4157 +(dp4158 +g201 +g176 +(g177 +(I0 +tp4159 +g179 +tp4160 +Rp4161 +(I1 +(I2 +tp4162 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4163 +tp4164 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp4165 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4166 +g179 +tp4167 +Rp4168 +(I1 +(I1 +I1 +I1 +tp4169 +g38 +I00 +S'\xabZ,\xc1\xb9Q\x0b@' +p4170 +tp4171 +bsg238 +g176 +(g177 +(I0 +tp4172 +g179 +tp4173 +Rp4174 +(I1 +(I1 +I1 +I1 +tp4175 +g38 +I00 +S'&~\x91\x1a\xfa\xedA?' +p4176 +tp4177 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4178 +g179 +tp4179 +Rp4180 +(I1 +(I1 +I1 +I1 +tp4181 +g38 +I00 +S'\x95\xdb\x1fd\xa8\xec\xc8?' +p4182 +tp4183 +bsg252 +g586 +sg48 +(lp4184 +g0 +(g52 +g2 +Ntp4185 +Rp4186 +(dp4187 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp4188 +g179 +tp4189 +Rp4190 +(I1 +(I1 +I1 +I1 +tp4191 +g38 +I00 +S'effff\x861@' +p4192 +tp4193 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp4194 +g600 +asg113 +I10123 +sg280 +I01 +sbaatp4195 +Rp4196 +sg337 +I00 +sg338 +Nsbaa(lp4197 +g604 +ag0 +(g605 +g2 +Ntp4198 +Rp4199 +(dp4200 +g17 +g3822 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4201 +(lp4202 +g611 +ag0 +(g190 +g2 +Ntp4203 +Rp4204 +(dp4205 +g194 +I01 +sg195 +(lp4206 +g0 +(g197 +g2 +Ntp4207 +Rp4208 +(dp4209 +g201 +g176 +(g177 +(I0 +tp4210 +g179 +tp4211 +Rp4212 +(I1 +(I1 +tp4213 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p4214 +tp4215 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4216 +Rp4217 +(dp4218 +g201 +g176 +(g177 +(I0 +tp4219 +g179 +tp4220 +Rp4221 +(I1 +(I2 +tp4222 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4223 +tp4224 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp4225 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4226 +g179 +tp4227 +Rp4228 +(I1 +(I1 +I1 +I1 +tp4229 +g38 +I00 +S'\xf2\xc2\xc2N*^\x9e?' +p4230 +tp4231 +bsg238 +g176 +(g177 +(I0 +tp4232 +g179 +tp4233 +Rp4234 +(I1 +(I1 +I1 +I1 +tp4235 +g38 +I00 +S'qR\x8dl\xce\xcd(?' +p4236 +tp4237 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4238 +g179 +tp4239 +Rp4240 +(I1 +(I1 +I1 +I1 +tp4241 +g38 +I00 +S'\xfc\x8fe\xaa}\x7f\x92?' +p4242 +tp4243 +bsg252 +g513 +sg48 +(lp4244 +g0 +(g52 +g2 +Ntp4245 +Rp4246 +(dp4247 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp4248 +g179 +tp4249 +Rp4250 +(I1 +(I1 +I1 +I1 +tp4251 +g38 +I00 +S'{\xd2\x9e\xb7H\x03\xfa?' +p4252 +tp4253 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp4254 +g664 +asg113 +I10126 +sg280 +I01 +sbaa(lp4255 +g666 +ag0 +(g190 +g2 +Ntp4256 +Rp4257 +(dp4258 +g194 +I01 +sg195 +(lp4259 +g0 +(g197 +g2 +Ntp4260 +Rp4261 +(dp4262 +g201 +g176 +(g177 +(I0 +tp4263 +g179 +tp4264 +Rp4265 +(I1 +(I1 +tp4266 +g208 +I00 +S"\x17'\x00\x00\x00\x00\x00\x00" +p4267 +tp4268 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4269 +Rp4270 +(dp4271 +g201 +g176 +(g177 +(I0 +tp4272 +g179 +tp4273 +Rp4274 +(I1 +(I2 +tp4275 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4276 +tp4277 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp4278 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4279 +g179 +tp4280 +Rp4281 +(I1 +(I1 +I1 +I1 +tp4282 +g38 +I00 +S'\xf2\xc2\xc2N*^\x9e?' +p4283 +tp4284 +bsg238 +g176 +(g177 +(I0 +tp4285 +g179 +tp4286 +Rp4287 +(I1 +(I1 +I1 +I1 +tp4288 +g38 +I00 +S'\xbfQ\x8dl\xce\xcd(?' +p4289 +tp4290 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4291 +g179 +tp4292 +Rp4293 +(I1 +(I1 +I1 +I1 +tp4294 +g38 +I00 +S'\xfd\x8fe\xaa}\x7f\x92?' +p4295 +tp4296 +bsg252 +g713 +sg48 +(lp4297 +g0 +(g52 +g2 +Ntp4298 +Rp4299 +(dp4300 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp4301 +g179 +tp4302 +Rp4303 +(I1 +(I1 +I1 +I1 +tp4304 +g38 +I00 +S'|\xd2\x9e\xb7H\x03\xfa?' +p4305 +tp4306 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp4307 +g727 +asg113 +I10127 +sg280 +I01 +sbaatp4308 +Rp4309 +sg337 +I00 +sg338 +Nsbaatp4310 +Rp4311 +aa(lp4312 +I10008 +ag7 +((lp4313 +(lp4314 +g12 +ag0 +(g13 +g2 +Ntp4315 +Rp4316 +(dp4317 +g17 +g0 +(g18 +g2 +Ntp4318 +Rp4319 +(dp4320 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p4321 +sg116 +g0 +(g117 +g2 +Ntp4322 +Rp4323 +(dp4324 +g121 +(lp4325 +g0 +(g123 +g2 +Ntp4326 +Rp4327 +(dp4328 +g127 +g0 +(g128 +g2 +Ntp4329 +Rp4330 +(dp4331 +g23 +g132 +sg133 +(dp4332 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'33333\xb3\x12@' +p4333 +tp4334 +Rp4335 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p4336 +sg113 +I18 +sg146 +(lp4337 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp4338 +Rp4339 +(dp4340 +g127 +g0 +(g128 +g2 +Ntp4341 +Rp4342 +(dp4343 +g23 +g132 +sg133 +(dp4344 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xf6(\\\x8f\xc2\xf5\x12@' +p4345 +tp4346 +Rp4347 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p4348 +sg113 +I19 +sg146 +(lp4349 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10008 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4350 +(lp4351 +g189 +ag0 +(g190 +g2 +Ntp4352 +Rp4353 +(dp4354 +g194 +I01 +sg195 +(lp4355 +g0 +(g197 +g2 +Ntp4356 +Rp4357 +(dp4358 +g201 +g176 +(g177 +(I0 +tp4359 +g179 +tp4360 +Rp4361 +(I1 +(I1 +tp4362 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4363 +tp4364 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4365 +Rp4366 +(dp4367 +g201 +g176 +(g177 +(I0 +tp4368 +g179 +tp4369 +Rp4370 +(I1 +(I2 +tp4371 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4372 +tp4373 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4374 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4375 +g179 +tp4376 +Rp4377 +(I1 +(I1 +I1 +I1 +tp4378 +g38 +I00 +S'~\x05\x8aZ\x7fcI@' +p4379 +tp4380 +bsg238 +g176 +(g177 +(I0 +tp4381 +g179 +tp4382 +Rp4383 +(I1 +(I1 +I1 +I1 +tp4384 +g38 +I00 +S'\xb8\x02o\x0e\x81+K?' +p4385 +tp4386 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4387 +g179 +tp4388 +Rp4389 +(I1 +(I1 +I1 +I1 +tp4390 +g38 +I00 +S'\xd5\x8a\xab\x12\xe7\x08\xe8?' +p4391 +tp4392 +bsg252 +g260 +sg48 +(lp4393 +g0 +(g52 +g2 +Ntp4394 +Rp4395 +(dp4396 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4397 +g179 +tp4398 +Rp4399 +(I1 +(I1 +I1 +I1 +tp4400 +g38 +I00 +S'\x9e\x9d yB\xe6P@' +p4401 +tp4402 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4403 +g279 +asg113 +I10130 +sg280 +I01 +sbaa(lp4404 +g12 +ag0 +(g190 +g2 +Ntp4405 +Rp4406 +(dp4407 +g194 +I01 +sg195 +(lp4408 +g0 +(g197 +g2 +Ntp4409 +Rp4410 +(dp4411 +g201 +g176 +(g177 +(I0 +tp4412 +g179 +tp4413 +Rp4414 +(I1 +(I1 +tp4415 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4416 +tp4417 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4418 +Rp4419 +(dp4420 +g201 +g176 +(g177 +(I0 +tp4421 +g179 +tp4422 +Rp4423 +(I1 +(I2 +tp4424 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4425 +tp4426 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4427 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4428 +g179 +tp4429 +Rp4430 +(I1 +(I1 +I1 +I1 +tp4431 +g38 +I00 +S'[\x8a\xa9e>\x93N@' +p4432 +tp4433 +bsg238 +g176 +(g177 +(I0 +tp4434 +g179 +tp4435 +Rp4436 +(I1 +(I1 +I1 +I1 +tp4437 +g38 +I00 +S'\x8b\xdf\xc9R\xa0\x8aU?' +p4438 +tp4439 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4440 +g179 +tp4441 +Rp4442 +(I1 +(I1 +I1 +I1 +tp4443 +g38 +I00 +S'\x11\x92s]\xca_\xea?' +p4444 +tp4445 +bsg252 +g260 +sg48 +(lp4446 +g0 +(g52 +g2 +Ntp4447 +Rp4448 +(dp4449 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4450 +g179 +tp4451 +Rp4452 +(I1 +(I1 +I1 +I1 +tp4453 +g38 +I00 +S'\xb4B\xb5IZ\x8bR@' +p4454 +tp4455 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4456 +g334 +asg113 +I10131 +sg280 +I01 +sbaatp4457 +Rp4458 +sg337 +I00 +sg338 +Nsbaa(lp4459 +g340 +ag0 +(g341 +g2 +Ntp4460 +Rp4461 +(dp4462 +g17 +g4319 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4463 +(lp4464 +g189 +ag0 +(g190 +g2 +Ntp4465 +Rp4466 +(dp4467 +g194 +I01 +sg195 +(lp4468 +g0 +(g197 +g2 +Ntp4469 +Rp4470 +(dp4471 +g201 +g176 +(g177 +(I0 +tp4472 +g179 +tp4473 +Rp4474 +(I1 +(I1 +tp4475 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4476 +tp4477 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4478 +Rp4479 +(dp4480 +g201 +g176 +(g177 +(I0 +tp4481 +g179 +tp4482 +Rp4483 +(I1 +(I2 +tp4484 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4485 +tp4486 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4487 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4488 +g179 +tp4489 +Rp4490 +(I1 +(I1 +I1 +I1 +tp4491 +g38 +I00 +S'~\x05\x8aZ\x7fcI@' +p4492 +tp4493 +bsg238 +g176 +(g177 +(I0 +tp4494 +g179 +tp4495 +Rp4496 +(I1 +(I1 +I1 +I1 +tp4497 +g38 +I00 +S'\xb8\x02o\x0e\x81+K?' +p4498 +tp4499 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4500 +g179 +tp4501 +Rp4502 +(I1 +(I1 +I1 +I1 +tp4503 +g38 +I00 +S'\xd5\x8a\xab\x12\xe7\x08\xe8?' +p4504 +tp4505 +bsg252 +g260 +sg48 +(lp4506 +g0 +(g52 +g2 +Ntp4507 +Rp4508 +(dp4509 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4510 +g179 +tp4511 +Rp4512 +(I1 +(I1 +I1 +I1 +tp4513 +g38 +I00 +S'\x9e\x9d yB\xe6P@' +p4514 +tp4515 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4516 +g279 +asg113 +I10134 +sg280 +I01 +sbaa(lp4517 +g401 +ag0 +(g190 +g2 +Ntp4518 +Rp4519 +(dp4520 +g194 +I01 +sg195 +(lp4521 +g0 +(g197 +g2 +Ntp4522 +Rp4523 +(dp4524 +g201 +g176 +(g177 +(I0 +tp4525 +g179 +tp4526 +Rp4527 +(I1 +(I1 +tp4528 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4529 +tp4530 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4531 +Rp4532 +(dp4533 +g201 +g176 +(g177 +(I0 +tp4534 +g179 +tp4535 +Rp4536 +(I1 +(I2 +tp4537 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4538 +tp4539 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4540 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4541 +g179 +tp4542 +Rp4543 +(I1 +(I1 +I1 +I1 +tp4544 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4545 +tp4546 +bsg238 +g176 +(g177 +(I0 +tp4547 +g179 +tp4548 +Rp4549 +(I1 +(I1 +I1 +I1 +tp4550 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4551 +tp4552 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4553 +g179 +tp4554 +Rp4555 +(I1 +(I1 +I1 +I1 +tp4556 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4557 +tp4558 +bsg252 +g260 +sg48 +(lp4559 +g0 +(g52 +g2 +Ntp4560 +Rp4561 +(dp4562 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4563 +g179 +tp4564 +Rp4565 +(I1 +(I1 +I1 +I1 +tp4566 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4567 +tp4568 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4569 +g454 +asg113 +I10135 +sg280 +I01 +sbaatp4570 +Rp4571 +sg337 +I00 +sg338 +Nsbaa(lp4572 +g458 +ag0 +(g459 +g2 +Ntp4573 +Rp4574 +(dp4575 +g17 +g4319 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4576 +(lp4577 +g189 +ag0 +(g190 +g2 +Ntp4578 +Rp4579 +(dp4580 +g194 +I01 +sg195 +(lp4581 +g0 +(g197 +g2 +Ntp4582 +Rp4583 +(dp4584 +g201 +g176 +(g177 +(I0 +tp4585 +g179 +tp4586 +Rp4587 +(I1 +(I1 +tp4588 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4589 +tp4590 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4591 +Rp4592 +(dp4593 +g201 +g176 +(g177 +(I0 +tp4594 +g179 +tp4595 +Rp4596 +(I1 +(I2 +tp4597 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4598 +tp4599 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp4600 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4601 +g179 +tp4602 +Rp4603 +(I1 +(I1 +I1 +I1 +tp4604 +g38 +I00 +S'z\xb3\xe0:,\x8bI@' +p4605 +tp4606 +bsg238 +g176 +(g177 +(I0 +tp4607 +g179 +tp4608 +Rp4609 +(I1 +(I1 +I1 +I1 +tp4610 +g38 +I00 +S'i\xfa\xf3\x84\xfbsY?' +p4611 +tp4612 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4613 +g179 +tp4614 +Rp4615 +(I1 +(I1 +I1 +I1 +tp4616 +g38 +I00 +S'^*e\x16\xd2\x1a\xe8?' +p4617 +tp4618 +bsg252 +g513 +sg48 +(lp4619 +g0 +(g52 +g2 +Ntp4620 +Rp4621 +(dp4622 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp4623 +g179 +tp4624 +Rp4625 +(I1 +(I1 +I1 +I1 +tp4626 +g38 +I00 +S'\xca!\xbf\xb7\xdb\xf2P@' +p4627 +tp4628 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp4629 +g527 +asg113 +I10138 +sg280 +I01 +sbaa(lp4630 +g529 +ag0 +(g190 +g2 +Ntp4631 +Rp4632 +(dp4633 +g194 +I01 +sg195 +(lp4634 +g0 +(g197 +g2 +Ntp4635 +Rp4636 +(dp4637 +g201 +g176 +(g177 +(I0 +tp4638 +g179 +tp4639 +Rp4640 +(I1 +(I1 +tp4641 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4642 +tp4643 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4644 +Rp4645 +(dp4646 +g201 +g176 +(g177 +(I0 +tp4647 +g179 +tp4648 +Rp4649 +(I1 +(I2 +tp4650 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4651 +tp4652 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4653 +Rp4654 +(dp4655 +g201 +g176 +(g177 +(I0 +tp4656 +g179 +tp4657 +Rp4658 +(I1 +(I2 +tp4659 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4660 +tp4661 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp4662 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4663 +g179 +tp4664 +Rp4665 +(I1 +(I1 +I1 +I1 +tp4666 +g38 +I00 +S'\xad\xb3B\r\xb6\xe3M@' +p4667 +tp4668 +bsg238 +g176 +(g177 +(I0 +tp4669 +g179 +tp4670 +Rp4671 +(I1 +(I1 +I1 +I1 +tp4672 +g38 +I00 +S'c\x11\xa6E\xf0\xa1Y?' +p4673 +tp4674 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4675 +g179 +tp4676 +Rp4677 +(I1 +(I1 +I1 +I1 +tp4678 +g38 +I00 +S'\x1bLN\x9eP\x13\xea?' +p4679 +tp4680 +bsg252 +g586 +sg48 +(lp4681 +g0 +(g52 +g2 +Ntp4682 +Rp4683 +(dp4684 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp4685 +g179 +tp4686 +Rp4687 +(I1 +(I1 +I1 +I1 +tp4688 +g38 +I00 +S'\x83\rO\xaf\x94UR@' +p4689 +tp4690 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp4691 +g600 +asg113 +I10139 +sg280 +I01 +sbaatp4692 +Rp4693 +sg337 +I00 +sg338 +Nsbaa(lp4694 +g604 +ag0 +(g605 +g2 +Ntp4695 +Rp4696 +(dp4697 +g17 +g4319 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4698 +(lp4699 +g611 +ag0 +(g190 +g2 +Ntp4700 +Rp4701 +(dp4702 +g194 +I01 +sg195 +(lp4703 +g0 +(g197 +g2 +Ntp4704 +Rp4705 +(dp4706 +g201 +g176 +(g177 +(I0 +tp4707 +g179 +tp4708 +Rp4709 +(I1 +(I1 +tp4710 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4711 +tp4712 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4713 +Rp4714 +(dp4715 +g201 +g176 +(g177 +(I0 +tp4716 +g179 +tp4717 +Rp4718 +(I1 +(I2 +tp4719 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4720 +tp4721 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp4722 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4723 +g179 +tp4724 +Rp4725 +(I1 +(I1 +I1 +I1 +tp4726 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4727 +tp4728 +bsg238 +g176 +(g177 +(I0 +tp4729 +g179 +tp4730 +Rp4731 +(I1 +(I1 +I1 +I1 +tp4732 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4733 +tp4734 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4735 +g179 +tp4736 +Rp4737 +(I1 +(I1 +I1 +I1 +tp4738 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4739 +tp4740 +bsg252 +g513 +sg48 +(lp4741 +g0 +(g52 +g2 +Ntp4742 +Rp4743 +(dp4744 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp4745 +g179 +tp4746 +Rp4747 +(I1 +(I1 +I1 +I1 +tp4748 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4749 +tp4750 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp4751 +g664 +asg113 +I10142 +sg280 +I01 +sbaa(lp4752 +g666 +ag0 +(g190 +g2 +Ntp4753 +Rp4754 +(dp4755 +g194 +I01 +sg195 +(lp4756 +g0 +(g197 +g2 +Ntp4757 +Rp4758 +(dp4759 +g201 +g176 +(g177 +(I0 +tp4760 +g179 +tp4761 +Rp4762 +(I1 +(I1 +tp4763 +g208 +I00 +S"\x18'\x00\x00\x00\x00\x00\x00" +p4764 +tp4765 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4766 +Rp4767 +(dp4768 +g201 +g176 +(g177 +(I0 +tp4769 +g179 +tp4770 +Rp4771 +(I1 +(I2 +tp4772 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4773 +tp4774 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp4775 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4776 +g179 +tp4777 +Rp4778 +(I1 +(I1 +I1 +I1 +tp4779 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4780 +tp4781 +bsg238 +g176 +(g177 +(I0 +tp4782 +g179 +tp4783 +Rp4784 +(I1 +(I1 +I1 +I1 +tp4785 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4786 +tp4787 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4788 +g179 +tp4789 +Rp4790 +(I1 +(I1 +I1 +I1 +tp4791 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4792 +tp4793 +bsg252 +g713 +sg48 +(lp4794 +g0 +(g52 +g2 +Ntp4795 +Rp4796 +(dp4797 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp4798 +g179 +tp4799 +Rp4800 +(I1 +(I1 +I1 +I1 +tp4801 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p4802 +tp4803 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp4804 +g727 +asg113 +I10143 +sg280 +I01 +sbaatp4805 +Rp4806 +sg337 +I00 +sg338 +Nsbaatp4807 +Rp4808 +aa(lp4809 +I10009 +ag7 +((lp4810 +(lp4811 +g12 +ag0 +(g13 +g2 +Ntp4812 +Rp4813 +(dp4814 +g17 +g0 +(g18 +g2 +Ntp4815 +Rp4816 +(dp4817 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p4818 +sg116 +g0 +(g117 +g2 +Ntp4819 +Rp4820 +(dp4821 +g121 +(lp4822 +g0 +(g123 +g2 +Ntp4823 +Rp4824 +(dp4825 +g127 +g0 +(g128 +g2 +Ntp4826 +Rp4827 +(dp4828 +g23 +g132 +sg133 +(dp4829 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\\\x8f\xc2\xf5(\\\x10@' +p4830 +tp4831 +Rp4832 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p4833 +sg113 +I20 +sg146 +(lp4834 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp4835 +Rp4836 +(dp4837 +g127 +g0 +(g128 +g2 +Ntp4838 +Rp4839 +(dp4840 +g23 +g132 +sg133 +(dp4841 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x1f\x85\xebQ\xb8\x9e\x10@' +p4842 +tp4843 +Rp4844 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p4845 +sg113 +I21 +sg146 +(lp4846 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10009 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4847 +(lp4848 +g189 +ag0 +(g190 +g2 +Ntp4849 +Rp4850 +(dp4851 +g194 +I01 +sg195 +(lp4852 +g0 +(g197 +g2 +Ntp4853 +Rp4854 +(dp4855 +g201 +g176 +(g177 +(I0 +tp4856 +g179 +tp4857 +Rp4858 +(I1 +(I1 +tp4859 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p4860 +tp4861 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4862 +Rp4863 +(dp4864 +g201 +g176 +(g177 +(I0 +tp4865 +g179 +tp4866 +Rp4867 +(I1 +(I2 +tp4868 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4869 +tp4870 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4871 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4872 +g179 +tp4873 +Rp4874 +(I1 +(I1 +I1 +I1 +tp4875 +g38 +I00 +S'\xdc\x95\xceUH\xc9H@' +p4876 +tp4877 +bsg238 +g176 +(g177 +(I0 +tp4878 +g179 +tp4879 +Rp4880 +(I1 +(I1 +I1 +I1 +tp4881 +g38 +I00 +S'4\x97xT\x1a\x93C?' +p4882 +tp4883 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4884 +g179 +tp4885 +Rp4886 +(I1 +(I1 +I1 +I1 +tp4887 +g38 +I00 +S'\x98\xdcC\x8c\x9f\xbf\xe7?' +p4888 +tp4889 +bsg252 +g260 +sg48 +(lp4890 +g0 +(g52 +g2 +Ntp4891 +Rp4892 +(dp4893 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4894 +g179 +tp4895 +Rp4896 +(I1 +(I1 +I1 +I1 +tp4897 +g38 +I00 +S'\x1b\xb7\x9f.\xbc\xb2P@' +p4898 +tp4899 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4900 +g279 +asg113 +I10146 +sg280 +I01 +sbaa(lp4901 +g12 +ag0 +(g190 +g2 +Ntp4902 +Rp4903 +(dp4904 +g194 +I01 +sg195 +(lp4905 +g0 +(g197 +g2 +Ntp4906 +Rp4907 +(dp4908 +g201 +g176 +(g177 +(I0 +tp4909 +g179 +tp4910 +Rp4911 +(I1 +(I1 +tp4912 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p4913 +tp4914 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4915 +Rp4916 +(dp4917 +g201 +g176 +(g177 +(I0 +tp4918 +g179 +tp4919 +Rp4920 +(I1 +(I2 +tp4921 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4922 +tp4923 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4924 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4925 +g179 +tp4926 +Rp4927 +(I1 +(I1 +I1 +I1 +tp4928 +g38 +I00 +S'\xb0\xe6\xe3T\xa8TL@' +p4929 +tp4930 +bsg238 +g176 +(g177 +(I0 +tp4931 +g179 +tp4932 +Rp4933 +(I1 +(I1 +I1 +I1 +tp4934 +g38 +I00 +S'\xd0!\xc6Vb\xb1O?' +p4935 +tp4936 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4937 +g179 +tp4938 +Rp4939 +(I1 +(I1 +I1 +I1 +tp4940 +g38 +I00 +S'\xe8\x8b@\xe2\x8dc\xe9?' +p4941 +tp4942 +bsg252 +g260 +sg48 +(lp4943 +g0 +(g52 +g2 +Ntp4944 +Rp4945 +(dp4946 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp4947 +g179 +tp4948 +Rp4949 +(I1 +(I1 +I1 +I1 +tp4950 +g38 +I00 +S'_b\x15\xc3\xff\xd9Q@' +p4951 +tp4952 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp4953 +g334 +asg113 +I10147 +sg280 +I01 +sbaatp4954 +Rp4955 +sg337 +I00 +sg338 +Nsbaa(lp4956 +g340 +ag0 +(g341 +g2 +Ntp4957 +Rp4958 +(dp4959 +g17 +g4816 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp4960 +(lp4961 +g189 +ag0 +(g190 +g2 +Ntp4962 +Rp4963 +(dp4964 +g194 +I01 +sg195 +(lp4965 +g0 +(g197 +g2 +Ntp4966 +Rp4967 +(dp4968 +g201 +g176 +(g177 +(I0 +tp4969 +g179 +tp4970 +Rp4971 +(I1 +(I1 +tp4972 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p4973 +tp4974 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp4975 +Rp4976 +(dp4977 +g201 +g176 +(g177 +(I0 +tp4978 +g179 +tp4979 +Rp4980 +(I1 +(I2 +tp4981 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p4982 +tp4983 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp4984 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp4985 +g179 +tp4986 +Rp4987 +(I1 +(I1 +I1 +I1 +tp4988 +g38 +I00 +S'\xdc\x95\xceUH\xc9H@' +p4989 +tp4990 +bsg238 +g176 +(g177 +(I0 +tp4991 +g179 +tp4992 +Rp4993 +(I1 +(I1 +I1 +I1 +tp4994 +g38 +I00 +S'4\x97xT\x1a\x93C?' +p4995 +tp4996 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp4997 +g179 +tp4998 +Rp4999 +(I1 +(I1 +I1 +I1 +tp5000 +g38 +I00 +S'\x98\xdcC\x8c\x9f\xbf\xe7?' +p5001 +tp5002 +bsg252 +g260 +sg48 +(lp5003 +g0 +(g52 +g2 +Ntp5004 +Rp5005 +(dp5006 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5007 +g179 +tp5008 +Rp5009 +(I1 +(I1 +I1 +I1 +tp5010 +g38 +I00 +S'\x1b\xb7\x9f.\xbc\xb2P@' +p5011 +tp5012 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5013 +g279 +asg113 +I10150 +sg280 +I01 +sbaa(lp5014 +g401 +ag0 +(g190 +g2 +Ntp5015 +Rp5016 +(dp5017 +g194 +I01 +sg195 +(lp5018 +g0 +(g197 +g2 +Ntp5019 +Rp5020 +(dp5021 +g201 +g176 +(g177 +(I0 +tp5022 +g179 +tp5023 +Rp5024 +(I1 +(I1 +tp5025 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p5026 +tp5027 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5028 +Rp5029 +(dp5030 +g201 +g176 +(g177 +(I0 +tp5031 +g179 +tp5032 +Rp5033 +(I1 +(I2 +tp5034 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5035 +tp5036 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5037 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5038 +g179 +tp5039 +Rp5040 +(I1 +(I1 +I1 +I1 +tp5041 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5042 +tp5043 +bsg238 +g176 +(g177 +(I0 +tp5044 +g179 +tp5045 +Rp5046 +(I1 +(I1 +I1 +I1 +tp5047 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5048 +tp5049 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5050 +g179 +tp5051 +Rp5052 +(I1 +(I1 +I1 +I1 +tp5053 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5054 +tp5055 +bsg252 +g260 +sg48 +(lp5056 +g0 +(g52 +g2 +Ntp5057 +Rp5058 +(dp5059 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5060 +g179 +tp5061 +Rp5062 +(I1 +(I1 +I1 +I1 +tp5063 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5064 +tp5065 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5066 +g454 +asg113 +I10151 +sg280 +I01 +sbaatp5067 +Rp5068 +sg337 +I00 +sg338 +Nsbaa(lp5069 +g458 +ag0 +(g459 +g2 +Ntp5070 +Rp5071 +(dp5072 +g17 +g4816 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5073 +(lp5074 +g189 +ag0 +(g190 +g2 +Ntp5075 +Rp5076 +(dp5077 +g194 +I01 +sg195 +(lp5078 +g0 +(g197 +g2 +Ntp5079 +Rp5080 +(dp5081 +g201 +g176 +(g177 +(I0 +tp5082 +g179 +tp5083 +Rp5084 +(I1 +(I1 +tp5085 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p5086 +tp5087 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5088 +Rp5089 +(dp5090 +g201 +g176 +(g177 +(I0 +tp5091 +g179 +tp5092 +Rp5093 +(I1 +(I2 +tp5094 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5095 +tp5096 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp5097 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5098 +g179 +tp5099 +Rp5100 +(I1 +(I1 +I1 +I1 +tp5101 +g38 +I00 +S'\xb0\xd0jjO\xd5H@' +p5102 +tp5103 +bsg238 +g176 +(g177 +(I0 +tp5104 +g179 +tp5105 +Rp5106 +(I1 +(I1 +I1 +I1 +tp5107 +g38 +I00 +S'\x98\x16e\xe1\x95\x02T?' +p5108 +tp5109 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5110 +g179 +tp5111 +Rp5112 +(I1 +(I1 +I1 +I1 +tp5113 +g38 +I00 +S'\xcb\x88\x84s\xd3\xc4\xe7?' +p5114 +tp5115 +bsg252 +g513 +sg48 +(lp5116 +g0 +(g52 +g2 +Ntp5117 +Rp5118 +(dp5119 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp5120 +g179 +tp5121 +Rp5122 +(I1 +(I1 +I1 +I1 +tp5123 +g38 +I00 +S'/09\xadd\xb6P@' +p5124 +tp5125 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp5126 +g527 +asg113 +I10154 +sg280 +I01 +sbaa(lp5127 +g529 +ag0 +(g190 +g2 +Ntp5128 +Rp5129 +(dp5130 +g194 +I01 +sg195 +(lp5131 +g0 +(g197 +g2 +Ntp5132 +Rp5133 +(dp5134 +g201 +g176 +(g177 +(I0 +tp5135 +g179 +tp5136 +Rp5137 +(I1 +(I1 +tp5138 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p5139 +tp5140 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5141 +Rp5142 +(dp5143 +g201 +g176 +(g177 +(I0 +tp5144 +g179 +tp5145 +Rp5146 +(I1 +(I2 +tp5147 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5148 +tp5149 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5150 +Rp5151 +(dp5152 +g201 +g176 +(g177 +(I0 +tp5153 +g179 +tp5154 +Rp5155 +(I1 +(I2 +tp5156 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5157 +tp5158 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp5159 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5160 +g179 +tp5161 +Rp5162 +(I1 +(I1 +I1 +I1 +tp5163 +g38 +I00 +S'\xc5\xd4\x02 \x93\xa1K@' +p5164 +tp5165 +bsg238 +g176 +(g177 +(I0 +tp5166 +g179 +tp5167 +Rp5168 +(I1 +(I1 +I1 +I1 +tp5169 +g38 +I00 +S'G\xe8\x06joBU?' +p5170 +tp5171 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5172 +g179 +tp5173 +Rp5174 +(I1 +(I1 +I1 +I1 +tp5175 +g38 +I00 +S'f5\x99@s\x12\xe9?' +p5176 +tp5177 +bsg252 +g586 +sg48 +(lp5178 +g0 +(g52 +g2 +Ntp5179 +Rp5180 +(dp5181 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp5182 +g179 +tp5183 +Rp5184 +(I1 +(I1 +I1 +I1 +tp5185 +g38 +I00 +S'\x8c\xb9k\t\xf9\xa0Q@' +p5186 +tp5187 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp5188 +g600 +asg113 +I10155 +sg280 +I01 +sbaatp5189 +Rp5190 +sg337 +I00 +sg338 +Nsbaa(lp5191 +g604 +ag0 +(g605 +g2 +Ntp5192 +Rp5193 +(dp5194 +g17 +g4816 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5195 +(lp5196 +g611 +ag0 +(g190 +g2 +Ntp5197 +Rp5198 +(dp5199 +g194 +I01 +sg195 +(lp5200 +g0 +(g197 +g2 +Ntp5201 +Rp5202 +(dp5203 +g201 +g176 +(g177 +(I0 +tp5204 +g179 +tp5205 +Rp5206 +(I1 +(I1 +tp5207 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p5208 +tp5209 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5210 +Rp5211 +(dp5212 +g201 +g176 +(g177 +(I0 +tp5213 +g179 +tp5214 +Rp5215 +(I1 +(I2 +tp5216 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5217 +tp5218 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp5219 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5220 +g179 +tp5221 +Rp5222 +(I1 +(I1 +I1 +I1 +tp5223 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5224 +tp5225 +bsg238 +g176 +(g177 +(I0 +tp5226 +g179 +tp5227 +Rp5228 +(I1 +(I1 +I1 +I1 +tp5229 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5230 +tp5231 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5232 +g179 +tp5233 +Rp5234 +(I1 +(I1 +I1 +I1 +tp5235 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5236 +tp5237 +bsg252 +g513 +sg48 +(lp5238 +g0 +(g52 +g2 +Ntp5239 +Rp5240 +(dp5241 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp5242 +g179 +tp5243 +Rp5244 +(I1 +(I1 +I1 +I1 +tp5245 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5246 +tp5247 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp5248 +g664 +asg113 +I10158 +sg280 +I01 +sbaa(lp5249 +g666 +ag0 +(g190 +g2 +Ntp5250 +Rp5251 +(dp5252 +g194 +I01 +sg195 +(lp5253 +g0 +(g197 +g2 +Ntp5254 +Rp5255 +(dp5256 +g201 +g176 +(g177 +(I0 +tp5257 +g179 +tp5258 +Rp5259 +(I1 +(I1 +tp5260 +g208 +I00 +S"\x19'\x00\x00\x00\x00\x00\x00" +p5261 +tp5262 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5263 +Rp5264 +(dp5265 +g201 +g176 +(g177 +(I0 +tp5266 +g179 +tp5267 +Rp5268 +(I1 +(I2 +tp5269 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5270 +tp5271 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp5272 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5273 +g179 +tp5274 +Rp5275 +(I1 +(I1 +I1 +I1 +tp5276 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5277 +tp5278 +bsg238 +g176 +(g177 +(I0 +tp5279 +g179 +tp5280 +Rp5281 +(I1 +(I1 +I1 +I1 +tp5282 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5283 +tp5284 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5285 +g179 +tp5286 +Rp5287 +(I1 +(I1 +I1 +I1 +tp5288 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5289 +tp5290 +bsg252 +g713 +sg48 +(lp5291 +g0 +(g52 +g2 +Ntp5292 +Rp5293 +(dp5294 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp5295 +g179 +tp5296 +Rp5297 +(I1 +(I1 +I1 +I1 +tp5298 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p5299 +tp5300 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp5301 +g727 +asg113 +I10159 +sg280 +I01 +sbaatp5302 +Rp5303 +sg337 +I00 +sg338 +Nsbaatp5304 +Rp5305 +aa(lp5306 +I10010 +ag7 +((lp5307 +(lp5308 +g12 +ag0 +(g13 +g2 +Ntp5309 +Rp5310 +(dp5311 +g17 +g0 +(g18 +g2 +Ntp5312 +Rp5313 +(dp5314 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p5315 +sg116 +g0 +(g117 +g2 +Ntp5316 +Rp5317 +(dp5318 +g121 +(lp5319 +g0 +(g123 +g2 +Ntp5320 +Rp5321 +(dp5322 +g127 +g0 +(g128 +g2 +Ntp5323 +Rp5324 +(dp5325 +g23 +g132 +sg133 +(dp5326 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xf0?' +p5327 +tp5328 +Rp5329 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p5330 +sg113 +I22 +sg146 +(lp5331 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp5332 +Rp5333 +(dp5334 +g127 +g0 +(g128 +g2 +Ntp5335 +Rp5336 +(dp5337 +g23 +g132 +sg133 +(dp5338 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xee?' +p5339 +tp5340 +Rp5341 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p5342 +sg113 +I23 +sg146 +(lp5343 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10010 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5344 +(lp5345 +g189 +ag0 +(g190 +g2 +Ntp5346 +Rp5347 +(dp5348 +g194 +I01 +sg195 +(lp5349 +g0 +(g197 +g2 +Ntp5350 +Rp5351 +(dp5352 +g201 +g176 +(g177 +(I0 +tp5353 +g179 +tp5354 +Rp5355 +(I1 +(I1 +tp5356 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5357 +tp5358 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5359 +Rp5360 +(dp5361 +g201 +g176 +(g177 +(I0 +tp5362 +g179 +tp5363 +Rp5364 +(I1 +(I2 +tp5365 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5366 +tp5367 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5368 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5369 +g179 +tp5370 +Rp5371 +(I1 +(I1 +I1 +I1 +tp5372 +g38 +I00 +S'\xb3!P\xe5V}8@' +p5373 +tp5374 +bsg238 +g176 +(g177 +(I0 +tp5375 +g179 +tp5376 +Rp5377 +(I1 +(I1 +I1 +I1 +tp5378 +g38 +I00 +S'\x96j\x1c`\xdd\xe9B?' +p5379 +tp5380 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5381 +g179 +tp5382 +Rp5383 +(I1 +(I1 +I1 +I1 +tp5384 +g38 +I00 +S'\xf0H\xb1\xa9\x07\xb1\xe0?' +p5385 +tp5386 +bsg252 +g260 +sg48 +(lp5387 +g0 +(g52 +g2 +Ntp5388 +Rp5389 +(dp5390 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5391 +g179 +tp5392 +Rp5393 +(I1 +(I1 +I1 +I1 +tp5394 +g38 +I00 +S'\x92N\xa1\xc6\xf2xG@' +p5395 +tp5396 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5397 +g279 +asg113 +I10162 +sg280 +I01 +sbaa(lp5398 +g12 +ag0 +(g190 +g2 +Ntp5399 +Rp5400 +(dp5401 +g194 +I01 +sg195 +(lp5402 +g0 +(g197 +g2 +Ntp5403 +Rp5404 +(dp5405 +g201 +g176 +(g177 +(I0 +tp5406 +g179 +tp5407 +Rp5408 +(I1 +(I1 +tp5409 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5410 +tp5411 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5412 +Rp5413 +(dp5414 +g201 +g176 +(g177 +(I0 +tp5415 +g179 +tp5416 +Rp5417 +(I1 +(I2 +tp5418 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5419 +tp5420 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5421 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5422 +g179 +tp5423 +Rp5424 +(I1 +(I1 +I1 +I1 +tp5425 +g38 +I00 +S'\xf8\x81\xa3b\x85\xea\x0f@' +p5426 +tp5427 +bsg238 +g176 +(g177 +(I0 +tp5428 +g179 +tp5429 +Rp5430 +(I1 +(I1 +I1 +I1 +tp5431 +g38 +I00 +S'YX\xa2\xe0\xd030?' +p5432 +tp5433 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5434 +g179 +tp5435 +Rp5436 +(I1 +(I1 +I1 +I1 +tp5437 +g38 +I00 +S'\x8e\x17\xc5\x87\x9d\xf2\xca?' +p5438 +tp5439 +bsg252 +g260 +sg48 +(lp5440 +g0 +(g52 +g2 +Ntp5441 +Rp5442 +(dp5443 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5444 +g179 +tp5445 +Rp5446 +(I1 +(I1 +I1 +I1 +tp5447 +g38 +I00 +S'\x90\x94v\xc3\x96\xf22@' +p5448 +tp5449 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5450 +g334 +asg113 +I10163 +sg280 +I01 +sbaatp5451 +Rp5452 +sg337 +I00 +sg338 +Nsbaa(lp5453 +g340 +ag0 +(g341 +g2 +Ntp5454 +Rp5455 +(dp5456 +g17 +g5313 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5457 +(lp5458 +g189 +ag0 +(g190 +g2 +Ntp5459 +Rp5460 +(dp5461 +g194 +I01 +sg195 +(lp5462 +g0 +(g197 +g2 +Ntp5463 +Rp5464 +(dp5465 +g201 +g176 +(g177 +(I0 +tp5466 +g179 +tp5467 +Rp5468 +(I1 +(I1 +tp5469 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5470 +tp5471 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5472 +Rp5473 +(dp5474 +g201 +g176 +(g177 +(I0 +tp5475 +g179 +tp5476 +Rp5477 +(I1 +(I2 +tp5478 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5479 +tp5480 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5481 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5482 +g179 +tp5483 +Rp5484 +(I1 +(I1 +I1 +I1 +tp5485 +g38 +I00 +S'\xb3!P\xe5V}8@' +p5486 +tp5487 +bsg238 +g176 +(g177 +(I0 +tp5488 +g179 +tp5489 +Rp5490 +(I1 +(I1 +I1 +I1 +tp5491 +g38 +I00 +S'\x96j\x1c`\xdd\xe9B?' +p5492 +tp5493 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5494 +g179 +tp5495 +Rp5496 +(I1 +(I1 +I1 +I1 +tp5497 +g38 +I00 +S'\xf0H\xb1\xa9\x07\xb1\xe0?' +p5498 +tp5499 +bsg252 +g260 +sg48 +(lp5500 +g0 +(g52 +g2 +Ntp5501 +Rp5502 +(dp5503 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5504 +g179 +tp5505 +Rp5506 +(I1 +(I1 +I1 +I1 +tp5507 +g38 +I00 +S'\x92N\xa1\xc6\xf2xG@' +p5508 +tp5509 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5510 +g279 +asg113 +I10166 +sg280 +I01 +sbaa(lp5511 +g401 +ag0 +(g190 +g2 +Ntp5512 +Rp5513 +(dp5514 +g194 +I01 +sg195 +(lp5515 +g0 +(g197 +g2 +Ntp5516 +Rp5517 +(dp5518 +g201 +g176 +(g177 +(I0 +tp5519 +g179 +tp5520 +Rp5521 +(I1 +(I1 +tp5522 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5523 +tp5524 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5525 +Rp5526 +(dp5527 +g201 +g176 +(g177 +(I0 +tp5528 +g179 +tp5529 +Rp5530 +(I1 +(I2 +tp5531 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5532 +tp5533 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5534 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5535 +g179 +tp5536 +Rp5537 +(I1 +(I1 +I1 +I1 +tp5538 +g38 +I00 +S'\xc1U\xacw[\x94\xa5?' +p5539 +tp5540 +bsg238 +g176 +(g177 +(I0 +tp5541 +g179 +tp5542 +Rp5543 +(I1 +(I1 +I1 +I1 +tp5544 +g38 +I00 +S'j\xa7\x94K==\n?' +p5545 +tp5546 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5547 +g179 +tp5548 +Rp5549 +(I1 +(I1 +I1 +I1 +tp5550 +g38 +I00 +S"\xfe\xd5n\xe3\x8a'\x96?" +p5551 +tp5552 +bsg252 +g260 +sg48 +(lp5553 +g0 +(g52 +g2 +Ntp5554 +Rp5555 +(dp5556 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5557 +g179 +tp5558 +Rp5559 +(I1 +(I1 +I1 +I1 +tp5560 +g38 +I00 +S"\xed\xdc\xd3O\x9b'\xff?" +p5561 +tp5562 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5563 +g454 +asg113 +I10167 +sg280 +I01 +sbaatp5564 +Rp5565 +sg337 +I00 +sg338 +Nsbaa(lp5566 +g458 +ag0 +(g459 +g2 +Ntp5567 +Rp5568 +(dp5569 +g17 +g5313 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5570 +(lp5571 +g189 +ag0 +(g190 +g2 +Ntp5572 +Rp5573 +(dp5574 +g194 +I01 +sg195 +(lp5575 +g0 +(g197 +g2 +Ntp5576 +Rp5577 +(dp5578 +g201 +g176 +(g177 +(I0 +tp5579 +g179 +tp5580 +Rp5581 +(I1 +(I1 +tp5582 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5583 +tp5584 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5585 +Rp5586 +(dp5587 +g201 +g176 +(g177 +(I0 +tp5588 +g179 +tp5589 +Rp5590 +(I1 +(I2 +tp5591 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5592 +tp5593 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp5594 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5595 +g179 +tp5596 +Rp5597 +(I1 +(I1 +I1 +I1 +tp5598 +g38 +I00 +S'|\xa3\x05\x18sv8@' +p5599 +tp5600 +bsg238 +g176 +(g177 +(I0 +tp5601 +g179 +tp5602 +Rp5603 +(I1 +(I1 +I1 +I1 +tp5604 +g38 +I00 +S'k\xd7\x929\xc7 W?' +p5605 +tp5606 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5607 +g179 +tp5608 +Rp5609 +(I1 +(I1 +I1 +I1 +tp5610 +g38 +I00 +S't;\xda;\x85\xad\xe0?' +p5611 +tp5612 +bsg252 +g513 +sg48 +(lp5613 +g0 +(g52 +g2 +Ntp5614 +Rp5615 +(dp5616 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp5617 +g179 +tp5618 +Rp5619 +(I1 +(I1 +I1 +I1 +tp5620 +g38 +I00 +S'\x9b\xe3*\\\x03tG@' +p5621 +tp5622 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp5623 +g527 +asg113 +I10170 +sg280 +I01 +sbaa(lp5624 +g529 +ag0 +(g190 +g2 +Ntp5625 +Rp5626 +(dp5627 +g194 +I01 +sg195 +(lp5628 +g0 +(g197 +g2 +Ntp5629 +Rp5630 +(dp5631 +g201 +g176 +(g177 +(I0 +tp5632 +g179 +tp5633 +Rp5634 +(I1 +(I1 +tp5635 +g208 +I00 +S"\x1a'\x00\x00\x00\x00\x00\x00" +p5636 +tp5637 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5638 +Rp5639 +(dp5640 +g201 +g176 +(g177 +(I0 +tp5641 +g179 +tp5642 +Rp5643 +(I1 +(I2 +tp5644 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5645 +tp5646 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5647 +Rp5648 +(dp5649 +g201 +g176 +(g177 +(I0 +tp5650 +g179 +tp5651 +Rp5652 +(I1 +(I2 +tp5653 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5654 +tp5655 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp5656 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5657 +g179 +tp5658 +Rp5659 +(I1 +(I1 +I1 +I1 +tp5660 +g38 +I00 +S'c\x9ecz\xa1|\x0b@' +p5661 +tp5662 +bsg238 +g176 +(g177 +(I0 +tp5663 +g179 +tp5664 +Rp5665 +(I1 +(I1 +I1 +I1 +tp5666 +g38 +I00 +S'Y/\\\xea\x0b\xa7A?' +p5667 +tp5668 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5669 +g179 +tp5670 +Rp5671 +(I1 +(I1 +I1 +I1 +tp5672 +g38 +I00 +S'\xb9e8\xedC\xd3\xa26\xa6?' +p5774 +tp5775 +bsg238 +g176 +(g177 +(I0 +tp5776 +g179 +tp5777 +Rp5778 +(I1 +(I1 +I1 +I1 +tp5779 +g38 +I00 +S'\x96\xe0U(k\xd7)?' +p5780 +tp5781 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5782 +g179 +tp5783 +Rp5784 +(I1 +(I1 +I1 +I1 +tp5785 +g38 +I00 +S'\xcf\x15\xb0\xec\xebf\x96?' +p5786 +tp5787 +bsg252 +g713 +sg48 +(lp5788 +g0 +(g52 +g2 +Ntp5789 +Rp5790 +(dp5791 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp5792 +g179 +tp5793 +Rp5794 +(I1 +(I1 +I1 +I1 +tp5795 +g38 +I00 +S'\xab\x9e\xd7\xc4\xbb\x80\xff?' +p5796 +tp5797 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp5798 +g727 +asg113 +I10175 +sg280 +I01 +sbaatp5799 +Rp5800 +sg337 +I00 +sg338 +Nsbaatp5801 +Rp5802 +aa(lp5803 +I10012 +ag7 +((lp5804 +(lp5805 +g12 +ag0 +(g13 +g2 +Ntp5806 +Rp5807 +(dp5808 +g17 +g0 +(g18 +g2 +Ntp5809 +Rp5810 +(dp5811 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p5812 +sg116 +g0 +(g117 +g2 +Ntp5813 +Rp5814 +(dp5815 +g121 +(lp5816 +g0 +(g123 +g2 +Ntp5817 +Rp5818 +(dp5819 +g127 +g2839 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp5820 +Rp5821 +(dp5822 +g127 +g0 +(g128 +g2 +Ntp5823 +Rp5824 +(dp5825 +g23 +g132 +sg133 +(dp5826 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xf3?' +p5827 +tp5828 +Rp5829 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p5830 +sg113 +I30 +sg146 +(lp5831 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10012 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5832 +(lp5833 +g189 +ag0 +(g190 +g2 +Ntp5834 +Rp5835 +(dp5836 +g194 +I01 +sg195 +(lp5837 +g0 +(g197 +g2 +Ntp5838 +Rp5839 +(dp5840 +g201 +g176 +(g177 +(I0 +tp5841 +g179 +tp5842 +Rp5843 +(I1 +(I1 +tp5844 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p5845 +tp5846 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5847 +Rp5848 +(dp5849 +g201 +g176 +(g177 +(I0 +tp5850 +g179 +tp5851 +Rp5852 +(I1 +(I2 +tp5853 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5854 +tp5855 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5856 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5857 +g179 +tp5858 +Rp5859 +(I1 +(I1 +I1 +I1 +tp5860 +g38 +I00 +S'\x08\x8a\xd3q\x90\x8a8@' +p5861 +tp5862 +bsg238 +g176 +(g177 +(I0 +tp5863 +g179 +tp5864 +Rp5865 +(I1 +(I1 +I1 +I1 +tp5866 +g38 +I00 +S"\xad\xfb#2\xf9'C?" +p5867 +tp5868 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5869 +g179 +tp5870 +Rp5871 +(I1 +(I1 +I1 +I1 +tp5872 +g38 +I00 +S'|\x15\xb9e\x87\xb5\xe0?' +p5873 +tp5874 +bsg252 +g260 +sg48 +(lp5875 +g0 +(g52 +g2 +Ntp5876 +Rp5877 +(dp5878 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5879 +g179 +tp5880 +Rp5881 +(I1 +(I1 +I1 +I1 +tp5882 +g38 +I00 +S'6F\x0cgF\x7fG@' +p5883 +tp5884 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5885 +g279 +asg113 +I10178 +sg280 +I01 +sbaa(lp5886 +g12 +ag0 +(g190 +g2 +Ntp5887 +Rp5888 +(dp5889 +g194 +I01 +sg195 +(lp5890 +g0 +(g197 +g2 +Ntp5891 +Rp5892 +(dp5893 +g201 +g176 +(g177 +(I0 +tp5894 +g179 +tp5895 +Rp5896 +(I1 +(I1 +tp5897 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p5898 +tp5899 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5900 +Rp5901 +(dp5902 +g201 +g176 +(g177 +(I0 +tp5903 +g179 +tp5904 +Rp5905 +(I1 +(I2 +tp5906 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5907 +tp5908 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5909 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5910 +g179 +tp5911 +Rp5912 +(I1 +(I1 +I1 +I1 +tp5913 +g38 +I00 +S'V\xb9\xd4\x15\x8c1\x10@' +p5914 +tp5915 +bsg238 +g176 +(g177 +(I0 +tp5916 +g179 +tp5917 +Rp5918 +(I1 +(I1 +I1 +I1 +tp5919 +g38 +I00 +S'\xf4\xf1f\x03\x17\xe20?' +p5920 +tp5921 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5922 +g179 +tp5923 +Rp5924 +(I1 +(I1 +I1 +I1 +tp5925 +g38 +I00 +S'\x01z\x1b\nM%\xcb?' +p5926 +tp5927 +bsg252 +g260 +sg48 +(lp5928 +g0 +(g52 +g2 +Ntp5929 +Rp5930 +(dp5931 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5932 +g179 +tp5933 +Rp5934 +(I1 +(I1 +I1 +I1 +tp5935 +g38 +I00 +S'\xc9Q\x1b+:\x163@' +p5936 +tp5937 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5938 +g334 +asg113 +I10179 +sg280 +I01 +sbaatp5939 +Rp5940 +sg337 +I00 +sg338 +Nsbaa(lp5941 +g340 +ag0 +(g341 +g2 +Ntp5942 +Rp5943 +(dp5944 +g17 +g5810 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp5945 +(lp5946 +g189 +ag0 +(g190 +g2 +Ntp5947 +Rp5948 +(dp5949 +g194 +I01 +sg195 +(lp5950 +g0 +(g197 +g2 +Ntp5951 +Rp5952 +(dp5953 +g201 +g176 +(g177 +(I0 +tp5954 +g179 +tp5955 +Rp5956 +(I1 +(I1 +tp5957 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p5958 +tp5959 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp5960 +Rp5961 +(dp5962 +g201 +g176 +(g177 +(I0 +tp5963 +g179 +tp5964 +Rp5965 +(I1 +(I2 +tp5966 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p5967 +tp5968 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp5969 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp5970 +g179 +tp5971 +Rp5972 +(I1 +(I1 +I1 +I1 +tp5973 +g38 +I00 +S'\x08\x8a\xd3q\x90\x8a8@' +p5974 +tp5975 +bsg238 +g176 +(g177 +(I0 +tp5976 +g179 +tp5977 +Rp5978 +(I1 +(I1 +I1 +I1 +tp5979 +g38 +I00 +S"\xad\xfb#2\xf9'C?" +p5980 +tp5981 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp5982 +g179 +tp5983 +Rp5984 +(I1 +(I1 +I1 +I1 +tp5985 +g38 +I00 +S'|\x15\xb9e\x87\xb5\xe0?' +p5986 +tp5987 +bsg252 +g260 +sg48 +(lp5988 +g0 +(g52 +g2 +Ntp5989 +Rp5990 +(dp5991 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp5992 +g179 +tp5993 +Rp5994 +(I1 +(I1 +I1 +I1 +tp5995 +g38 +I00 +S'6F\x0cgF\x7fG@' +p5996 +tp5997 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp5998 +g279 +asg113 +I10182 +sg280 +I01 +sbaa(lp5999 +g401 +ag0 +(g190 +g2 +Ntp6000 +Rp6001 +(dp6002 +g194 +I01 +sg195 +(lp6003 +g0 +(g197 +g2 +Ntp6004 +Rp6005 +(dp6006 +g201 +g176 +(g177 +(I0 +tp6007 +g179 +tp6008 +Rp6009 +(I1 +(I1 +tp6010 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p6011 +tp6012 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6013 +Rp6014 +(dp6015 +g201 +g176 +(g177 +(I0 +tp6016 +g179 +tp6017 +Rp6018 +(I1 +(I2 +tp6019 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6020 +tp6021 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6022 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6023 +g179 +tp6024 +Rp6025 +(I1 +(I1 +I1 +I1 +tp6026 +g38 +I00 +S'\x8d\x1e\x08\xd7\xc5q\xa9?' +p6027 +tp6028 +bsg238 +g176 +(g177 +(I0 +tp6029 +g179 +tp6030 +Rp6031 +(I1 +(I1 +I1 +I1 +tp6032 +g38 +I00 +S'Qh4\x1b\xf3\x18\x0c?' +p6033 +tp6034 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6035 +g179 +tp6036 +Rp6037 +(I1 +(I1 +I1 +I1 +tp6038 +g38 +I00 +S'\xe6_\x0cf\x90\x0e\x98?' +p6039 +tp6040 +bsg252 +g260 +sg48 +(lp6041 +g0 +(g52 +g2 +Ntp6042 +Rp6043 +(dp6044 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6045 +g179 +tp6046 +Rp6047 +(I1 +(I1 +I1 +I1 +tp6048 +g38 +I00 +S'n\xb3\xc0\x87=\xea\x00@' +p6049 +tp6050 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6051 +g454 +asg113 +I10183 +sg280 +I01 +sbaatp6052 +Rp6053 +sg337 +I00 +sg338 +Nsbaa(lp6054 +g458 +ag0 +(g459 +g2 +Ntp6055 +Rp6056 +(dp6057 +g17 +g5810 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6058 +(lp6059 +g189 +ag0 +(g190 +g2 +Ntp6060 +Rp6061 +(dp6062 +g194 +I01 +sg195 +(lp6063 +g0 +(g197 +g2 +Ntp6064 +Rp6065 +(dp6066 +g201 +g176 +(g177 +(I0 +tp6067 +g179 +tp6068 +Rp6069 +(I1 +(I1 +tp6070 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p6071 +tp6072 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6073 +Rp6074 +(dp6075 +g201 +g176 +(g177 +(I0 +tp6076 +g179 +tp6077 +Rp6078 +(I1 +(I2 +tp6079 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6080 +tp6081 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp6082 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6083 +g179 +tp6084 +Rp6085 +(I1 +(I1 +I1 +I1 +tp6086 +g38 +I00 +S'\xc94\xa4\xa9\x13s8@' +p6087 +tp6088 +bsg238 +g176 +(g177 +(I0 +tp6089 +g179 +tp6090 +Rp6091 +(I1 +(I1 +I1 +I1 +tp6092 +g38 +I00 +S'c\xbc\xe8fE\xb2Y?' +p6093 +tp6094 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6095 +g179 +tp6096 +Rp6097 +(I1 +(I1 +I1 +I1 +tp6098 +g38 +I00 +S'\xa8\x812\x00\x0b\xac\xe0?' +p6099 +tp6100 +bsg252 +g513 +sg48 +(lp6101 +g0 +(g52 +g2 +Ntp6102 +Rp6103 +(dp6104 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp6105 +g179 +tp6106 +Rp6107 +(I1 +(I1 +I1 +I1 +tp6108 +g38 +I00 +S'T\x06Gx\xefqG@' +p6109 +tp6110 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp6111 +g527 +asg113 +I10186 +sg280 +I01 +sbaa(lp6112 +g529 +ag0 +(g190 +g2 +Ntp6113 +Rp6114 +(dp6115 +g194 +I01 +sg195 +(lp6116 +g0 +(g197 +g2 +Ntp6117 +Rp6118 +(dp6119 +g201 +g176 +(g177 +(I0 +tp6120 +g179 +tp6121 +Rp6122 +(I1 +(I1 +tp6123 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p6124 +tp6125 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6126 +Rp6127 +(dp6128 +g201 +g176 +(g177 +(I0 +tp6129 +g179 +tp6130 +Rp6131 +(I1 +(I2 +tp6132 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6133 +tp6134 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6135 +Rp6136 +(dp6137 +g201 +g176 +(g177 +(I0 +tp6138 +g179 +tp6139 +Rp6140 +(I1 +(I2 +tp6141 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6142 +tp6143 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp6144 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6145 +g179 +tp6146 +Rp6147 +(I1 +(I1 +I1 +I1 +tp6148 +g38 +I00 +S'Tx\x97\x8b\xf8\x9e\x0b@' +p6149 +tp6150 +bsg238 +g176 +(g177 +(I0 +tp6151 +g179 +tp6152 +Rp6153 +(I1 +(I1 +I1 +I1 +tp6154 +g38 +I00 +S'\xc2\xcf\x88\xce\xb1PC?' +p6155 +tp6156 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6157 +g179 +tp6158 +Rp6159 +(I1 +(I1 +I1 +I1 +tp6160 +g38 +I00 +S'_*\xfa\xf4v\x0f\xc9?' +p6161 +tp6162 +bsg252 +g586 +sg48 +(lp6163 +g0 +(g52 +g2 +Ntp6164 +Rp6165 +(dp6166 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp6167 +g179 +tp6168 +Rp6169 +(I1 +(I1 +I1 +I1 +tp6170 +g38 +I00 +S'\xcb\xe5?\xa4\xdf\x9e1@' +p6171 +tp6172 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp6173 +g600 +asg113 +I10187 +sg280 +I01 +sbaatp6174 +Rp6175 +sg337 +I00 +sg338 +Nsbaa(lp6176 +g604 +ag0 +(g605 +g2 +Ntp6177 +Rp6178 +(dp6179 +g17 +g5810 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6180 +(lp6181 +g611 +ag0 +(g190 +g2 +Ntp6182 +Rp6183 +(dp6184 +g194 +I01 +sg195 +(lp6185 +g0 +(g197 +g2 +Ntp6186 +Rp6187 +(dp6188 +g201 +g176 +(g177 +(I0 +tp6189 +g179 +tp6190 +Rp6191 +(I1 +(I1 +tp6192 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p6193 +tp6194 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6195 +Rp6196 +(dp6197 +g201 +g176 +(g177 +(I0 +tp6198 +g179 +tp6199 +Rp6200 +(I1 +(I2 +tp6201 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6202 +tp6203 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp6204 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6205 +g179 +tp6206 +Rp6207 +(I1 +(I1 +I1 +I1 +tp6208 +g38 +I00 +S'\xb5;\x83\xe9\xa8\xc5\xa8?' +p6209 +tp6210 +bsg238 +g176 +(g177 +(I0 +tp6211 +g179 +tp6212 +Rp6213 +(I1 +(I1 +I1 +I1 +tp6214 +g38 +I00 +S'\x93\xa7\xa5s\x19\x06.?' +p6215 +tp6216 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6217 +g179 +tp6218 +Rp6219 +(I1 +(I1 +I1 +I1 +tp6220 +g38 +I00 +S'6\x85\x04,\x9b\xa3\x97?' +p6221 +tp6222 +bsg252 +g513 +sg48 +(lp6223 +g0 +(g52 +g2 +Ntp6224 +Rp6225 +(dp6226 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp6227 +g179 +tp6228 +Rp6229 +(I1 +(I1 +I1 +I1 +tp6230 +g38 +I00 +S'\xaa-\xf3\x1a\t\x9f\x00@' +p6231 +tp6232 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp6233 +g664 +asg113 +I10190 +sg280 +I01 +sbaa(lp6234 +g666 +ag0 +(g190 +g2 +Ntp6235 +Rp6236 +(dp6237 +g194 +I01 +sg195 +(lp6238 +g0 +(g197 +g2 +Ntp6239 +Rp6240 +(dp6241 +g201 +g176 +(g177 +(I0 +tp6242 +g179 +tp6243 +Rp6244 +(I1 +(I1 +tp6245 +g208 +I00 +S"\x1c'\x00\x00\x00\x00\x00\x00" +p6246 +tp6247 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6248 +Rp6249 +(dp6250 +g201 +g176 +(g177 +(I0 +tp6251 +g179 +tp6252 +Rp6253 +(I1 +(I2 +tp6254 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6255 +tp6256 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp6257 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6258 +g179 +tp6259 +Rp6260 +(I1 +(I1 +I1 +I1 +tp6261 +g38 +I00 +S'\xb8;\x83\xe9\xa8\xc5\xa8?' +p6262 +tp6263 +bsg238 +g176 +(g177 +(I0 +tp6264 +g179 +tp6265 +Rp6266 +(I1 +(I1 +I1 +I1 +tp6267 +g38 +I00 +S'\xb9\xa8\xa5s\x19\x06.?' +p6268 +tp6269 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6270 +g179 +tp6271 +Rp6272 +(I1 +(I1 +I1 +I1 +tp6273 +g38 +I00 +S'6\x85\x04,\x9b\xa3\x97?' +p6274 +tp6275 +bsg252 +g713 +sg48 +(lp6276 +g0 +(g52 +g2 +Ntp6277 +Rp6278 +(dp6279 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp6280 +g179 +tp6281 +Rp6282 +(I1 +(I1 +I1 +I1 +tp6283 +g38 +I00 +S'\xaa-\xf3\x1a\t\x9f\x00@' +p6284 +tp6285 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp6286 +g727 +asg113 +I10191 +sg280 +I01 +sbaatp6287 +Rp6288 +sg337 +I00 +sg338 +Nsbaatp6289 +Rp6290 +aa(lp6291 +I10013 +ag7 +((lp6292 +(lp6293 +g12 +ag0 +(g13 +g2 +Ntp6294 +Rp6295 +(dp6296 +g17 +g0 +(g18 +g2 +Ntp6297 +Rp6298 +(dp6299 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p6300 +sg116 +g0 +(g117 +g2 +Ntp6301 +Rp6302 +(dp6303 +g121 +(lp6304 +g0 +(g123 +g2 +Ntp6305 +Rp6306 +(dp6307 +g127 +g0 +(g128 +g2 +Ntp6308 +Rp6309 +(dp6310 +g23 +g132 +sg133 +(dp6311 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xe0?' +p6312 +tp6313 +Rp6314 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p6315 +sg113 +I32 +sg146 +(lp6316 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp6317 +Rp6318 +(dp6319 +g127 +g0 +(g128 +g2 +Ntp6320 +Rp6321 +(dp6322 +g23 +g132 +sg133 +(dp6323 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xe1?' +p6324 +tp6325 +Rp6326 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p6327 +sg113 +I31 +sg146 +(lp6328 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10013 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6329 +(lp6330 +g189 +ag0 +(g190 +g2 +Ntp6331 +Rp6332 +(dp6333 +g194 +I01 +sg195 +(lp6334 +g0 +(g197 +g2 +Ntp6335 +Rp6336 +(dp6337 +g201 +g176 +(g177 +(I0 +tp6338 +g179 +tp6339 +Rp6340 +(I1 +(I1 +tp6341 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6342 +tp6343 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6344 +Rp6345 +(dp6346 +g201 +g176 +(g177 +(I0 +tp6347 +g179 +tp6348 +Rp6349 +(I1 +(I2 +tp6350 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6351 +tp6352 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6353 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6354 +g179 +tp6355 +Rp6356 +(I1 +(I1 +I1 +I1 +tp6357 +g38 +I00 +S'15)T\xe7p8@' +p6358 +tp6359 +bsg238 +g176 +(g177 +(I0 +tp6360 +g179 +tp6361 +Rp6362 +(I1 +(I1 +I1 +I1 +tp6363 +g38 +I00 +S'7f\xe4\xf8P\xc2C?' +p6364 +tp6365 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6366 +g179 +tp6367 +Rp6368 +(I1 +(I1 +I1 +I1 +tp6369 +g38 +I00 +S'\x15\xa9\x8d\xa1\xc4\xac\xe0?' +p6370 +tp6371 +bsg252 +g260 +sg48 +(lp6372 +g0 +(g52 +g2 +Ntp6373 +Rp6374 +(dp6375 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6376 +g179 +tp6377 +Rp6378 +(I1 +(I1 +I1 +I1 +tp6379 +g38 +I00 +S'\xc65/\x83\xf4rG@' +p6380 +tp6381 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6382 +g279 +asg113 +I10194 +sg280 +I01 +sbaa(lp6383 +g12 +ag0 +(g190 +g2 +Ntp6384 +Rp6385 +(dp6386 +g194 +I01 +sg195 +(lp6387 +g0 +(g197 +g2 +Ntp6388 +Rp6389 +(dp6390 +g201 +g176 +(g177 +(I0 +tp6391 +g179 +tp6392 +Rp6393 +(I1 +(I1 +tp6394 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6395 +tp6396 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6397 +Rp6398 +(dp6399 +g201 +g176 +(g177 +(I0 +tp6400 +g179 +tp6401 +Rp6402 +(I1 +(I2 +tp6403 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6404 +tp6405 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6406 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6407 +g179 +tp6408 +Rp6409 +(I1 +(I1 +I1 +I1 +tp6410 +g38 +I00 +S'Sqc\xd6\xbfJ\x0f@' +p6411 +tp6412 +bsg238 +g176 +(g177 +(I0 +tp6413 +g179 +tp6414 +Rp6415 +(I1 +(I1 +I1 +I1 +tp6416 +g38 +I00 +S'*n\xabI\x8f\xd00?' +p6417 +tp6418 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6419 +g179 +tp6420 +Rp6421 +(I1 +(I1 +I1 +I1 +tp6422 +g38 +I00 +S'vR\x17\x83\xca\xae\xca?' +p6423 +tp6424 +bsg252 +g260 +sg48 +(lp6425 +g0 +(g52 +g2 +Ntp6426 +Rp6427 +(dp6428 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6429 +g179 +tp6430 +Rp6431 +(I1 +(I1 +I1 +I1 +tp6432 +g38 +I00 +S'\xfbe,d\xe6\xc22@' +p6433 +tp6434 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6435 +g334 +asg113 +I10195 +sg280 +I01 +sbaatp6436 +Rp6437 +sg337 +I00 +sg338 +Nsbaa(lp6438 +g340 +ag0 +(g341 +g2 +Ntp6439 +Rp6440 +(dp6441 +g17 +g6298 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6442 +(lp6443 +g189 +ag0 +(g190 +g2 +Ntp6444 +Rp6445 +(dp6446 +g194 +I01 +sg195 +(lp6447 +g0 +(g197 +g2 +Ntp6448 +Rp6449 +(dp6450 +g201 +g176 +(g177 +(I0 +tp6451 +g179 +tp6452 +Rp6453 +(I1 +(I1 +tp6454 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6455 +tp6456 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6457 +Rp6458 +(dp6459 +g201 +g176 +(g177 +(I0 +tp6460 +g179 +tp6461 +Rp6462 +(I1 +(I2 +tp6463 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6464 +tp6465 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6466 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6467 +g179 +tp6468 +Rp6469 +(I1 +(I1 +I1 +I1 +tp6470 +g38 +I00 +S'15)T\xe7p8@' +p6471 +tp6472 +bsg238 +g176 +(g177 +(I0 +tp6473 +g179 +tp6474 +Rp6475 +(I1 +(I1 +I1 +I1 +tp6476 +g38 +I00 +S'7f\xe4\xf8P\xc2C?' +p6477 +tp6478 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6479 +g179 +tp6480 +Rp6481 +(I1 +(I1 +I1 +I1 +tp6482 +g38 +I00 +S'\x15\xa9\x8d\xa1\xc4\xac\xe0?' +p6483 +tp6484 +bsg252 +g260 +sg48 +(lp6485 +g0 +(g52 +g2 +Ntp6486 +Rp6487 +(dp6488 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6489 +g179 +tp6490 +Rp6491 +(I1 +(I1 +I1 +I1 +tp6492 +g38 +I00 +S'\xc65/\x83\xf4rG@' +p6493 +tp6494 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6495 +g279 +asg113 +I10198 +sg280 +I01 +sbaa(lp6496 +g401 +ag0 +(g190 +g2 +Ntp6497 +Rp6498 +(dp6499 +g194 +I01 +sg195 +(lp6500 +g0 +(g197 +g2 +Ntp6501 +Rp6502 +(dp6503 +g201 +g176 +(g177 +(I0 +tp6504 +g179 +tp6505 +Rp6506 +(I1 +(I1 +tp6507 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6508 +tp6509 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6510 +Rp6511 +(dp6512 +g201 +g176 +(g177 +(I0 +tp6513 +g179 +tp6514 +Rp6515 +(I1 +(I2 +tp6516 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6517 +tp6518 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6519 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6520 +g179 +tp6521 +Rp6522 +(I1 +(I1 +I1 +I1 +tp6523 +g38 +I00 +S'\xafS\x8c\xf1\xfa\xcd\xa0?' +p6524 +tp6525 +bsg238 +g176 +(g177 +(I0 +tp6526 +g179 +tp6527 +Rp6528 +(I1 +(I1 +I1 +I1 +tp6529 +g38 +I00 +S'\xe1\x95\xc2V\xee)\x08?' +p6530 +tp6531 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6532 +g179 +tp6533 +Rp6534 +(I1 +(I1 +I1 +I1 +tp6535 +g38 +I00 +S'\xd1\x15\x14\xa0\xc8\x8c\x93?' +p6536 +tp6537 +bsg252 +g260 +sg48 +(lp6538 +g0 +(g52 +g2 +Ntp6539 +Rp6540 +(dp6541 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6542 +g179 +tp6543 +Rp6544 +(I1 +(I1 +I1 +I1 +tp6545 +g38 +I00 +S'\xae>\x1c!\xfa}\xfb?' +p6546 +tp6547 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6548 +g454 +asg113 +I10199 +sg280 +I01 +sbaatp6549 +Rp6550 +sg337 +I00 +sg338 +Nsbaa(lp6551 +g458 +ag0 +(g459 +g2 +Ntp6552 +Rp6553 +(dp6554 +g17 +g6298 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6555 +(lp6556 +g189 +ag0 +(g190 +g2 +Ntp6557 +Rp6558 +(dp6559 +g194 +I01 +sg195 +(lp6560 +g0 +(g197 +g2 +Ntp6561 +Rp6562 +(dp6563 +g201 +g176 +(g177 +(I0 +tp6564 +g179 +tp6565 +Rp6566 +(I1 +(I1 +tp6567 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6568 +tp6569 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6570 +Rp6571 +(dp6572 +g201 +g176 +(g177 +(I0 +tp6573 +g179 +tp6574 +Rp6575 +(I1 +(I2 +tp6576 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6577 +tp6578 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp6579 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6580 +g179 +tp6581 +Rp6582 +(I1 +(I1 +I1 +I1 +tp6583 +g38 +I00 +S'x!\xc0\x00\xa7\x858@' +p6584 +tp6585 +bsg238 +g176 +(g177 +(I0 +tp6586 +g179 +tp6587 +Rp6588 +(I1 +(I1 +I1 +I1 +tp6589 +g38 +I00 +S'\x18} E\x8a\xeaU?' +p6590 +tp6591 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6592 +g179 +tp6593 +Rp6594 +(I1 +(I1 +I1 +I1 +tp6595 +g38 +I00 +S'\xa6\xaa\xd8X\xd8\xb2\xe0?' +p6596 +tp6597 +bsg252 +g513 +sg48 +(lp6598 +g0 +(g52 +g2 +Ntp6599 +Rp6600 +(dp6601 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp6602 +g179 +tp6603 +Rp6604 +(I1 +(I1 +I1 +I1 +tp6605 +g38 +I00 +S'\xfa\xaf\xf0<\x80{G@' +p6606 +tp6607 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp6608 +g527 +asg113 +I10202 +sg280 +I01 +sbaa(lp6609 +g529 +ag0 +(g190 +g2 +Ntp6610 +Rp6611 +(dp6612 +g194 +I01 +sg195 +(lp6613 +g0 +(g197 +g2 +Ntp6614 +Rp6615 +(dp6616 +g201 +g176 +(g177 +(I0 +tp6617 +g179 +tp6618 +Rp6619 +(I1 +(I1 +tp6620 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6621 +tp6622 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6623 +Rp6624 +(dp6625 +g201 +g176 +(g177 +(I0 +tp6626 +g179 +tp6627 +Rp6628 +(I1 +(I2 +tp6629 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6630 +tp6631 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6632 +Rp6633 +(dp6634 +g201 +g176 +(g177 +(I0 +tp6635 +g179 +tp6636 +Rp6637 +(I1 +(I2 +tp6638 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6639 +tp6640 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp6641 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6642 +g179 +tp6643 +Rp6644 +(I1 +(I1 +I1 +I1 +tp6645 +g38 +I00 +S'\xec\xaaP\x0f\x97U\x0b@' +p6646 +tp6647 +bsg238 +g176 +(g177 +(I0 +tp6648 +g179 +tp6649 +Rp6650 +(I1 +(I1 +I1 +I1 +tp6651 +g38 +I00 +S'\xed\xa2\xd1\xa1$\xa3@?' +p6652 +tp6653 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6654 +g179 +tp6655 +Rp6656 +(I1 +(I1 +I1 +I1 +tp6657 +g38 +I00 +S'\x1a\x12l\xab\xbb\xee\xc8?' +p6658 +tp6659 +bsg252 +g586 +sg48 +(lp6660 +g0 +(g52 +g2 +Ntp6661 +Rp6662 +(dp6663 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp6664 +g179 +tp6665 +Rp6666 +(I1 +(I1 +I1 +I1 +tp6667 +g38 +I00 +S'\xba\xfc\x87\xf4\xdb\x871@' +p6668 +tp6669 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp6670 +g600 +asg113 +I10203 +sg280 +I01 +sbaatp6671 +Rp6672 +sg337 +I00 +sg338 +Nsbaa(lp6673 +g604 +ag0 +(g605 +g2 +Ntp6674 +Rp6675 +(dp6676 +g17 +g6298 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6677 +(lp6678 +g611 +ag0 +(g190 +g2 +Ntp6679 +Rp6680 +(dp6681 +g194 +I01 +sg195 +(lp6682 +g0 +(g197 +g2 +Ntp6683 +Rp6684 +(dp6685 +g201 +g176 +(g177 +(I0 +tp6686 +g179 +tp6687 +Rp6688 +(I1 +(I1 +tp6689 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6690 +tp6691 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6692 +Rp6693 +(dp6694 +g201 +g176 +(g177 +(I0 +tp6695 +g179 +tp6696 +Rp6697 +(I1 +(I2 +tp6698 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6699 +tp6700 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp6701 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6702 +g179 +tp6703 +Rp6704 +(I1 +(I1 +I1 +I1 +tp6705 +g38 +I00 +S'\xbc\x81\x0e[\xfbq\xa1?' +p6706 +tp6707 +bsg238 +g176 +(g177 +(I0 +tp6708 +g179 +tp6709 +Rp6710 +(I1 +(I1 +I1 +I1 +tp6711 +g38 +I00 +S'\x16\xd5\xces\xc1\xcb(?' +p6712 +tp6713 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6714 +g179 +tp6715 +Rp6716 +(I1 +(I1 +I1 +I1 +tp6717 +g38 +I00 +S'\xa5\x94H\xe4\x1b\xd7\x93?' +p6718 +tp6719 +bsg252 +g513 +sg48 +(lp6720 +g0 +(g52 +g2 +Ntp6721 +Rp6722 +(dp6723 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp6724 +g179 +tp6725 +Rp6726 +(I1 +(I1 +I1 +I1 +tp6727 +g38 +I00 +S'\x08\x11\x069\x7f\xe6\xfb?' +p6728 +tp6729 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp6730 +g664 +asg113 +I10206 +sg280 +I01 +sbaa(lp6731 +g666 +ag0 +(g190 +g2 +Ntp6732 +Rp6733 +(dp6734 +g194 +I01 +sg195 +(lp6735 +g0 +(g197 +g2 +Ntp6736 +Rp6737 +(dp6738 +g201 +g176 +(g177 +(I0 +tp6739 +g179 +tp6740 +Rp6741 +(I1 +(I1 +tp6742 +g208 +I00 +S"\x1d'\x00\x00\x00\x00\x00\x00" +p6743 +tp6744 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6745 +Rp6746 +(dp6747 +g201 +g176 +(g177 +(I0 +tp6748 +g179 +tp6749 +Rp6750 +(I1 +(I2 +tp6751 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6752 +tp6753 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp6754 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6755 +g179 +tp6756 +Rp6757 +(I1 +(I1 +I1 +I1 +tp6758 +g38 +I00 +S'\xbe\x81\x0e[\xfbq\xa1?' +p6759 +tp6760 +bsg238 +g176 +(g177 +(I0 +tp6761 +g179 +tp6762 +Rp6763 +(I1 +(I1 +I1 +I1 +tp6764 +g38 +I00 +S'\x9f\xd4\xces\xc1\xcb(?' +p6765 +tp6766 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6767 +g179 +tp6768 +Rp6769 +(I1 +(I1 +I1 +I1 +tp6770 +g38 +I00 +S'\xa7\x94H\xe4\x1b\xd7\x93?' +p6771 +tp6772 +bsg252 +g713 +sg48 +(lp6773 +g0 +(g52 +g2 +Ntp6774 +Rp6775 +(dp6776 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp6777 +g179 +tp6778 +Rp6779 +(I1 +(I1 +I1 +I1 +tp6780 +g38 +I00 +S'\x0b\x11\x069\x7f\xe6\xfb?' +p6781 +tp6782 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp6783 +g727 +asg113 +I10207 +sg280 +I01 +sbaatp6784 +Rp6785 +sg337 +I00 +sg338 +Nsbaatp6786 +Rp6787 +aa(lp6788 +I10014 +ag7 +((lp6789 +(lp6790 +g12 +ag0 +(g13 +g2 +Ntp6791 +Rp6792 +(dp6793 +g17 +g0 +(g18 +g2 +Ntp6794 +Rp6795 +(dp6796 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p6797 +sg116 +g0 +(g117 +g2 +Ntp6798 +Rp6799 +(dp6800 +g121 +(lp6801 +g0 +(g123 +g2 +Ntp6802 +Rp6803 +(dp6804 +g127 +g0 +(g128 +g2 +Ntp6805 +Rp6806 +(dp6807 +g23 +g132 +sg133 +(dp6808 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xfe?' +p6809 +tp6810 +Rp6811 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p6812 +sg113 +I33 +sg146 +(lp6813 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp6814 +Rp6815 +(dp6816 +g127 +g0 +(g128 +g2 +Ntp6817 +Rp6818 +(dp6819 +g23 +g132 +sg133 +(dp6820 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xfd?' +p6821 +tp6822 +Rp6823 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p6824 +sg113 +I34 +sg146 +(lp6825 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10014 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6826 +(lp6827 +g189 +ag0 +(g190 +g2 +Ntp6828 +Rp6829 +(dp6830 +g194 +I01 +sg195 +(lp6831 +g0 +(g197 +g2 +Ntp6832 +Rp6833 +(dp6834 +g201 +g176 +(g177 +(I0 +tp6835 +g179 +tp6836 +Rp6837 +(I1 +(I1 +tp6838 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p6839 +tp6840 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6841 +Rp6842 +(dp6843 +g201 +g176 +(g177 +(I0 +tp6844 +g179 +tp6845 +Rp6846 +(I1 +(I2 +tp6847 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6848 +tp6849 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6850 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6851 +g179 +tp6852 +Rp6853 +(I1 +(I1 +I1 +I1 +tp6854 +g38 +I00 +S't\x91b?\xc7\x818@' +p6855 +tp6856 +bsg238 +g176 +(g177 +(I0 +tp6857 +g179 +tp6858 +Rp6859 +(I1 +(I1 +I1 +I1 +tp6860 +g38 +I00 +S'\x1d\x16\xcag\x1b\x01A?' +p6861 +tp6862 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6863 +g179 +tp6864 +Rp6865 +(I1 +(I1 +I1 +I1 +tp6866 +g38 +I00 +S"\xe2'QP\x96\xb2\xe0?" +p6867 +tp6868 +bsg252 +g260 +sg48 +(lp6869 +g0 +(g52 +g2 +Ntp6870 +Rp6871 +(dp6872 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6873 +g179 +tp6874 +Rp6875 +(I1 +(I1 +I1 +I1 +tp6876 +g38 +I00 +S'\x16 \xf2`#{G@' +p6877 +tp6878 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6879 +g279 +asg113 +I10210 +sg280 +I01 +sbaa(lp6880 +g12 +ag0 +(g190 +g2 +Ntp6881 +Rp6882 +(dp6883 +g194 +I01 +sg195 +(lp6884 +g0 +(g197 +g2 +Ntp6885 +Rp6886 +(dp6887 +g201 +g176 +(g177 +(I0 +tp6888 +g179 +tp6889 +Rp6890 +(I1 +(I1 +tp6891 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p6892 +tp6893 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6894 +Rp6895 +(dp6896 +g201 +g176 +(g177 +(I0 +tp6897 +g179 +tp6898 +Rp6899 +(I1 +(I2 +tp6900 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6901 +tp6902 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6903 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6904 +g179 +tp6905 +Rp6906 +(I1 +(I1 +I1 +I1 +tp6907 +g38 +I00 +S'Oq[\xa0\xba7\x12@' +p6908 +tp6909 +bsg238 +g176 +(g177 +(I0 +tp6910 +g179 +tp6911 +Rp6912 +(I1 +(I1 +I1 +I1 +tp6913 +g38 +I00 +S'\xf5\x8af\xab\xa0\x170?' +p6914 +tp6915 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6916 +g179 +tp6917 +Rp6918 +(I1 +(I1 +I1 +I1 +tp6919 +g38 +I00 +S'\xcbk\x0cB\xee\xca\xcc?' +p6920 +tp6921 +bsg252 +g260 +sg48 +(lp6922 +g0 +(g52 +g2 +Ntp6923 +Rp6924 +(dp6925 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6926 +g179 +tp6927 +Rp6928 +(I1 +(I1 +I1 +I1 +tp6929 +g38 +I00 +S'\xcb\xbbp\x86\xaf>4@' +p6930 +tp6931 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6932 +g334 +asg113 +I10211 +sg280 +I01 +sbaatp6933 +Rp6934 +sg337 +I00 +sg338 +Nsbaa(lp6935 +g340 +ag0 +(g341 +g2 +Ntp6936 +Rp6937 +(dp6938 +g17 +g6795 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp6939 +(lp6940 +g189 +ag0 +(g190 +g2 +Ntp6941 +Rp6942 +(dp6943 +g194 +I01 +sg195 +(lp6944 +g0 +(g197 +g2 +Ntp6945 +Rp6946 +(dp6947 +g201 +g176 +(g177 +(I0 +tp6948 +g179 +tp6949 +Rp6950 +(I1 +(I1 +tp6951 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p6952 +tp6953 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp6954 +Rp6955 +(dp6956 +g201 +g176 +(g177 +(I0 +tp6957 +g179 +tp6958 +Rp6959 +(I1 +(I2 +tp6960 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p6961 +tp6962 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp6963 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp6964 +g179 +tp6965 +Rp6966 +(I1 +(I1 +I1 +I1 +tp6967 +g38 +I00 +S't\x91b?\xc7\x818@' +p6968 +tp6969 +bsg238 +g176 +(g177 +(I0 +tp6970 +g179 +tp6971 +Rp6972 +(I1 +(I1 +I1 +I1 +tp6973 +g38 +I00 +S'\x1d\x16\xcag\x1b\x01A?' +p6974 +tp6975 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp6976 +g179 +tp6977 +Rp6978 +(I1 +(I1 +I1 +I1 +tp6979 +g38 +I00 +S"\xe2'QP\x96\xb2\xe0?" +p6980 +tp6981 +bsg252 +g260 +sg48 +(lp6982 +g0 +(g52 +g2 +Ntp6983 +Rp6984 +(dp6985 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp6986 +g179 +tp6987 +Rp6988 +(I1 +(I1 +I1 +I1 +tp6989 +g38 +I00 +S'\x16 \xf2`#{G@' +p6990 +tp6991 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp6992 +g279 +asg113 +I10214 +sg280 +I01 +sbaa(lp6993 +g401 +ag0 +(g190 +g2 +Ntp6994 +Rp6995 +(dp6996 +g194 +I01 +sg195 +(lp6997 +g0 +(g197 +g2 +Ntp6998 +Rp6999 +(dp7000 +g201 +g176 +(g177 +(I0 +tp7001 +g179 +tp7002 +Rp7003 +(I1 +(I1 +tp7004 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p7005 +tp7006 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7007 +Rp7008 +(dp7009 +g201 +g176 +(g177 +(I0 +tp7010 +g179 +tp7011 +Rp7012 +(I1 +(I2 +tp7013 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7014 +tp7015 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7016 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7017 +g179 +tp7018 +Rp7019 +(I1 +(I1 +I1 +I1 +tp7020 +g38 +I00 +S'\xc4\xf4\r$\xba\xbd\xbe?' +p7021 +tp7022 +bsg238 +g176 +(g177 +(I0 +tp7023 +g179 +tp7024 +Rp7025 +(I1 +(I1 +I1 +I1 +tp7026 +g38 +I00 +S'\x96\xb8\x0c\x9a\xfd\xdb\x12?' +p7027 +tp7028 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7029 +g179 +tp7030 +Rp7031 +(I1 +(I1 +I1 +I1 +tp7032 +g38 +I00 +S'\xc1\xb0\xf9(\xe4\xb2\xa2?' +p7033 +tp7034 +bsg252 +g260 +sg48 +(lp7035 +g0 +(g52 +g2 +Ntp7036 +Rp7037 +(dp7038 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7039 +g179 +tp7040 +Rp7041 +(I1 +(I1 +I1 +I1 +tp7042 +g38 +I00 +S'\x8f \x9f\xd9\x90K\n@' +p7043 +tp7044 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7045 +g454 +asg113 +I10215 +sg280 +I01 +sbaatp7046 +Rp7047 +sg337 +I00 +sg338 +Nsbaa(lp7048 +g458 +ag0 +(g459 +g2 +Ntp7049 +Rp7050 +(dp7051 +g17 +g6795 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7052 +(lp7053 +g189 +ag0 +(g190 +g2 +Ntp7054 +Rp7055 +(dp7056 +g194 +I01 +sg195 +(lp7057 +g0 +(g197 +g2 +Ntp7058 +Rp7059 +(dp7060 +g201 +g176 +(g177 +(I0 +tp7061 +g179 +tp7062 +Rp7063 +(I1 +(I1 +tp7064 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p7065 +tp7066 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7067 +Rp7068 +(dp7069 +g201 +g176 +(g177 +(I0 +tp7070 +g179 +tp7071 +Rp7072 +(I1 +(I2 +tp7073 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7074 +tp7075 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp7076 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7077 +g179 +tp7078 +Rp7079 +(I1 +(I1 +I1 +I1 +tp7080 +g38 +I00 +S'\xff\xb8\xba\xdfGK8@' +p7081 +tp7082 +bsg238 +g176 +(g177 +(I0 +tp7083 +g179 +tp7084 +Rp7085 +(I1 +(I1 +I1 +I1 +tp7086 +g38 +I00 +S'Jw\x93\xa2\xa1\xe7S?' +p7087 +tp7088 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7089 +g179 +tp7090 +Rp7091 +(I1 +(I1 +I1 +I1 +tp7092 +g38 +I00 +S'\x13\xb67\xec!\x9f\xe0?' +p7093 +tp7094 +bsg252 +g513 +sg48 +(lp7095 +g0 +(g52 +g2 +Ntp7096 +Rp7097 +(dp7098 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp7099 +g179 +tp7100 +Rp7101 +(I1 +(I1 +I1 +I1 +tp7102 +g38 +I00 +S'\x0bX.\xb4\xc7_G@' +p7103 +tp7104 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp7105 +g527 +asg113 +I10218 +sg280 +I01 +sbaa(lp7106 +g529 +ag0 +(g190 +g2 +Ntp7107 +Rp7108 +(dp7109 +g194 +I01 +sg195 +(lp7110 +g0 +(g197 +g2 +Ntp7111 +Rp7112 +(dp7113 +g201 +g176 +(g177 +(I0 +tp7114 +g179 +tp7115 +Rp7116 +(I1 +(I1 +tp7117 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p7118 +tp7119 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7120 +Rp7121 +(dp7122 +g201 +g176 +(g177 +(I0 +tp7123 +g179 +tp7124 +Rp7125 +(I1 +(I2 +tp7126 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7127 +tp7128 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7129 +Rp7130 +(dp7131 +g201 +g176 +(g177 +(I0 +tp7132 +g179 +tp7133 +Rp7134 +(I1 +(I2 +tp7135 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7136 +tp7137 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp7138 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7139 +g179 +tp7140 +Rp7141 +(I1 +(I1 +I1 +I1 +tp7142 +g38 +I00 +S'\xfdA#\xf9\xc6\x7f\x0c@' +p7143 +tp7144 +bsg238 +g176 +(g177 +(I0 +tp7145 +g179 +tp7146 +Rp7147 +(I1 +(I1 +I1 +I1 +tp7148 +g38 +I00 +S'\x17K$\xa5\x9dn??' +p7149 +tp7150 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7151 +g179 +tp7152 +Rp7153 +(I1 +(I1 +I1 +I1 +tp7154 +g38 +I00 +S'\xcb\x1d\xaes\x97u\xc9?' +p7155 +tp7156 +bsg252 +g586 +sg48 +(lp7157 +g0 +(g52 +g2 +Ntp7158 +Rp7159 +(dp7160 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp7161 +g179 +tp7162 +Rp7163 +(I1 +(I1 +I1 +I1 +tp7164 +g38 +I00 +S'\xf3lV}\xae\xe61@' +p7165 +tp7166 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp7167 +g600 +asg113 +I10219 +sg280 +I01 +sbaatp7168 +Rp7169 +sg337 +I00 +sg338 +Nsbaa(lp7170 +g604 +ag0 +(g605 +g2 +Ntp7171 +Rp7172 +(dp7173 +g17 +g6795 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7174 +(lp7175 +g611 +ag0 +(g190 +g2 +Ntp7176 +Rp7177 +(dp7178 +g194 +I01 +sg195 +(lp7179 +g0 +(g197 +g2 +Ntp7180 +Rp7181 +(dp7182 +g201 +g176 +(g177 +(I0 +tp7183 +g179 +tp7184 +Rp7185 +(I1 +(I1 +tp7186 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p7187 +tp7188 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7189 +Rp7190 +(dp7191 +g201 +g176 +(g177 +(I0 +tp7192 +g179 +tp7193 +Rp7194 +(I1 +(I2 +tp7195 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7196 +tp7197 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp7198 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7199 +g179 +tp7200 +Rp7201 +(I1 +(I1 +I1 +I1 +tp7202 +g38 +I00 +S'\xe2\xbdZ\xb1\xafY\xbe?' +p7203 +tp7204 +bsg238 +g176 +(g177 +(I0 +tp7205 +g179 +tp7206 +Rp7207 +(I1 +(I1 +I1 +I1 +tp7208 +g38 +I00 +S'\xf8\x01B\xc8\xa0K2?' +p7209 +tp7210 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7211 +g179 +tp7212 +Rp7213 +(I1 +(I1 +I1 +I1 +tp7214 +g38 +I00 +S'\x1a,2\x0b\xa6\x88\xa2?' +p7215 +tp7216 +bsg252 +g513 +sg48 +(lp7217 +g0 +(g52 +g2 +Ntp7218 +Rp7219 +(dp7220 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp7221 +g179 +tp7222 +Rp7223 +(I1 +(I1 +I1 +I1 +tp7224 +g38 +I00 +S'\x04\x8e\xbe\x7f)\x10\n@' +p7225 +tp7226 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp7227 +g664 +asg113 +I10222 +sg280 +I01 +sbaa(lp7228 +g666 +ag0 +(g190 +g2 +Ntp7229 +Rp7230 +(dp7231 +g194 +I01 +sg195 +(lp7232 +g0 +(g197 +g2 +Ntp7233 +Rp7234 +(dp7235 +g201 +g176 +(g177 +(I0 +tp7236 +g179 +tp7237 +Rp7238 +(I1 +(I1 +tp7239 +g208 +I00 +S"\x1e'\x00\x00\x00\x00\x00\x00" +p7240 +tp7241 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7242 +Rp7243 +(dp7244 +g201 +g176 +(g177 +(I0 +tp7245 +g179 +tp7246 +Rp7247 +(I1 +(I2 +tp7248 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7249 +tp7250 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp7251 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7252 +g179 +tp7253 +Rp7254 +(I1 +(I1 +I1 +I1 +tp7255 +g38 +I00 +S'\xe3\xbdZ\xb1\xafY\xbe?' +p7256 +tp7257 +bsg238 +g176 +(g177 +(I0 +tp7258 +g179 +tp7259 +Rp7260 +(I1 +(I1 +I1 +I1 +tp7261 +g38 +I00 +S'f\x00B\xc8\xa0K2?' +p7262 +tp7263 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7264 +g179 +tp7265 +Rp7266 +(I1 +(I1 +I1 +I1 +tp7267 +g38 +I00 +S'\x1c,2\x0b\xa6\x88\xa2?' +p7268 +tp7269 +bsg252 +g713 +sg48 +(lp7270 +g0 +(g52 +g2 +Ntp7271 +Rp7272 +(dp7273 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp7274 +g179 +tp7275 +Rp7276 +(I1 +(I1 +I1 +I1 +tp7277 +g38 +I00 +S'\x07\x8e\xbe\x7f)\x10\n@' +p7278 +tp7279 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp7280 +g727 +asg113 +I10223 +sg280 +I01 +sbaatp7281 +Rp7282 +sg337 +I00 +sg338 +Nsbaatp7283 +Rp7284 +aa(lp7285 +I10015 +ag7 +((lp7286 +(lp7287 +g12 +ag0 +(g13 +g2 +Ntp7288 +Rp7289 +(dp7290 +g17 +g0 +(g18 +g2 +Ntp7291 +Rp7292 +(dp7293 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p7294 +sg116 +g0 +(g117 +g2 +Ntp7295 +Rp7296 +(dp7297 +g121 +(lp7298 +g0 +(g123 +g2 +Ntp7299 +Rp7300 +(dp7301 +g127 +g0 +(g128 +g2 +Ntp7302 +Rp7303 +(dp7304 +g23 +g132 +sg133 +(dp7305 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xaeG\xe1z\x14\xae\x0f@' +p7306 +tp7307 +Rp7308 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p7309 +sg113 +I35 +sg146 +(lp7310 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp7311 +Rp7312 +(dp7313 +g127 +g0 +(g128 +g2 +Ntp7314 +Rp7315 +(dp7316 +g23 +g132 +sg133 +(dp7317 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x19\x10@' +p7318 +tp7319 +Rp7320 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p7321 +sg113 +I36 +sg146 +(lp7322 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10015 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7323 +(lp7324 +g189 +ag0 +(g190 +g2 +Ntp7325 +Rp7326 +(dp7327 +g194 +I01 +sg195 +(lp7328 +g0 +(g197 +g2 +Ntp7329 +Rp7330 +(dp7331 +g201 +g176 +(g177 +(I0 +tp7332 +g179 +tp7333 +Rp7334 +(I1 +(I1 +tp7335 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7336 +tp7337 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7338 +Rp7339 +(dp7340 +g201 +g176 +(g177 +(I0 +tp7341 +g179 +tp7342 +Rp7343 +(I1 +(I2 +tp7344 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7345 +tp7346 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7347 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7348 +g179 +tp7349 +Rp7350 +(I1 +(I1 +I1 +I1 +tp7351 +g38 +I00 +S'y\xe5nOc\x9cH@' +p7352 +tp7353 +bsg238 +g176 +(g177 +(I0 +tp7354 +g179 +tp7355 +Rp7356 +(I1 +(I1 +I1 +I1 +tp7357 +g38 +I00 +S'\x0b\xb6\xf9\x9e\x0fSD?' +p7358 +tp7359 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7360 +g179 +tp7361 +Rp7362 +(I1 +(I1 +I1 +I1 +tp7363 +g38 +I00 +S'd\xa9|\x04\x10\xaa\xe7?' +p7364 +tp7365 +bsg252 +g260 +sg48 +(lp7366 +g0 +(g52 +g2 +Ntp7367 +Rp7368 +(dp7369 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7370 +g179 +tp7371 +Rp7372 +(I1 +(I1 +I1 +I1 +tp7373 +g38 +I00 +S"\x1a\xa7'C\x93\xa3P@" +p7374 +tp7375 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7376 +g279 +asg113 +I10226 +sg280 +I01 +sbaa(lp7377 +g12 +ag0 +(g190 +g2 +Ntp7378 +Rp7379 +(dp7380 +g194 +I01 +sg195 +(lp7381 +g0 +(g197 +g2 +Ntp7382 +Rp7383 +(dp7384 +g201 +g176 +(g177 +(I0 +tp7385 +g179 +tp7386 +Rp7387 +(I1 +(I1 +tp7388 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7389 +tp7390 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7391 +Rp7392 +(dp7393 +g201 +g176 +(g177 +(I0 +tp7394 +g179 +tp7395 +Rp7396 +(I1 +(I2 +tp7397 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7398 +tp7399 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7400 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7401 +g179 +tp7402 +Rp7403 +(I1 +(I1 +I1 +I1 +tp7404 +g38 +I00 +S'v\xd2\x82X\xf6\x98K@' +p7405 +tp7406 +bsg238 +g176 +(g177 +(I0 +tp7407 +g179 +tp7408 +Rp7409 +(I1 +(I1 +I1 +I1 +tp7410 +g38 +I00 +S'Ybe\xc2\xa9\xeaM?' +p7411 +tp7412 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7413 +g179 +tp7414 +Rp7415 +(I1 +(I1 +I1 +I1 +tp7416 +g38 +I00 +S'\x94D\x1f\xbc\xef\x0e\xe9?' +p7417 +tp7418 +bsg252 +g260 +sg48 +(lp7419 +g0 +(g52 +g2 +Ntp7420 +Rp7421 +(dp7422 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7423 +g179 +tp7424 +Rp7425 +(I1 +(I1 +I1 +I1 +tp7426 +g38 +I00 +S'8\xfcE\x90\x80\x9eQ@' +p7427 +tp7428 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7429 +g334 +asg113 +I10227 +sg280 +I01 +sbaatp7430 +Rp7431 +sg337 +I00 +sg338 +Nsbaa(lp7432 +g340 +ag0 +(g341 +g2 +Ntp7433 +Rp7434 +(dp7435 +g17 +g7292 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7436 +(lp7437 +g189 +ag0 +(g190 +g2 +Ntp7438 +Rp7439 +(dp7440 +g194 +I01 +sg195 +(lp7441 +g0 +(g197 +g2 +Ntp7442 +Rp7443 +(dp7444 +g201 +g176 +(g177 +(I0 +tp7445 +g179 +tp7446 +Rp7447 +(I1 +(I1 +tp7448 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7449 +tp7450 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7451 +Rp7452 +(dp7453 +g201 +g176 +(g177 +(I0 +tp7454 +g179 +tp7455 +Rp7456 +(I1 +(I2 +tp7457 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7458 +tp7459 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7460 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7461 +g179 +tp7462 +Rp7463 +(I1 +(I1 +I1 +I1 +tp7464 +g38 +I00 +S'y\xe5nOc\x9cH@' +p7465 +tp7466 +bsg238 +g176 +(g177 +(I0 +tp7467 +g179 +tp7468 +Rp7469 +(I1 +(I1 +I1 +I1 +tp7470 +g38 +I00 +S'\x0b\xb6\xf9\x9e\x0fSD?' +p7471 +tp7472 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7473 +g179 +tp7474 +Rp7475 +(I1 +(I1 +I1 +I1 +tp7476 +g38 +I00 +S'd\xa9|\x04\x10\xaa\xe7?' +p7477 +tp7478 +bsg252 +g260 +sg48 +(lp7479 +g0 +(g52 +g2 +Ntp7480 +Rp7481 +(dp7482 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7483 +g179 +tp7484 +Rp7485 +(I1 +(I1 +I1 +I1 +tp7486 +g38 +I00 +S"\x1a\xa7'C\x93\xa3P@" +p7487 +tp7488 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7489 +g279 +asg113 +I10230 +sg280 +I01 +sbaa(lp7490 +g401 +ag0 +(g190 +g2 +Ntp7491 +Rp7492 +(dp7493 +g194 +I01 +sg195 +(lp7494 +g0 +(g197 +g2 +Ntp7495 +Rp7496 +(dp7497 +g201 +g176 +(g177 +(I0 +tp7498 +g179 +tp7499 +Rp7500 +(I1 +(I1 +tp7501 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7502 +tp7503 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7504 +Rp7505 +(dp7506 +g201 +g176 +(g177 +(I0 +tp7507 +g179 +tp7508 +Rp7509 +(I1 +(I2 +tp7510 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7511 +tp7512 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7513 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7514 +g179 +tp7515 +Rp7516 +(I1 +(I1 +I1 +I1 +tp7517 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7518 +tp7519 +bsg238 +g176 +(g177 +(I0 +tp7520 +g179 +tp7521 +Rp7522 +(I1 +(I1 +I1 +I1 +tp7523 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7524 +tp7525 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7526 +g179 +tp7527 +Rp7528 +(I1 +(I1 +I1 +I1 +tp7529 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7530 +tp7531 +bsg252 +g260 +sg48 +(lp7532 +g0 +(g52 +g2 +Ntp7533 +Rp7534 +(dp7535 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7536 +g179 +tp7537 +Rp7538 +(I1 +(I1 +I1 +I1 +tp7539 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7540 +tp7541 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7542 +g454 +asg113 +I10231 +sg280 +I01 +sbaatp7543 +Rp7544 +sg337 +I00 +sg338 +Nsbaa(lp7545 +g458 +ag0 +(g459 +g2 +Ntp7546 +Rp7547 +(dp7548 +g17 +g7292 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7549 +(lp7550 +g189 +ag0 +(g190 +g2 +Ntp7551 +Rp7552 +(dp7553 +g194 +I01 +sg195 +(lp7554 +g0 +(g197 +g2 +Ntp7555 +Rp7556 +(dp7557 +g201 +g176 +(g177 +(I0 +tp7558 +g179 +tp7559 +Rp7560 +(I1 +(I1 +tp7561 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7562 +tp7563 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7564 +Rp7565 +(dp7566 +g201 +g176 +(g177 +(I0 +tp7567 +g179 +tp7568 +Rp7569 +(I1 +(I2 +tp7570 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7571 +tp7572 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp7573 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7574 +g179 +tp7575 +Rp7576 +(I1 +(I1 +I1 +I1 +tp7577 +g38 +I00 +S'\xc6\xf1\x03\xf9\xa2\xbeH@' +p7578 +tp7579 +bsg238 +g176 +(g177 +(I0 +tp7580 +g179 +tp7581 +Rp7582 +(I1 +(I1 +I1 +I1 +tp7583 +g38 +I00 +S'\\\x98\x94\x8b65T?' +p7584 +tp7585 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7586 +g179 +tp7587 +Rp7588 +(I1 +(I1 +I1 +I1 +tp7589 +g38 +I00 +S'\r9H\xbe\xf2\xb9\xe7?' +p7590 +tp7591 +bsg252 +g513 +sg48 +(lp7592 +g0 +(g52 +g2 +Ntp7593 +Rp7594 +(dp7595 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp7596 +g179 +tp7597 +Rp7598 +(I1 +(I1 +I1 +I1 +tp7599 +g38 +I00 +S'\x1d\xc8\xca\xad\xbe\xaeP@' +p7600 +tp7601 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp7602 +g527 +asg113 +I10234 +sg280 +I01 +sbaa(lp7603 +g529 +ag0 +(g190 +g2 +Ntp7604 +Rp7605 +(dp7606 +g194 +I01 +sg195 +(lp7607 +g0 +(g197 +g2 +Ntp7608 +Rp7609 +(dp7610 +g201 +g176 +(g177 +(I0 +tp7611 +g179 +tp7612 +Rp7613 +(I1 +(I1 +tp7614 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7615 +tp7616 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7617 +Rp7618 +(dp7619 +g201 +g176 +(g177 +(I0 +tp7620 +g179 +tp7621 +Rp7622 +(I1 +(I2 +tp7623 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7624 +tp7625 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7626 +Rp7627 +(dp7628 +g201 +g176 +(g177 +(I0 +tp7629 +g179 +tp7630 +Rp7631 +(I1 +(I2 +tp7632 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7633 +tp7634 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp7635 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7636 +g179 +tp7637 +Rp7638 +(I1 +(I1 +I1 +I1 +tp7639 +g38 +I00 +S'\xfe\x0e\xfb\xf3\xa3\x15K@' +p7640 +tp7641 +bsg238 +g176 +(g177 +(I0 +tp7642 +g179 +tp7643 +Rp7644 +(I1 +(I1 +I1 +I1 +tp7645 +g38 +I00 +S'm\x18t\xa0\x0c4U?' +p7646 +tp7647 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7648 +g179 +tp7649 +Rp7650 +(I1 +(I1 +I1 +I1 +tp7651 +g38 +I00 +S'f\xa91p\xa2\xd2\xe8?' +p7652 +tp7653 +bsg252 +g586 +sg48 +(lp7654 +g0 +(g52 +g2 +Ntp7655 +Rp7656 +(dp7657 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp7658 +g179 +tp7659 +Rp7660 +(I1 +(I1 +I1 +I1 +tp7661 +g38 +I00 +S'\x1c\xeb\xe26\x1atQ@' +p7662 +tp7663 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp7664 +g600 +asg113 +I10235 +sg280 +I01 +sbaatp7665 +Rp7666 +sg337 +I00 +sg338 +Nsbaa(lp7667 +g604 +ag0 +(g605 +g2 +Ntp7668 +Rp7669 +(dp7670 +g17 +g7292 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7671 +(lp7672 +g611 +ag0 +(g190 +g2 +Ntp7673 +Rp7674 +(dp7675 +g194 +I01 +sg195 +(lp7676 +g0 +(g197 +g2 +Ntp7677 +Rp7678 +(dp7679 +g201 +g176 +(g177 +(I0 +tp7680 +g179 +tp7681 +Rp7682 +(I1 +(I1 +tp7683 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7684 +tp7685 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7686 +Rp7687 +(dp7688 +g201 +g176 +(g177 +(I0 +tp7689 +g179 +tp7690 +Rp7691 +(I1 +(I2 +tp7692 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7693 +tp7694 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp7695 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7696 +g179 +tp7697 +Rp7698 +(I1 +(I1 +I1 +I1 +tp7699 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7700 +tp7701 +bsg238 +g176 +(g177 +(I0 +tp7702 +g179 +tp7703 +Rp7704 +(I1 +(I1 +I1 +I1 +tp7705 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7706 +tp7707 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7708 +g179 +tp7709 +Rp7710 +(I1 +(I1 +I1 +I1 +tp7711 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7712 +tp7713 +bsg252 +g513 +sg48 +(lp7714 +g0 +(g52 +g2 +Ntp7715 +Rp7716 +(dp7717 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp7718 +g179 +tp7719 +Rp7720 +(I1 +(I1 +I1 +I1 +tp7721 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7722 +tp7723 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp7724 +g664 +asg113 +I10238 +sg280 +I01 +sbaa(lp7725 +g666 +ag0 +(g190 +g2 +Ntp7726 +Rp7727 +(dp7728 +g194 +I01 +sg195 +(lp7729 +g0 +(g197 +g2 +Ntp7730 +Rp7731 +(dp7732 +g201 +g176 +(g177 +(I0 +tp7733 +g179 +tp7734 +Rp7735 +(I1 +(I1 +tp7736 +g208 +I00 +S"\x1f'\x00\x00\x00\x00\x00\x00" +p7737 +tp7738 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7739 +Rp7740 +(dp7741 +g201 +g176 +(g177 +(I0 +tp7742 +g179 +tp7743 +Rp7744 +(I1 +(I2 +tp7745 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7746 +tp7747 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp7748 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7749 +g179 +tp7750 +Rp7751 +(I1 +(I1 +I1 +I1 +tp7752 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7753 +tp7754 +bsg238 +g176 +(g177 +(I0 +tp7755 +g179 +tp7756 +Rp7757 +(I1 +(I1 +I1 +I1 +tp7758 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7759 +tp7760 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7761 +g179 +tp7762 +Rp7763 +(I1 +(I1 +I1 +I1 +tp7764 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7765 +tp7766 +bsg252 +g713 +sg48 +(lp7767 +g0 +(g52 +g2 +Ntp7768 +Rp7769 +(dp7770 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp7771 +g179 +tp7772 +Rp7773 +(I1 +(I1 +I1 +I1 +tp7774 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7775 +tp7776 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp7777 +g727 +asg113 +I10239 +sg280 +I01 +sbaatp7778 +Rp7779 +sg337 +I00 +sg338 +Nsbaatp7780 +Rp7781 +aa(lp7782 +I10016 +ag7 +((lp7783 +(lp7784 +g12 +ag0 +(g13 +g2 +Ntp7785 +Rp7786 +(dp7787 +g17 +g0 +(g18 +g2 +Ntp7788 +Rp7789 +(dp7790 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p7791 +sg116 +g0 +(g117 +g2 +Ntp7792 +Rp7793 +(dp7794 +g121 +(lp7795 +g0 +(g123 +g2 +Ntp7796 +Rp7797 +(dp7798 +g127 +g7315 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp7799 +Rp7800 +(dp7801 +g127 +g4827 +sg148 +g149 +sbasbsg163 +Nsg113 +I10016 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7802 +(lp7803 +g189 +ag0 +(g190 +g2 +Ntp7804 +Rp7805 +(dp7806 +g194 +I01 +sg195 +(lp7807 +g0 +(g197 +g2 +Ntp7808 +Rp7809 +(dp7810 +g201 +g176 +(g177 +(I0 +tp7811 +g179 +tp7812 +Rp7813 +(I1 +(I1 +tp7814 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p7815 +tp7816 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7817 +Rp7818 +(dp7819 +g201 +g176 +(g177 +(I0 +tp7820 +g179 +tp7821 +Rp7822 +(I1 +(I2 +tp7823 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7824 +tp7825 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7826 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7827 +g179 +tp7828 +Rp7829 +(I1 +(I1 +I1 +I1 +tp7830 +g38 +I00 +S'=*\xd4ui\xb4H@' +p7831 +tp7832 +bsg238 +g176 +(g177 +(I0 +tp7833 +g179 +tp7834 +Rp7835 +(I1 +(I1 +I1 +I1 +tp7836 +g38 +I00 +S'nEu\xe6\x1d\xd8C?' +p7837 +tp7838 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7839 +g179 +tp7840 +Rp7841 +(I1 +(I1 +I1 +I1 +tp7842 +g38 +I00 +S'\xcer\x18t\x9c\xb5\xe7?' +p7843 +tp7844 +bsg252 +g260 +sg48 +(lp7845 +g0 +(g52 +g2 +Ntp7846 +Rp7847 +(dp7848 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7849 +g179 +tp7850 +Rp7851 +(I1 +(I1 +I1 +I1 +tp7852 +g38 +I00 +S'\xb90\xa1\x01\xb2\xabP@' +p7853 +tp7854 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7855 +g279 +asg113 +I10242 +sg280 +I01 +sbaa(lp7856 +g12 +ag0 +(g190 +g2 +Ntp7857 +Rp7858 +(dp7859 +g194 +I01 +sg195 +(lp7860 +g0 +(g197 +g2 +Ntp7861 +Rp7862 +(dp7863 +g201 +g176 +(g177 +(I0 +tp7864 +g179 +tp7865 +Rp7866 +(I1 +(I1 +tp7867 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p7868 +tp7869 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7870 +Rp7871 +(dp7872 +g201 +g176 +(g177 +(I0 +tp7873 +g179 +tp7874 +Rp7875 +(I1 +(I2 +tp7876 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7877 +tp7878 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7879 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7880 +g179 +tp7881 +Rp7882 +(I1 +(I1 +I1 +I1 +tp7883 +g38 +I00 +S'\x19\xdb2\x0c\xc8\xf6K@' +p7884 +tp7885 +bsg238 +g176 +(g177 +(I0 +tp7886 +g179 +tp7887 +Rp7888 +(I1 +(I1 +I1 +I1 +tp7889 +g38 +I00 +S'\x0e\x1f\xf8\xbc\x08,O?' +p7890 +tp7891 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7892 +g179 +tp7893 +Rp7894 +(I1 +(I1 +I1 +I1 +tp7895 +g38 +I00 +S'wj\xc3\x94\\9\xe9?' +p7896 +tp7897 +bsg252 +g260 +sg48 +(lp7898 +g0 +(g52 +g2 +Ntp7899 +Rp7900 +(dp7901 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7902 +g179 +tp7903 +Rp7904 +(I1 +(I1 +I1 +I1 +tp7905 +g38 +I00 +S'\xdcf\x99\x18U\xbcQ@' +p7906 +tp7907 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7908 +g334 +asg113 +I10243 +sg280 +I01 +sbaatp7909 +Rp7910 +sg337 +I00 +sg338 +Nsbaa(lp7911 +g340 +ag0 +(g341 +g2 +Ntp7912 +Rp7913 +(dp7914 +g17 +g7789 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp7915 +(lp7916 +g189 +ag0 +(g190 +g2 +Ntp7917 +Rp7918 +(dp7919 +g194 +I01 +sg195 +(lp7920 +g0 +(g197 +g2 +Ntp7921 +Rp7922 +(dp7923 +g201 +g176 +(g177 +(I0 +tp7924 +g179 +tp7925 +Rp7926 +(I1 +(I1 +tp7927 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p7928 +tp7929 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7930 +Rp7931 +(dp7932 +g201 +g176 +(g177 +(I0 +tp7933 +g179 +tp7934 +Rp7935 +(I1 +(I2 +tp7936 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7937 +tp7938 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7939 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7940 +g179 +tp7941 +Rp7942 +(I1 +(I1 +I1 +I1 +tp7943 +g38 +I00 +S'=*\xd4ui\xb4H@' +p7944 +tp7945 +bsg238 +g176 +(g177 +(I0 +tp7946 +g179 +tp7947 +Rp7948 +(I1 +(I1 +I1 +I1 +tp7949 +g38 +I00 +S'nEu\xe6\x1d\xd8C?' +p7950 +tp7951 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp7952 +g179 +tp7953 +Rp7954 +(I1 +(I1 +I1 +I1 +tp7955 +g38 +I00 +S'\xcer\x18t\x9c\xb5\xe7?' +p7956 +tp7957 +bsg252 +g260 +sg48 +(lp7958 +g0 +(g52 +g2 +Ntp7959 +Rp7960 +(dp7961 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp7962 +g179 +tp7963 +Rp7964 +(I1 +(I1 +I1 +I1 +tp7965 +g38 +I00 +S'\xb90\xa1\x01\xb2\xabP@' +p7966 +tp7967 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp7968 +g279 +asg113 +I10246 +sg280 +I01 +sbaa(lp7969 +g401 +ag0 +(g190 +g2 +Ntp7970 +Rp7971 +(dp7972 +g194 +I01 +sg195 +(lp7973 +g0 +(g197 +g2 +Ntp7974 +Rp7975 +(dp7976 +g201 +g176 +(g177 +(I0 +tp7977 +g179 +tp7978 +Rp7979 +(I1 +(I1 +tp7980 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p7981 +tp7982 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp7983 +Rp7984 +(dp7985 +g201 +g176 +(g177 +(I0 +tp7986 +g179 +tp7987 +Rp7988 +(I1 +(I2 +tp7989 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p7990 +tp7991 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp7992 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp7993 +g179 +tp7994 +Rp7995 +(I1 +(I1 +I1 +I1 +tp7996 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p7997 +tp7998 +bsg238 +g176 +(g177 +(I0 +tp7999 +g179 +tp8000 +Rp8001 +(I1 +(I1 +I1 +I1 +tp8002 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8003 +tp8004 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8005 +g179 +tp8006 +Rp8007 +(I1 +(I1 +I1 +I1 +tp8008 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8009 +tp8010 +bsg252 +g260 +sg48 +(lp8011 +g0 +(g52 +g2 +Ntp8012 +Rp8013 +(dp8014 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8015 +g179 +tp8016 +Rp8017 +(I1 +(I1 +I1 +I1 +tp8018 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8019 +tp8020 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8021 +g454 +asg113 +I10247 +sg280 +I01 +sbaatp8022 +Rp8023 +sg337 +I00 +sg338 +Nsbaa(lp8024 +g458 +ag0 +(g459 +g2 +Ntp8025 +Rp8026 +(dp8027 +g17 +g7789 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8028 +(lp8029 +g189 +ag0 +(g190 +g2 +Ntp8030 +Rp8031 +(dp8032 +g194 +I01 +sg195 +(lp8033 +g0 +(g197 +g2 +Ntp8034 +Rp8035 +(dp8036 +g201 +g176 +(g177 +(I0 +tp8037 +g179 +tp8038 +Rp8039 +(I1 +(I1 +tp8040 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p8041 +tp8042 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8043 +Rp8044 +(dp8045 +g201 +g176 +(g177 +(I0 +tp8046 +g179 +tp8047 +Rp8048 +(I1 +(I2 +tp8049 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8050 +tp8051 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp8052 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8053 +g179 +tp8054 +Rp8055 +(I1 +(I1 +I1 +I1 +tp8056 +g38 +I00 +S"\xc9\xfe#m'\xcaH@" +p8057 +tp8058 +bsg238 +g176 +(g177 +(I0 +tp8059 +g179 +tp8060 +Rp8061 +(I1 +(I1 +I1 +I1 +tp8062 +g38 +I00 +S'R\xd4w4\x91eU?' +p8063 +tp8064 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8065 +g179 +tp8066 +Rp8067 +(I1 +(I1 +I1 +I1 +tp8068 +g38 +I00 +S'\xb6r\xea\xd5`\xbf\xe7?' +p8069 +tp8070 +bsg252 +g513 +sg48 +(lp8071 +g0 +(g52 +g2 +Ntp8072 +Rp8073 +(dp8074 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp8075 +g179 +tp8076 +Rp8077 +(I1 +(I1 +I1 +I1 +tp8078 +g38 +I00 +S'\xa8\xd8h\x16\x90\xb2P@' +p8079 +tp8080 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp8081 +g527 +asg113 +I10250 +sg280 +I01 +sbaa(lp8082 +g529 +ag0 +(g190 +g2 +Ntp8083 +Rp8084 +(dp8085 +g194 +I01 +sg195 +(lp8086 +g0 +(g197 +g2 +Ntp8087 +Rp8088 +(dp8089 +g201 +g176 +(g177 +(I0 +tp8090 +g179 +tp8091 +Rp8092 +(I1 +(I1 +tp8093 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p8094 +tp8095 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8096 +Rp8097 +(dp8098 +g201 +g176 +(g177 +(I0 +tp8099 +g179 +tp8100 +Rp8101 +(I1 +(I2 +tp8102 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8103 +tp8104 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8105 +Rp8106 +(dp8107 +g201 +g176 +(g177 +(I0 +tp8108 +g179 +tp8109 +Rp8110 +(I1 +(I2 +tp8111 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8112 +tp8113 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp8114 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8115 +g179 +tp8116 +Rp8117 +(I1 +(I1 +I1 +I1 +tp8118 +g38 +I00 +S'5\xe3+\x89\x05\\K@' +p8119 +tp8120 +bsg238 +g176 +(g177 +(I0 +tp8121 +g179 +tp8122 +Rp8123 +(I1 +(I1 +I1 +I1 +tp8124 +g38 +I00 +S'\xe3\x13S\x84\xc2nS?' +p8125 +tp8126 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8127 +g179 +tp8128 +Rp8129 +(I1 +(I1 +I1 +I1 +tp8130 +g38 +I00 +S'\xb0/(5\xf0\xf2\xe8?' +p8131 +tp8132 +bsg252 +g586 +sg48 +(lp8133 +g0 +(g52 +g2 +Ntp8134 +Rp8135 +(dp8136 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp8137 +g179 +tp8138 +Rp8139 +(I1 +(I1 +I1 +I1 +tp8140 +g38 +I00 +S'\x88A`\xe5\xd0\x8aQ@' +p8141 +tp8142 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp8143 +g600 +asg113 +I10251 +sg280 +I01 +sbaatp8144 +Rp8145 +sg337 +I00 +sg338 +Nsbaa(lp8146 +g604 +ag0 +(g605 +g2 +Ntp8147 +Rp8148 +(dp8149 +g17 +g7789 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8150 +(lp8151 +g611 +ag0 +(g190 +g2 +Ntp8152 +Rp8153 +(dp8154 +g194 +I01 +sg195 +(lp8155 +g0 +(g197 +g2 +Ntp8156 +Rp8157 +(dp8158 +g201 +g176 +(g177 +(I0 +tp8159 +g179 +tp8160 +Rp8161 +(I1 +(I1 +tp8162 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p8163 +tp8164 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8165 +Rp8166 +(dp8167 +g201 +g176 +(g177 +(I0 +tp8168 +g179 +tp8169 +Rp8170 +(I1 +(I2 +tp8171 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8172 +tp8173 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp8174 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8175 +g179 +tp8176 +Rp8177 +(I1 +(I1 +I1 +I1 +tp8178 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8179 +tp8180 +bsg238 +g176 +(g177 +(I0 +tp8181 +g179 +tp8182 +Rp8183 +(I1 +(I1 +I1 +I1 +tp8184 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8185 +tp8186 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8187 +g179 +tp8188 +Rp8189 +(I1 +(I1 +I1 +I1 +tp8190 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8191 +tp8192 +bsg252 +g513 +sg48 +(lp8193 +g0 +(g52 +g2 +Ntp8194 +Rp8195 +(dp8196 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp8197 +g179 +tp8198 +Rp8199 +(I1 +(I1 +I1 +I1 +tp8200 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8201 +tp8202 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp8203 +g664 +asg113 +I10254 +sg280 +I01 +sbaa(lp8204 +g666 +ag0 +(g190 +g2 +Ntp8205 +Rp8206 +(dp8207 +g194 +I01 +sg195 +(lp8208 +g0 +(g197 +g2 +Ntp8209 +Rp8210 +(dp8211 +g201 +g176 +(g177 +(I0 +tp8212 +g179 +tp8213 +Rp8214 +(I1 +(I1 +tp8215 +g208 +I00 +S" '\x00\x00\x00\x00\x00\x00" +p8216 +tp8217 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8218 +Rp8219 +(dp8220 +g201 +g176 +(g177 +(I0 +tp8221 +g179 +tp8222 +Rp8223 +(I1 +(I2 +tp8224 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8225 +tp8226 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp8227 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8228 +g179 +tp8229 +Rp8230 +(I1 +(I1 +I1 +I1 +tp8231 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8232 +tp8233 +bsg238 +g176 +(g177 +(I0 +tp8234 +g179 +tp8235 +Rp8236 +(I1 +(I1 +I1 +I1 +tp8237 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8238 +tp8239 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8240 +g179 +tp8241 +Rp8242 +(I1 +(I1 +I1 +I1 +tp8243 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8244 +tp8245 +bsg252 +g713 +sg48 +(lp8246 +g0 +(g52 +g2 +Ntp8247 +Rp8248 +(dp8249 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp8250 +g179 +tp8251 +Rp8252 +(I1 +(I1 +I1 +I1 +tp8253 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8254 +tp8255 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp8256 +g727 +asg113 +I10255 +sg280 +I01 +sbaatp8257 +Rp8258 +sg337 +I00 +sg338 +Nsbaatp8259 +Rp8260 +aa(lp8261 +I10017 +ag7 +((lp8262 +(lp8263 +g12 +ag0 +(g13 +g2 +Ntp8264 +Rp8265 +(dp8266 +g17 +g0 +(g18 +g2 +Ntp8267 +Rp8268 +(dp8269 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p8270 +sg116 +g0 +(g117 +g2 +Ntp8271 +Rp8272 +(dp8273 +g121 +(lp8274 +g0 +(g123 +g2 +Ntp8275 +Rp8276 +(dp8277 +g127 +g0 +(g128 +g2 +Ntp8278 +Rp8279 +(dp8280 +g23 +g132 +sg133 +(dp8281 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xf6?' +p8282 +tp8283 +Rp8284 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p8285 +sg113 +I37 +sg146 +(lp8286 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp8287 +Rp8288 +(dp8289 +g127 +g0 +(g128 +g2 +Ntp8290 +Rp8291 +(dp8292 +g23 +g132 +sg133 +(dp8293 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xf5?' +p8294 +tp8295 +Rp8296 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p8297 +sg113 +I38 +sg146 +(lp8298 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10017 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8299 +(lp8300 +g189 +ag0 +(g190 +g2 +Ntp8301 +Rp8302 +(dp8303 +g194 +I01 +sg195 +(lp8304 +g0 +(g197 +g2 +Ntp8305 +Rp8306 +(dp8307 +g201 +g176 +(g177 +(I0 +tp8308 +g179 +tp8309 +Rp8310 +(I1 +(I1 +tp8311 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8312 +tp8313 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8314 +Rp8315 +(dp8316 +g201 +g176 +(g177 +(I0 +tp8317 +g179 +tp8318 +Rp8319 +(I1 +(I2 +tp8320 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8321 +tp8322 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8323 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8324 +g179 +tp8325 +Rp8326 +(I1 +(I1 +I1 +I1 +tp8327 +g38 +I00 +S'w\x0b\xd5d\xb8\x838@' +p8328 +tp8329 +bsg238 +g176 +(g177 +(I0 +tp8330 +g179 +tp8331 +Rp8332 +(I1 +(I1 +I1 +I1 +tp8333 +g38 +I00 +S'\x9d\x9d\x93\xbbOIA?' +p8334 +tp8335 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8336 +g179 +tp8337 +Rp8338 +(I1 +(I1 +I1 +I1 +tp8339 +g38 +I00 +S'\xba\xf8m\x11>\xb3\xe0?' +p8340 +tp8341 +bsg252 +g260 +sg48 +(lp8342 +g0 +(g52 +g2 +Ntp8343 +Rp8344 +(dp8345 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8346 +g179 +tp8347 +Rp8348 +(I1 +(I1 +I1 +I1 +tp8349 +g38 +I00 +S'\xc5\xa5\x82H\x0f|G@' +p8350 +tp8351 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8352 +g279 +asg113 +I10258 +sg280 +I01 +sbaa(lp8353 +g12 +ag0 +(g190 +g2 +Ntp8354 +Rp8355 +(dp8356 +g194 +I01 +sg195 +(lp8357 +g0 +(g197 +g2 +Ntp8358 +Rp8359 +(dp8360 +g201 +g176 +(g177 +(I0 +tp8361 +g179 +tp8362 +Rp8363 +(I1 +(I1 +tp8364 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8365 +tp8366 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8367 +Rp8368 +(dp8369 +g201 +g176 +(g177 +(I0 +tp8370 +g179 +tp8371 +Rp8372 +(I1 +(I2 +tp8373 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8374 +tp8375 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8376 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8377 +g179 +tp8378 +Rp8379 +(I1 +(I1 +I1 +I1 +tp8380 +g38 +I00 +S'\xdf\xf8Z\x1a\x9fx\x10@' +p8381 +tp8382 +bsg238 +g176 +(g177 +(I0 +tp8383 +g179 +tp8384 +Rp8385 +(I1 +(I1 +I1 +I1 +tp8386 +g38 +I00 +S'N\xca\xfcY\xb8\x9a.?' +p8387 +tp8388 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8389 +g179 +tp8390 +Rp8391 +(I1 +(I1 +I1 +I1 +tp8392 +g38 +I00 +S'h\xc1\xf4N\xb5`\xcb?' +p8393 +tp8394 +bsg252 +g260 +sg48 +(lp8395 +g0 +(g52 +g2 +Ntp8396 +Rp8397 +(dp8398 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8399 +g179 +tp8400 +Rp8401 +(I1 +(I1 +I1 +I1 +tp8402 +g38 +I00 +S'\xfd\x17\x84{\xff?3@' +p8403 +tp8404 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8405 +g334 +asg113 +I10259 +sg280 +I01 +sbaatp8406 +Rp8407 +sg337 +I00 +sg338 +Nsbaa(lp8408 +g340 +ag0 +(g341 +g2 +Ntp8409 +Rp8410 +(dp8411 +g17 +g8268 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8412 +(lp8413 +g189 +ag0 +(g190 +g2 +Ntp8414 +Rp8415 +(dp8416 +g194 +I01 +sg195 +(lp8417 +g0 +(g197 +g2 +Ntp8418 +Rp8419 +(dp8420 +g201 +g176 +(g177 +(I0 +tp8421 +g179 +tp8422 +Rp8423 +(I1 +(I1 +tp8424 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8425 +tp8426 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8427 +Rp8428 +(dp8429 +g201 +g176 +(g177 +(I0 +tp8430 +g179 +tp8431 +Rp8432 +(I1 +(I2 +tp8433 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8434 +tp8435 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8436 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8437 +g179 +tp8438 +Rp8439 +(I1 +(I1 +I1 +I1 +tp8440 +g38 +I00 +S'w\x0b\xd5d\xb8\x838@' +p8441 +tp8442 +bsg238 +g176 +(g177 +(I0 +tp8443 +g179 +tp8444 +Rp8445 +(I1 +(I1 +I1 +I1 +tp8446 +g38 +I00 +S'\x9d\x9d\x93\xbbOIA?' +p8447 +tp8448 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8449 +g179 +tp8450 +Rp8451 +(I1 +(I1 +I1 +I1 +tp8452 +g38 +I00 +S'\xba\xf8m\x11>\xb3\xe0?' +p8453 +tp8454 +bsg252 +g260 +sg48 +(lp8455 +g0 +(g52 +g2 +Ntp8456 +Rp8457 +(dp8458 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8459 +g179 +tp8460 +Rp8461 +(I1 +(I1 +I1 +I1 +tp8462 +g38 +I00 +S'\xc5\xa5\x82H\x0f|G@' +p8463 +tp8464 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8465 +g279 +asg113 +I10262 +sg280 +I01 +sbaa(lp8466 +g401 +ag0 +(g190 +g2 +Ntp8467 +Rp8468 +(dp8469 +g194 +I01 +sg195 +(lp8470 +g0 +(g197 +g2 +Ntp8471 +Rp8472 +(dp8473 +g201 +g176 +(g177 +(I0 +tp8474 +g179 +tp8475 +Rp8476 +(I1 +(I1 +tp8477 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8478 +tp8479 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8480 +Rp8481 +(dp8482 +g201 +g176 +(g177 +(I0 +tp8483 +g179 +tp8484 +Rp8485 +(I1 +(I2 +tp8486 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8487 +tp8488 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8489 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8490 +g179 +tp8491 +Rp8492 +(I1 +(I1 +I1 +I1 +tp8493 +g38 +I00 +S'U\x1c#\xdc\xdb\xcc\xae?' +p8494 +tp8495 +bsg238 +g176 +(g177 +(I0 +tp8496 +g179 +tp8497 +Rp8498 +(I1 +(I1 +I1 +I1 +tp8499 +g38 +I00 +S'\xd9ef\xbd\xf8#\r?' +p8500 +tp8501 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8502 +g179 +tp8503 +Rp8504 +(I1 +(I1 +I1 +I1 +tp8505 +g38 +I00 +S'\x95\x85\xf6\xb8\xf7w\x9a?' +p8506 +tp8507 +bsg252 +g260 +sg48 +(lp8508 +g0 +(g52 +g2 +Ntp8509 +Rp8510 +(dp8511 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8512 +g179 +tp8513 +Rp8514 +(I1 +(I1 +I1 +I1 +tp8515 +g38 +I00 +S'\xedU\r.Z\x9c\x02@' +p8516 +tp8517 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8518 +g454 +asg113 +I10263 +sg280 +I01 +sbaatp8519 +Rp8520 +sg337 +I00 +sg338 +Nsbaa(lp8521 +g458 +ag0 +(g459 +g2 +Ntp8522 +Rp8523 +(dp8524 +g17 +g8268 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8525 +(lp8526 +g189 +ag0 +(g190 +g2 +Ntp8527 +Rp8528 +(dp8529 +g194 +I01 +sg195 +(lp8530 +g0 +(g197 +g2 +Ntp8531 +Rp8532 +(dp8533 +g201 +g176 +(g177 +(I0 +tp8534 +g179 +tp8535 +Rp8536 +(I1 +(I1 +tp8537 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8538 +tp8539 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8540 +Rp8541 +(dp8542 +g201 +g176 +(g177 +(I0 +tp8543 +g179 +tp8544 +Rp8545 +(I1 +(I2 +tp8546 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8547 +tp8548 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp8549 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8550 +g179 +tp8551 +Rp8552 +(I1 +(I1 +I1 +I1 +tp8553 +g38 +I00 +S'\xe0\xfc=\x9fU\x8a8@' +p8554 +tp8555 +bsg238 +g176 +(g177 +(I0 +tp8556 +g179 +tp8557 +Rp8558 +(I1 +(I1 +I1 +I1 +tp8559 +g38 +I00 +S'/\xcc\xb0O$\xfdS?' +p8560 +tp8561 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8562 +g179 +tp8563 +Rp8564 +(I1 +(I1 +I1 +I1 +tp8565 +g38 +I00 +S'y9*g\xa6\xb4\xe0?' +p8566 +tp8567 +bsg252 +g513 +sg48 +(lp8568 +g0 +(g52 +g2 +Ntp8569 +Rp8570 +(dp8571 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp8572 +g179 +tp8573 +Rp8574 +(I1 +(I1 +I1 +I1 +tp8575 +g38 +I00 +S'\xd2`\x13\x01\n~G@' +p8576 +tp8577 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp8578 +g527 +asg113 +I10266 +sg280 +I01 +sbaa(lp8579 +g529 +ag0 +(g190 +g2 +Ntp8580 +Rp8581 +(dp8582 +g194 +I01 +sg195 +(lp8583 +g0 +(g197 +g2 +Ntp8584 +Rp8585 +(dp8586 +g201 +g176 +(g177 +(I0 +tp8587 +g179 +tp8588 +Rp8589 +(I1 +(I1 +tp8590 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8591 +tp8592 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8593 +Rp8594 +(dp8595 +g201 +g176 +(g177 +(I0 +tp8596 +g179 +tp8597 +Rp8598 +(I1 +(I2 +tp8599 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8600 +tp8601 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8602 +Rp8603 +(dp8604 +g201 +g176 +(g177 +(I0 +tp8605 +g179 +tp8606 +Rp8607 +(I1 +(I2 +tp8608 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8609 +tp8610 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp8611 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8612 +g179 +tp8613 +Rp8614 +(I1 +(I1 +I1 +I1 +tp8615 +g38 +I00 +S'\x83\xbb.\xf4o\xc4\x0b@' +p8616 +tp8617 +bsg238 +g176 +(g177 +(I0 +tp8618 +g179 +tp8619 +Rp8620 +(I1 +(I1 +I1 +I1 +tp8621 +g38 +I00 +S'\x0c\xa2\x88q\xb8\x9c??' +p8622 +tp8623 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8624 +g179 +tp8625 +Rp8626 +(I1 +(I1 +I1 +I1 +tp8627 +g38 +I00 +S'y\xd6\x84\x16N!\xc9?' +p8628 +tp8629 +bsg252 +g586 +sg48 +(lp8630 +g0 +(g52 +g2 +Ntp8631 +Rp8632 +(dp8633 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp8634 +g179 +tp8635 +Rp8636 +(I1 +(I1 +I1 +I1 +tp8637 +g38 +I00 +S'\xcdf\xd5\xe7j\xab1@' +p8638 +tp8639 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp8640 +g600 +asg113 +I10267 +sg280 +I01 +sbaatp8641 +Rp8642 +sg337 +I00 +sg338 +Nsbaa(lp8643 +g604 +ag0 +(g605 +g2 +Ntp8644 +Rp8645 +(dp8646 +g17 +g8268 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8647 +(lp8648 +g611 +ag0 +(g190 +g2 +Ntp8649 +Rp8650 +(dp8651 +g194 +I01 +sg195 +(lp8652 +g0 +(g197 +g2 +Ntp8653 +Rp8654 +(dp8655 +g201 +g176 +(g177 +(I0 +tp8656 +g179 +tp8657 +Rp8658 +(I1 +(I1 +tp8659 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8660 +tp8661 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8662 +Rp8663 +(dp8664 +g201 +g176 +(g177 +(I0 +tp8665 +g179 +tp8666 +Rp8667 +(I1 +(I2 +tp8668 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8669 +tp8670 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp8671 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8672 +g179 +tp8673 +Rp8674 +(I1 +(I1 +I1 +I1 +tp8675 +g38 +I00 +S'\xc6c\xc4\x8c\xcd\xaa\xae?' +p8676 +tp8677 +bsg238 +g176 +(g177 +(I0 +tp8678 +g179 +tp8679 +Rp8680 +(I1 +(I1 +I1 +I1 +tp8681 +g38 +I00 +S'4yq\x1b\xae\xf1-?' +p8682 +tp8683 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8684 +g179 +tp8685 +Rp8686 +(I1 +(I1 +I1 +I1 +tp8687 +g38 +I00 +S'\x18f\xea^\x11S\x9a?' +p8688 +tp8689 +bsg252 +g513 +sg48 +(lp8690 +g0 +(g52 +g2 +Ntp8691 +Rp8692 +(dp8693 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp8694 +g179 +tp8695 +Rp8696 +(I1 +(I1 +I1 +I1 +tp8697 +g38 +I00 +S'\xc9\xcf\xbc6h\x82\x02@' +p8698 +tp8699 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp8700 +g664 +asg113 +I10270 +sg280 +I01 +sbaa(lp8701 +g666 +ag0 +(g190 +g2 +Ntp8702 +Rp8703 +(dp8704 +g194 +I01 +sg195 +(lp8705 +g0 +(g197 +g2 +Ntp8706 +Rp8707 +(dp8708 +g201 +g176 +(g177 +(I0 +tp8709 +g179 +tp8710 +Rp8711 +(I1 +(I1 +tp8712 +g208 +I00 +S"!'\x00\x00\x00\x00\x00\x00" +p8713 +tp8714 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8715 +Rp8716 +(dp8717 +g201 +g176 +(g177 +(I0 +tp8718 +g179 +tp8719 +Rp8720 +(I1 +(I2 +tp8721 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8722 +tp8723 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp8724 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8725 +g179 +tp8726 +Rp8727 +(I1 +(I1 +I1 +I1 +tp8728 +g38 +I00 +S'\xc4c\xc4\x8c\xcd\xaa\xae?' +p8729 +tp8730 +bsg238 +g176 +(g177 +(I0 +tp8731 +g179 +tp8732 +Rp8733 +(I1 +(I1 +I1 +I1 +tp8734 +g38 +I00 +S'\xe6vq\x1b\xae\xf1-?' +p8735 +tp8736 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8737 +g179 +tp8738 +Rp8739 +(I1 +(I1 +I1 +I1 +tp8740 +g38 +I00 +S'\x1bf\xea^\x11S\x9a?' +p8741 +tp8742 +bsg252 +g713 +sg48 +(lp8743 +g0 +(g52 +g2 +Ntp8744 +Rp8745 +(dp8746 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp8747 +g179 +tp8748 +Rp8749 +(I1 +(I1 +I1 +I1 +tp8750 +g38 +I00 +S'\xcb\xcf\xbc6h\x82\x02@' +p8751 +tp8752 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp8753 +g727 +asg113 +I10271 +sg280 +I01 +sbaatp8754 +Rp8755 +sg337 +I00 +sg338 +Nsbaatp8756 +Rp8757 +aa(lp8758 +I10018 +ag7 +((lp8759 +(lp8760 +g12 +ag0 +(g13 +g2 +Ntp8761 +Rp8762 +(dp8763 +g17 +g0 +(g18 +g2 +Ntp8764 +Rp8765 +(dp8766 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p8767 +sg116 +g0 +(g117 +g2 +Ntp8768 +Rp8769 +(dp8770 +g121 +(lp8771 +g0 +(g123 +g2 +Ntp8772 +Rp8773 +(dp8774 +g127 +g0 +(g128 +g2 +Ntp8775 +Rp8776 +(dp8777 +g23 +g132 +sg133 +(dp8778 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'{\x14\xaeG\xe1z\x13@' +p8779 +tp8780 +Rp8781 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p8782 +sg113 +I40 +sg146 +(lp8783 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp8784 +Rp8785 +(dp8786 +g127 +g0 +(g128 +g2 +Ntp8787 +Rp8788 +(dp8789 +g23 +g132 +sg133 +(dp8790 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xb8\x1e\x85\xebQ8\x13@' +p8791 +tp8792 +Rp8793 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p8794 +sg113 +I39 +sg146 +(lp8795 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10018 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8796 +(lp8797 +g189 +ag0 +(g190 +g2 +Ntp8798 +Rp8799 +(dp8800 +g194 +I01 +sg195 +(lp8801 +g0 +(g197 +g2 +Ntp8802 +Rp8803 +(dp8804 +g201 +g176 +(g177 +(I0 +tp8805 +g179 +tp8806 +Rp8807 +(I1 +(I1 +tp8808 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p8809 +tp8810 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8811 +Rp8812 +(dp8813 +g201 +g176 +(g177 +(I0 +tp8814 +g179 +tp8815 +Rp8816 +(I1 +(I2 +tp8817 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8818 +tp8819 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8820 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8821 +g179 +tp8822 +Rp8823 +(I1 +(I1 +I1 +I1 +tp8824 +g38 +I00 +S'MT\x18\xe7wjI@' +p8825 +tp8826 +bsg238 +g176 +(g177 +(I0 +tp8827 +g179 +tp8828 +Rp8829 +(I1 +(I1 +I1 +I1 +tp8830 +g38 +I00 +S'\xdd\x85?\x11\x86\xbbK?' +p8831 +tp8832 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8833 +g179 +tp8834 +Rp8835 +(I1 +(I1 +I1 +I1 +tp8836 +g38 +I00 +S'(\xa0\x01\x0f0\x0c\xe8?' +p8837 +tp8838 +bsg252 +g260 +sg48 +(lp8839 +g0 +(g52 +g2 +Ntp8840 +Rp8841 +(dp8842 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8843 +g179 +tp8844 +Rp8845 +(I1 +(I1 +I1 +I1 +tp8846 +g38 +I00 +S'\x9c$\x8d\xca\x91\xe8P@' +p8847 +tp8848 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8849 +g279 +asg113 +I10274 +sg280 +I01 +sbaa(lp8850 +g12 +ag0 +(g190 +g2 +Ntp8851 +Rp8852 +(dp8853 +g194 +I01 +sg195 +(lp8854 +g0 +(g197 +g2 +Ntp8855 +Rp8856 +(dp8857 +g201 +g176 +(g177 +(I0 +tp8858 +g179 +tp8859 +Rp8860 +(I1 +(I1 +tp8861 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p8862 +tp8863 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8864 +Rp8865 +(dp8866 +g201 +g176 +(g177 +(I0 +tp8867 +g179 +tp8868 +Rp8869 +(I1 +(I2 +tp8870 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8871 +tp8872 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8873 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8874 +g179 +tp8875 +Rp8876 +(I1 +(I1 +I1 +I1 +tp8877 +g38 +I00 +S'H\xd6\xa1\x80\x90\xbdN@' +p8878 +tp8879 +bsg238 +g176 +(g177 +(I0 +tp8880 +g179 +tp8881 +Rp8882 +(I1 +(I1 +I1 +I1 +tp8883 +g38 +I00 +S'zi\xccvs\xc1V?' +p8884 +tp8885 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8886 +g179 +tp8887 +Rp8888 +(I1 +(I1 +I1 +I1 +tp8889 +g38 +I00 +S'!\xfe\x87@\xefq\xea?' +p8890 +tp8891 +bsg252 +g260 +sg48 +(lp8892 +g0 +(g52 +g2 +Ntp8893 +Rp8894 +(dp8895 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8896 +g179 +tp8897 +Rp8898 +(I1 +(I1 +I1 +I1 +tp8899 +g38 +I00 +S'\xaf\x9e_9\x1c\x98R@' +p8900 +tp8901 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8902 +g334 +asg113 +I10275 +sg280 +I01 +sbaatp8903 +Rp8904 +sg337 +I00 +sg338 +Nsbaa(lp8905 +g340 +ag0 +(g341 +g2 +Ntp8906 +Rp8907 +(dp8908 +g17 +g8765 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp8909 +(lp8910 +g189 +ag0 +(g190 +g2 +Ntp8911 +Rp8912 +(dp8913 +g194 +I01 +sg195 +(lp8914 +g0 +(g197 +g2 +Ntp8915 +Rp8916 +(dp8917 +g201 +g176 +(g177 +(I0 +tp8918 +g179 +tp8919 +Rp8920 +(I1 +(I1 +tp8921 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p8922 +tp8923 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8924 +Rp8925 +(dp8926 +g201 +g176 +(g177 +(I0 +tp8927 +g179 +tp8928 +Rp8929 +(I1 +(I2 +tp8930 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8931 +tp8932 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8933 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8934 +g179 +tp8935 +Rp8936 +(I1 +(I1 +I1 +I1 +tp8937 +g38 +I00 +S'MT\x18\xe7wjI@' +p8938 +tp8939 +bsg238 +g176 +(g177 +(I0 +tp8940 +g179 +tp8941 +Rp8942 +(I1 +(I1 +I1 +I1 +tp8943 +g38 +I00 +S'\xdd\x85?\x11\x86\xbbK?' +p8944 +tp8945 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8946 +g179 +tp8947 +Rp8948 +(I1 +(I1 +I1 +I1 +tp8949 +g38 +I00 +S'(\xa0\x01\x0f0\x0c\xe8?' +p8950 +tp8951 +bsg252 +g260 +sg48 +(lp8952 +g0 +(g52 +g2 +Ntp8953 +Rp8954 +(dp8955 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp8956 +g179 +tp8957 +Rp8958 +(I1 +(I1 +I1 +I1 +tp8959 +g38 +I00 +S'\x9c$\x8d\xca\x91\xe8P@' +p8960 +tp8961 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp8962 +g279 +asg113 +I10278 +sg280 +I01 +sbaa(lp8963 +g401 +ag0 +(g190 +g2 +Ntp8964 +Rp8965 +(dp8966 +g194 +I01 +sg195 +(lp8967 +g0 +(g197 +g2 +Ntp8968 +Rp8969 +(dp8970 +g201 +g176 +(g177 +(I0 +tp8971 +g179 +tp8972 +Rp8973 +(I1 +(I1 +tp8974 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p8975 +tp8976 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp8977 +Rp8978 +(dp8979 +g201 +g176 +(g177 +(I0 +tp8980 +g179 +tp8981 +Rp8982 +(I1 +(I2 +tp8983 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p8984 +tp8985 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp8986 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp8987 +g179 +tp8988 +Rp8989 +(I1 +(I1 +I1 +I1 +tp8990 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8991 +tp8992 +bsg238 +g176 +(g177 +(I0 +tp8993 +g179 +tp8994 +Rp8995 +(I1 +(I1 +I1 +I1 +tp8996 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p8997 +tp8998 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp8999 +g179 +tp9000 +Rp9001 +(I1 +(I1 +I1 +I1 +tp9002 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9003 +tp9004 +bsg252 +g260 +sg48 +(lp9005 +g0 +(g52 +g2 +Ntp9006 +Rp9007 +(dp9008 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9009 +g179 +tp9010 +Rp9011 +(I1 +(I1 +I1 +I1 +tp9012 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9013 +tp9014 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9015 +g454 +asg113 +I10279 +sg280 +I01 +sbaatp9016 +Rp9017 +sg337 +I00 +sg338 +Nsbaa(lp9018 +g458 +ag0 +(g459 +g2 +Ntp9019 +Rp9020 +(dp9021 +g17 +g8765 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9022 +(lp9023 +g189 +ag0 +(g190 +g2 +Ntp9024 +Rp9025 +(dp9026 +g194 +I01 +sg195 +(lp9027 +g0 +(g197 +g2 +Ntp9028 +Rp9029 +(dp9030 +g201 +g176 +(g177 +(I0 +tp9031 +g179 +tp9032 +Rp9033 +(I1 +(I1 +tp9034 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p9035 +tp9036 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9037 +Rp9038 +(dp9039 +g201 +g176 +(g177 +(I0 +tp9040 +g179 +tp9041 +Rp9042 +(I1 +(I2 +tp9043 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9044 +tp9045 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp9046 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9047 +g179 +tp9048 +Rp9049 +(I1 +(I1 +I1 +I1 +tp9050 +g38 +I00 +S'\x84\x9fN4CkI@' +p9051 +tp9052 +bsg238 +g176 +(g177 +(I0 +tp9053 +g179 +tp9054 +Rp9055 +(I1 +(I1 +I1 +I1 +tp9056 +g38 +I00 +S'\xc8M7j\xb4\xc9W?' +p9057 +tp9058 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9059 +g179 +tp9060 +Rp9061 +(I1 +(I1 +I1 +I1 +tp9062 +g38 +I00 +S'\x17\xc9\xdfi\xe3\x0b\xe8?' +p9063 +tp9064 +bsg252 +g513 +sg48 +(lp9065 +g0 +(g52 +g2 +Ntp9066 +Rp9067 +(dp9068 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp9069 +g179 +tp9070 +Rp9071 +(I1 +(I1 +I1 +I1 +tp9072 +g38 +I00 +S'dYq\xe6[\xe8P@' +p9073 +tp9074 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp9075 +g527 +asg113 +I10282 +sg280 +I01 +sbaa(lp9076 +g529 +ag0 +(g190 +g2 +Ntp9077 +Rp9078 +(dp9079 +g194 +I01 +sg195 +(lp9080 +g0 +(g197 +g2 +Ntp9081 +Rp9082 +(dp9083 +g201 +g176 +(g177 +(I0 +tp9084 +g179 +tp9085 +Rp9086 +(I1 +(I1 +tp9087 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p9088 +tp9089 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9090 +Rp9091 +(dp9092 +g201 +g176 +(g177 +(I0 +tp9093 +g179 +tp9094 +Rp9095 +(I1 +(I2 +tp9096 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9097 +tp9098 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9099 +Rp9100 +(dp9101 +g201 +g176 +(g177 +(I0 +tp9102 +g179 +tp9103 +Rp9104 +(I1 +(I2 +tp9105 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9106 +tp9107 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp9108 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9109 +g179 +tp9110 +Rp9111 +(I1 +(I1 +I1 +I1 +tp9112 +g38 +I00 +S'\x92M$^?\xdfM@' +p9113 +tp9114 +bsg238 +g176 +(g177 +(I0 +tp9115 +g179 +tp9116 +Rp9117 +(I1 +(I1 +I1 +I1 +tp9118 +g38 +I00 +S'\xad\x10\xb8\xd6P\xc7[?' +p9119 +tp9120 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9121 +g179 +tp9122 +Rp9123 +(I1 +(I1 +I1 +I1 +tp9124 +g38 +I00 +S'ArX\x07-\x11\xea?' +p9125 +tp9126 +bsg252 +g586 +sg48 +(lp9127 +g0 +(g52 +g2 +Ntp9128 +Rp9129 +(dp9130 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp9131 +g179 +tp9132 +Rp9133 +(I1 +(I1 +I1 +I1 +tp9134 +g38 +I00 +S'V0*\xa9\x13TR@' +p9135 +tp9136 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp9137 +g600 +asg113 +I10283 +sg280 +I01 +sbaatp9138 +Rp9139 +sg337 +I00 +sg338 +Nsbaa(lp9140 +g604 +ag0 +(g605 +g2 +Ntp9141 +Rp9142 +(dp9143 +g17 +g8765 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9144 +(lp9145 +g611 +ag0 +(g190 +g2 +Ntp9146 +Rp9147 +(dp9148 +g194 +I01 +sg195 +(lp9149 +g0 +(g197 +g2 +Ntp9150 +Rp9151 +(dp9152 +g201 +g176 +(g177 +(I0 +tp9153 +g179 +tp9154 +Rp9155 +(I1 +(I1 +tp9156 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p9157 +tp9158 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9159 +Rp9160 +(dp9161 +g201 +g176 +(g177 +(I0 +tp9162 +g179 +tp9163 +Rp9164 +(I1 +(I2 +tp9165 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9166 +tp9167 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp9168 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9169 +g179 +tp9170 +Rp9171 +(I1 +(I1 +I1 +I1 +tp9172 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9173 +tp9174 +bsg238 +g176 +(g177 +(I0 +tp9175 +g179 +tp9176 +Rp9177 +(I1 +(I1 +I1 +I1 +tp9178 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9179 +tp9180 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9181 +g179 +tp9182 +Rp9183 +(I1 +(I1 +I1 +I1 +tp9184 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9185 +tp9186 +bsg252 +g513 +sg48 +(lp9187 +g0 +(g52 +g2 +Ntp9188 +Rp9189 +(dp9190 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp9191 +g179 +tp9192 +Rp9193 +(I1 +(I1 +I1 +I1 +tp9194 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9195 +tp9196 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp9197 +g664 +asg113 +I10286 +sg280 +I01 +sbaa(lp9198 +g666 +ag0 +(g190 +g2 +Ntp9199 +Rp9200 +(dp9201 +g194 +I01 +sg195 +(lp9202 +g0 +(g197 +g2 +Ntp9203 +Rp9204 +(dp9205 +g201 +g176 +(g177 +(I0 +tp9206 +g179 +tp9207 +Rp9208 +(I1 +(I1 +tp9209 +g208 +I00 +S'"\'\x00\x00\x00\x00\x00\x00' +p9210 +tp9211 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9212 +Rp9213 +(dp9214 +g201 +g176 +(g177 +(I0 +tp9215 +g179 +tp9216 +Rp9217 +(I1 +(I2 +tp9218 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9219 +tp9220 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp9221 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9222 +g179 +tp9223 +Rp9224 +(I1 +(I1 +I1 +I1 +tp9225 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9226 +tp9227 +bsg238 +g176 +(g177 +(I0 +tp9228 +g179 +tp9229 +Rp9230 +(I1 +(I1 +I1 +I1 +tp9231 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9232 +tp9233 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9234 +g179 +tp9235 +Rp9236 +(I1 +(I1 +I1 +I1 +tp9237 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9238 +tp9239 +bsg252 +g713 +sg48 +(lp9240 +g0 +(g52 +g2 +Ntp9241 +Rp9242 +(dp9243 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp9244 +g179 +tp9245 +Rp9246 +(I1 +(I1 +I1 +I1 +tp9247 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9248 +tp9249 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp9250 +g727 +asg113 +I10287 +sg280 +I01 +sbaatp9251 +Rp9252 +sg337 +I00 +sg338 +Nsbaatp9253 +Rp9254 +aa(lp9255 +I10019 +ag7 +((lp9256 +(lp9257 +g12 +ag0 +(g13 +g2 +Ntp9258 +Rp9259 +(dp9260 +g17 +g0 +(g18 +g2 +Ntp9261 +Rp9262 +(dp9263 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p9264 +sg116 +g0 +(g117 +g2 +Ntp9265 +Rp9266 +(dp9267 +g121 +(lp9268 +g0 +(g123 +g2 +Ntp9269 +Rp9270 +(dp9271 +g127 +g6806 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp9272 +Rp9273 +(dp9274 +g127 +g3348 +sg148 +g149 +sbasbsg163 +Nsg113 +I10019 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9275 +(lp9276 +g189 +ag0 +(g190 +g2 +Ntp9277 +Rp9278 +(dp9279 +g194 +I01 +sg195 +(lp9280 +g0 +(g197 +g2 +Ntp9281 +Rp9282 +(dp9283 +g201 +g176 +(g177 +(I0 +tp9284 +g179 +tp9285 +Rp9286 +(I1 +(I1 +tp9287 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9288 +tp9289 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9290 +Rp9291 +(dp9292 +g201 +g176 +(g177 +(I0 +tp9293 +g179 +tp9294 +Rp9295 +(I1 +(I2 +tp9296 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9297 +tp9298 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9299 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9300 +g179 +tp9301 +Rp9302 +(I1 +(I1 +I1 +I1 +tp9303 +g38 +I00 +S'Z|\xd2-\x89\x848@' +p9304 +tp9305 +bsg238 +g176 +(g177 +(I0 +tp9306 +g179 +tp9307 +Rp9308 +(I1 +(I1 +I1 +I1 +tp9309 +g38 +I00 +S'\x88\xbe\xb9\xf8^\x16A?' +p9310 +tp9311 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9312 +g179 +tp9313 +Rp9314 +(I1 +(I1 +I1 +I1 +tp9315 +g38 +I00 +S'\xa4v\xc2S\x86\xb3\xe0?' +p9316 +tp9317 +bsg252 +g260 +sg48 +(lp9318 +g0 +(g52 +g2 +Ntp9319 +Rp9320 +(dp9321 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9322 +g179 +tp9323 +Rp9324 +(I1 +(I1 +I1 +I1 +tp9325 +g38 +I00 +S'\xd7v\xc9\xe5t|G@' +p9326 +tp9327 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9328 +g279 +asg113 +I10290 +sg280 +I01 +sbaa(lp9329 +g12 +ag0 +(g190 +g2 +Ntp9330 +Rp9331 +(dp9332 +g194 +I01 +sg195 +(lp9333 +g0 +(g197 +g2 +Ntp9334 +Rp9335 +(dp9336 +g201 +g176 +(g177 +(I0 +tp9337 +g179 +tp9338 +Rp9339 +(I1 +(I1 +tp9340 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9341 +tp9342 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9343 +Rp9344 +(dp9345 +g201 +g176 +(g177 +(I0 +tp9346 +g179 +tp9347 +Rp9348 +(I1 +(I2 +tp9349 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9350 +tp9351 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9352 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9353 +g179 +tp9354 +Rp9355 +(I1 +(I1 +I1 +I1 +tp9356 +g38 +I00 +S'9\xaalG\xd2\xb8\x12@' +p9357 +tp9358 +bsg238 +g176 +(g177 +(I0 +tp9359 +g179 +tp9360 +Rp9361 +(I1 +(I1 +I1 +I1 +tp9362 +g38 +I00 +S'\xf9CYzb\xe8/?' +p9363 +tp9364 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9365 +g179 +tp9366 +Rp9367 +(I1 +(I1 +I1 +I1 +tp9368 +g38 +I00 +S'\xb2:B\xffC0\xcd?' +p9369 +tp9370 +bsg252 +g260 +sg48 +(lp9371 +g0 +(g52 +g2 +Ntp9372 +Rp9373 +(dp9374 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9375 +g179 +tp9376 +Rp9377 +(I1 +(I1 +I1 +I1 +tp9378 +g38 +I00 +S'E\x91z\xcf\xef\x854@' +p9379 +tp9380 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9381 +g334 +asg113 +I10291 +sg280 +I01 +sbaatp9382 +Rp9383 +sg337 +I00 +sg338 +Nsbaa(lp9384 +g340 +ag0 +(g341 +g2 +Ntp9385 +Rp9386 +(dp9387 +g17 +g9262 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9388 +(lp9389 +g189 +ag0 +(g190 +g2 +Ntp9390 +Rp9391 +(dp9392 +g194 +I01 +sg195 +(lp9393 +g0 +(g197 +g2 +Ntp9394 +Rp9395 +(dp9396 +g201 +g176 +(g177 +(I0 +tp9397 +g179 +tp9398 +Rp9399 +(I1 +(I1 +tp9400 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9401 +tp9402 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9403 +Rp9404 +(dp9405 +g201 +g176 +(g177 +(I0 +tp9406 +g179 +tp9407 +Rp9408 +(I1 +(I2 +tp9409 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9410 +tp9411 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9412 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9413 +g179 +tp9414 +Rp9415 +(I1 +(I1 +I1 +I1 +tp9416 +g38 +I00 +S'Z|\xd2-\x89\x848@' +p9417 +tp9418 +bsg238 +g176 +(g177 +(I0 +tp9419 +g179 +tp9420 +Rp9421 +(I1 +(I1 +I1 +I1 +tp9422 +g38 +I00 +S'\x88\xbe\xb9\xf8^\x16A?' +p9423 +tp9424 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9425 +g179 +tp9426 +Rp9427 +(I1 +(I1 +I1 +I1 +tp9428 +g38 +I00 +S'\xa4v\xc2S\x86\xb3\xe0?' +p9429 +tp9430 +bsg252 +g260 +sg48 +(lp9431 +g0 +(g52 +g2 +Ntp9432 +Rp9433 +(dp9434 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9435 +g179 +tp9436 +Rp9437 +(I1 +(I1 +I1 +I1 +tp9438 +g38 +I00 +S'\xd7v\xc9\xe5t|G@' +p9439 +tp9440 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9441 +g279 +asg113 +I10294 +sg280 +I01 +sbaa(lp9442 +g401 +ag0 +(g190 +g2 +Ntp9443 +Rp9444 +(dp9445 +g194 +I01 +sg195 +(lp9446 +g0 +(g197 +g2 +Ntp9447 +Rp9448 +(dp9449 +g201 +g176 +(g177 +(I0 +tp9450 +g179 +tp9451 +Rp9452 +(I1 +(I1 +tp9453 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9454 +tp9455 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9456 +Rp9457 +(dp9458 +g201 +g176 +(g177 +(I0 +tp9459 +g179 +tp9460 +Rp9461 +(I1 +(I2 +tp9462 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9463 +tp9464 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9465 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9466 +g179 +tp9467 +Rp9468 +(I1 +(I1 +I1 +I1 +tp9469 +g38 +I00 +S'\xa874\xd3(\xe7\xc0?' +p9470 +tp9471 +bsg238 +g176 +(g177 +(I0 +tp9472 +g179 +tp9473 +Rp9474 +(I1 +(I1 +I1 +I1 +tp9475 +g38 +I00 +S'\xa9#\xa6\xfa\xf4\xd1\x13?' +p9476 +tp9477 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9478 +g179 +tp9479 +Rp9480 +(I1 +(I1 +I1 +I1 +tp9481 +g38 +I00 +S'+\x83\x8d\xf4\xd6\x9b\xa3?' +p9482 +tp9483 +bsg252 +g260 +sg48 +(lp9484 +g0 +(g52 +g2 +Ntp9485 +Rp9486 +(dp9487 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9488 +g179 +tp9489 +Rp9490 +(I1 +(I1 +I1 +I1 +tp9491 +g38 +I00 +S'u\x00\xe7G&\x93\x0b@' +p9492 +tp9493 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9494 +g454 +asg113 +I10295 +sg280 +I01 +sbaatp9495 +Rp9496 +sg337 +I00 +sg338 +Nsbaa(lp9497 +g458 +ag0 +(g459 +g2 +Ntp9498 +Rp9499 +(dp9500 +g17 +g9262 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9501 +(lp9502 +g189 +ag0 +(g190 +g2 +Ntp9503 +Rp9504 +(dp9505 +g194 +I01 +sg195 +(lp9506 +g0 +(g197 +g2 +Ntp9507 +Rp9508 +(dp9509 +g201 +g176 +(g177 +(I0 +tp9510 +g179 +tp9511 +Rp9512 +(I1 +(I1 +tp9513 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9514 +tp9515 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9516 +Rp9517 +(dp9518 +g201 +g176 +(g177 +(I0 +tp9519 +g179 +tp9520 +Rp9521 +(I1 +(I2 +tp9522 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9523 +tp9524 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp9525 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9526 +g179 +tp9527 +Rp9528 +(I1 +(I1 +I1 +I1 +tp9529 +g38 +I00 +S'\x93QniTS8@' +p9530 +tp9531 +bsg238 +g176 +(g177 +(I0 +tp9532 +g179 +tp9533 +Rp9534 +(I1 +(I1 +I1 +I1 +tp9535 +g38 +I00 +S'\x97=zZRoX?' +p9536 +tp9537 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9538 +g179 +tp9539 +Rp9540 +(I1 +(I1 +I1 +I1 +tp9541 +g38 +I00 +S',e}\x92\\\xa1\xe0?' +p9542 +tp9543 +bsg252 +g513 +sg48 +(lp9544 +g0 +(g52 +g2 +Ntp9545 +Rp9546 +(dp9547 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp9548 +g179 +tp9549 +Rp9550 +(I1 +(I1 +I1 +I1 +tp9551 +g38 +I00 +S'FV\x00.\xeabG@' +p9552 +tp9553 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp9554 +g527 +asg113 +I10298 +sg280 +I01 +sbaa(lp9555 +g529 +ag0 +(g190 +g2 +Ntp9556 +Rp9557 +(dp9558 +g194 +I01 +sg195 +(lp9559 +g0 +(g197 +g2 +Ntp9560 +Rp9561 +(dp9562 +g201 +g176 +(g177 +(I0 +tp9563 +g179 +tp9564 +Rp9565 +(I1 +(I1 +tp9566 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9567 +tp9568 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9569 +Rp9570 +(dp9571 +g201 +g176 +(g177 +(I0 +tp9572 +g179 +tp9573 +Rp9574 +(I1 +(I2 +tp9575 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9576 +tp9577 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9578 +Rp9579 +(dp9580 +g201 +g176 +(g177 +(I0 +tp9581 +g179 +tp9582 +Rp9583 +(I1 +(I2 +tp9584 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9585 +tp9586 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp9587 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9588 +g179 +tp9589 +Rp9590 +(I1 +(I1 +I1 +I1 +tp9591 +g38 +I00 +S'U\xbd\x04\xc0\xdb\xe8\x0c@' +p9592 +tp9593 +bsg238 +g176 +(g177 +(I0 +tp9594 +g179 +tp9595 +Rp9596 +(I1 +(I1 +I1 +I1 +tp9597 +g38 +I00 +S'o3\xd9\xab\xe7FC?' +p9598 +tp9599 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9600 +g179 +tp9601 +Rp9602 +(I1 +(I1 +I1 +I1 +tp9603 +g38 +I00 +S'_%\xf9$\x8a\xa3\xc9?' +p9604 +tp9605 +bsg252 +g586 +sg48 +(lp9606 +g0 +(g52 +g2 +Ntp9607 +Rp9608 +(dp9609 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp9610 +g179 +tp9611 +Rp9612 +(I1 +(I1 +I1 +I1 +tp9613 +g38 +I00 +S'G.\xff!\xfd\x062@' +p9614 +tp9615 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp9616 +g600 +asg113 +I10299 +sg280 +I01 +sbaatp9617 +Rp9618 +sg337 +I00 +sg338 +Nsbaa(lp9619 +g604 +ag0 +(g605 +g2 +Ntp9620 +Rp9621 +(dp9622 +g17 +g9262 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9623 +(lp9624 +g611 +ag0 +(g190 +g2 +Ntp9625 +Rp9626 +(dp9627 +g194 +I01 +sg195 +(lp9628 +g0 +(g197 +g2 +Ntp9629 +Rp9630 +(dp9631 +g201 +g176 +(g177 +(I0 +tp9632 +g179 +tp9633 +Rp9634 +(I1 +(I1 +tp9635 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9636 +tp9637 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9638 +Rp9639 +(dp9640 +g201 +g176 +(g177 +(I0 +tp9641 +g179 +tp9642 +Rp9643 +(I1 +(I2 +tp9644 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9645 +tp9646 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp9647 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9648 +g179 +tp9649 +Rp9650 +(I1 +(I1 +I1 +I1 +tp9651 +g38 +I00 +S'$\xba}\xa0,\xb1\xc0?' +p9652 +tp9653 +bsg238 +g176 +(g177 +(I0 +tp9654 +g179 +tp9655 +Rp9656 +(I1 +(I1 +I1 +I1 +tp9657 +g38 +I00 +S'\xec\x18\xb8\xb1Y\xd83?' +p9658 +tp9659 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9660 +g179 +tp9661 +Rp9662 +(I1 +(I1 +I1 +I1 +tp9663 +g38 +I00 +S'i\xc4\x9f\x079o\xa3?' +p9664 +tp9665 +bsg252 +g513 +sg48 +(lp9666 +g0 +(g52 +g2 +Ntp9667 +Rp9668 +(dp9669 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp9670 +g179 +tp9671 +Rp9672 +(I1 +(I1 +I1 +I1 +tp9673 +g38 +I00 +S'3\xac\xb82hT\x0b@' +p9674 +tp9675 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp9676 +g664 +asg113 +I10302 +sg280 +I01 +sbaa(lp9677 +g666 +ag0 +(g190 +g2 +Ntp9678 +Rp9679 +(dp9680 +g194 +I01 +sg195 +(lp9681 +g0 +(g197 +g2 +Ntp9682 +Rp9683 +(dp9684 +g201 +g176 +(g177 +(I0 +tp9685 +g179 +tp9686 +Rp9687 +(I1 +(I1 +tp9688 +g208 +I00 +S"#'\x00\x00\x00\x00\x00\x00" +p9689 +tp9690 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9691 +Rp9692 +(dp9693 +g201 +g176 +(g177 +(I0 +tp9694 +g179 +tp9695 +Rp9696 +(I1 +(I2 +tp9697 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9698 +tp9699 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp9700 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9701 +g179 +tp9702 +Rp9703 +(I1 +(I1 +I1 +I1 +tp9704 +g38 +I00 +S'%\xba}\xa0,\xb1\xc0?' +p9705 +tp9706 +bsg238 +g176 +(g177 +(I0 +tp9707 +g179 +tp9708 +Rp9709 +(I1 +(I1 +I1 +I1 +tp9710 +g38 +I00 +S'\xec\x18\xb8\xb1Y\xd83?' +p9711 +tp9712 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9713 +g179 +tp9714 +Rp9715 +(I1 +(I1 +I1 +I1 +tp9716 +g38 +I00 +S'j\xc4\x9f\x079o\xa3?' +p9717 +tp9718 +bsg252 +g713 +sg48 +(lp9719 +g0 +(g52 +g2 +Ntp9720 +Rp9721 +(dp9722 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp9723 +g179 +tp9724 +Rp9725 +(I1 +(I1 +I1 +I1 +tp9726 +g38 +I00 +S'5\xac\xb82hT\x0b@' +p9727 +tp9728 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp9729 +g727 +asg113 +I10303 +sg280 +I01 +sbaatp9730 +Rp9731 +sg337 +I00 +sg338 +Nsbaatp9732 +Rp9733 +aa(lp9734 +I10020 +ag7 +((lp9735 +(lp9736 +g12 +ag0 +(g13 +g2 +Ntp9737 +Rp9738 +(dp9739 +g17 +g0 +(g18 +g2 +Ntp9740 +Rp9741 +(dp9742 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p9743 +sg116 +g0 +(g117 +g2 +Ntp9744 +Rp9745 +(dp9746 +g121 +(lp9747 +g0 +(g123 +g2 +Ntp9748 +Rp9749 +(dp9750 +g127 +g8776 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp9751 +Rp9752 +(dp9753 +g127 +g0 +(g128 +g2 +Ntp9754 +Rp9755 +(dp9756 +g23 +g132 +sg133 +(dp9757 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'=\n\xd7\xa3p\xbd\x13@' +p9758 +tp9759 +Rp9760 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p9761 +sg113 +I41 +sg146 +(lp9762 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10020 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9763 +(lp9764 +g189 +ag0 +(g190 +g2 +Ntp9765 +Rp9766 +(dp9767 +g194 +I01 +sg195 +(lp9768 +g0 +(g197 +g2 +Ntp9769 +Rp9770 +(dp9771 +g201 +g176 +(g177 +(I0 +tp9772 +g179 +tp9773 +Rp9774 +(I1 +(I1 +tp9775 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p9776 +tp9777 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9778 +Rp9779 +(dp9780 +g201 +g176 +(g177 +(I0 +tp9781 +g179 +tp9782 +Rp9783 +(I1 +(I2 +tp9784 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9785 +tp9786 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9787 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9788 +g179 +tp9789 +Rp9790 +(I1 +(I1 +I1 +I1 +tp9791 +g38 +I00 +S'\x13or\xf3\x08pI@' +p9792 +tp9793 +bsg238 +g176 +(g177 +(I0 +tp9794 +g179 +tp9795 +Rp9796 +(I1 +(I1 +I1 +I1 +tp9797 +g38 +I00 +S'\xde\xc3\x88N?\x7fM?' +p9798 +tp9799 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9800 +g179 +tp9801 +Rp9802 +(I1 +(I1 +I1 +I1 +tp9803 +g38 +I00 +S'P/\x1e{\xc6\x0e\xe8?' +p9804 +tp9805 +bsg252 +g260 +sg48 +(lp9806 +g0 +(g52 +g2 +Ntp9807 +Rp9808 +(dp9809 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9810 +g179 +tp9811 +Rp9812 +(I1 +(I1 +I1 +I1 +tp9813 +g38 +I00 +S'D9\x91\x8ec\xeaP@' +p9814 +tp9815 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9816 +g279 +asg113 +I10306 +sg280 +I01 +sbaa(lp9817 +g12 +ag0 +(g190 +g2 +Ntp9818 +Rp9819 +(dp9820 +g194 +I01 +sg195 +(lp9821 +g0 +(g197 +g2 +Ntp9822 +Rp9823 +(dp9824 +g201 +g176 +(g177 +(I0 +tp9825 +g179 +tp9826 +Rp9827 +(I1 +(I1 +tp9828 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p9829 +tp9830 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9831 +Rp9832 +(dp9833 +g201 +g176 +(g177 +(I0 +tp9834 +g179 +tp9835 +Rp9836 +(I1 +(I2 +tp9837 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9838 +tp9839 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9840 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9841 +g179 +tp9842 +Rp9843 +(I1 +(I1 +I1 +I1 +tp9844 +g38 +I00 +S'\xf3>\xb6\x9a\xa5\xccN@' +p9845 +tp9846 +bsg238 +g176 +(g177 +(I0 +tp9847 +g179 +tp9848 +Rp9849 +(I1 +(I1 +I1 +I1 +tp9850 +g38 +I00 +S'\x02\xb2\xad\xf1\x13\x10X?' +p9851 +tp9852 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9853 +g179 +tp9854 +Rp9855 +(I1 +(I1 +I1 +I1 +tp9856 +g38 +I00 +S'\xb6U\xdf\xf1Qx\xea?' +p9857 +tp9858 +bsg252 +g260 +sg48 +(lp9859 +g0 +(g52 +g2 +Ntp9860 +Rp9861 +(dp9862 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9863 +g179 +tp9864 +Rp9865 +(I1 +(I1 +I1 +I1 +tp9866 +g38 +I00 +S'D\x08\x11\x9e\x99\x9cR@' +p9867 +tp9868 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9869 +g334 +asg113 +I10307 +sg280 +I01 +sbaatp9870 +Rp9871 +sg337 +I00 +sg338 +Nsbaa(lp9872 +g340 +ag0 +(g341 +g2 +Ntp9873 +Rp9874 +(dp9875 +g17 +g9741 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9876 +(lp9877 +g189 +ag0 +(g190 +g2 +Ntp9878 +Rp9879 +(dp9880 +g194 +I01 +sg195 +(lp9881 +g0 +(g197 +g2 +Ntp9882 +Rp9883 +(dp9884 +g201 +g176 +(g177 +(I0 +tp9885 +g179 +tp9886 +Rp9887 +(I1 +(I1 +tp9888 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p9889 +tp9890 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9891 +Rp9892 +(dp9893 +g201 +g176 +(g177 +(I0 +tp9894 +g179 +tp9895 +Rp9896 +(I1 +(I2 +tp9897 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9898 +tp9899 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9900 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9901 +g179 +tp9902 +Rp9903 +(I1 +(I1 +I1 +I1 +tp9904 +g38 +I00 +S'\x13or\xf3\x08pI@' +p9905 +tp9906 +bsg238 +g176 +(g177 +(I0 +tp9907 +g179 +tp9908 +Rp9909 +(I1 +(I1 +I1 +I1 +tp9910 +g38 +I00 +S'\xde\xc3\x88N?\x7fM?' +p9911 +tp9912 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9913 +g179 +tp9914 +Rp9915 +(I1 +(I1 +I1 +I1 +tp9916 +g38 +I00 +S'P/\x1e{\xc6\x0e\xe8?' +p9917 +tp9918 +bsg252 +g260 +sg48 +(lp9919 +g0 +(g52 +g2 +Ntp9920 +Rp9921 +(dp9922 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9923 +g179 +tp9924 +Rp9925 +(I1 +(I1 +I1 +I1 +tp9926 +g38 +I00 +S'D9\x91\x8ec\xeaP@' +p9927 +tp9928 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9929 +g279 +asg113 +I10310 +sg280 +I01 +sbaa(lp9930 +g401 +ag0 +(g190 +g2 +Ntp9931 +Rp9932 +(dp9933 +g194 +I01 +sg195 +(lp9934 +g0 +(g197 +g2 +Ntp9935 +Rp9936 +(dp9937 +g201 +g176 +(g177 +(I0 +tp9938 +g179 +tp9939 +Rp9940 +(I1 +(I1 +tp9941 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p9942 +tp9943 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp9944 +Rp9945 +(dp9946 +g201 +g176 +(g177 +(I0 +tp9947 +g179 +tp9948 +Rp9949 +(I1 +(I2 +tp9950 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p9951 +tp9952 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp9953 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp9954 +g179 +tp9955 +Rp9956 +(I1 +(I1 +I1 +I1 +tp9957 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9958 +tp9959 +bsg238 +g176 +(g177 +(I0 +tp9960 +g179 +tp9961 +Rp9962 +(I1 +(I1 +I1 +I1 +tp9963 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9964 +tp9965 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp9966 +g179 +tp9967 +Rp9968 +(I1 +(I1 +I1 +I1 +tp9969 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9970 +tp9971 +bsg252 +g260 +sg48 +(lp9972 +g0 +(g52 +g2 +Ntp9973 +Rp9974 +(dp9975 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp9976 +g179 +tp9977 +Rp9978 +(I1 +(I1 +I1 +I1 +tp9979 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p9980 +tp9981 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp9982 +g454 +asg113 +I10311 +sg280 +I01 +sbaatp9983 +Rp9984 +sg337 +I00 +sg338 +Nsbaa(lp9985 +g458 +ag0 +(g459 +g2 +Ntp9986 +Rp9987 +(dp9988 +g17 +g9741 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp9989 +(lp9990 +g189 +ag0 +(g190 +g2 +Ntp9991 +Rp9992 +(dp9993 +g194 +I01 +sg195 +(lp9994 +g0 +(g197 +g2 +Ntp9995 +Rp9996 +(dp9997 +g201 +g176 +(g177 +(I0 +tp9998 +g179 +tp9999 +Rp10000 +(I1 +(I1 +tp10001 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p10002 +tp10003 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10004 +Rp10005 +(dp10006 +g201 +g176 +(g177 +(I0 +tp10007 +g179 +tp10008 +Rp10009 +(I1 +(I2 +tp10010 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10011 +tp10012 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp10013 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10014 +g179 +tp10015 +Rp10016 +(I1 +(I1 +I1 +I1 +tp10017 +g38 +I00 +S'B\xf7[\x95\x02NI@' +p10018 +tp10019 +bsg238 +g176 +(g177 +(I0 +tp10020 +g179 +tp10021 +Rp10022 +(I1 +(I1 +I1 +I1 +tp10023 +g38 +I00 +S'OW\x93\xf82+X?' +p10024 +tp10025 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10026 +g179 +tp10027 +Rp10028 +(I1 +(I1 +I1 +I1 +tp10029 +g38 +I00 +S'h;\xc6\xa5\xff\xfd\xe7?' +p10030 +tp10031 +bsg252 +g513 +sg48 +(lp10032 +g0 +(g52 +g2 +Ntp10033 +Rp10034 +(dp10035 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp10036 +g179 +tp10037 +Rp10038 +(I1 +(I1 +I1 +I1 +tp10039 +g38 +I00 +S'\xc5a\x8f\xc0\x97\xdeP@' +p10040 +tp10041 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp10042 +g527 +asg113 +I10314 +sg280 +I01 +sbaa(lp10043 +g529 +ag0 +(g190 +g2 +Ntp10044 +Rp10045 +(dp10046 +g194 +I01 +sg195 +(lp10047 +g0 +(g197 +g2 +Ntp10048 +Rp10049 +(dp10050 +g201 +g176 +(g177 +(I0 +tp10051 +g179 +tp10052 +Rp10053 +(I1 +(I1 +tp10054 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p10055 +tp10056 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10057 +Rp10058 +(dp10059 +g201 +g176 +(g177 +(I0 +tp10060 +g179 +tp10061 +Rp10062 +(I1 +(I2 +tp10063 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10064 +tp10065 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10066 +Rp10067 +(dp10068 +g201 +g176 +(g177 +(I0 +tp10069 +g179 +tp10070 +Rp10071 +(I1 +(I2 +tp10072 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10073 +tp10074 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp10075 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10076 +g179 +tp10077 +Rp10078 +(I1 +(I1 +I1 +I1 +tp10079 +g38 +I00 +S'a\xe4#1Z\xeeM@' +p10080 +tp10081 +bsg238 +g176 +(g177 +(I0 +tp10082 +g179 +tp10083 +Rp10084 +(I1 +(I1 +I1 +I1 +tp10085 +g38 +I00 +S'\x8eYCg\x9a\xa5\\?' +p10086 +tp10087 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10088 +g179 +tp10089 +Rp10090 +(I1 +(I1 +I1 +I1 +tp10091 +g38 +I00 +S'\x81{u\x19\xaf\x17\xea?' +p10092 +tp10093 +bsg252 +g586 +sg48 +(lp10094 +g0 +(g52 +g2 +Ntp10095 +Rp10096 +(dp10097 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp10098 +g179 +tp10099 +Rp10100 +(I1 +(I1 +I1 +I1 +tp10101 +g38 +I00 +S'\xd7\x9a\xe6\x1d\xa7XR@' +p10102 +tp10103 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp10104 +g600 +asg113 +I10315 +sg280 +I01 +sbaatp10105 +Rp10106 +sg337 +I00 +sg338 +Nsbaa(lp10107 +g604 +ag0 +(g605 +g2 +Ntp10108 +Rp10109 +(dp10110 +g17 +g9741 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10111 +(lp10112 +g611 +ag0 +(g190 +g2 +Ntp10113 +Rp10114 +(dp10115 +g194 +I01 +sg195 +(lp10116 +g0 +(g197 +g2 +Ntp10117 +Rp10118 +(dp10119 +g201 +g176 +(g177 +(I0 +tp10120 +g179 +tp10121 +Rp10122 +(I1 +(I1 +tp10123 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p10124 +tp10125 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10126 +Rp10127 +(dp10128 +g201 +g176 +(g177 +(I0 +tp10129 +g179 +tp10130 +Rp10131 +(I1 +(I2 +tp10132 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10133 +tp10134 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp10135 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10136 +g179 +tp10137 +Rp10138 +(I1 +(I1 +I1 +I1 +tp10139 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10140 +tp10141 +bsg238 +g176 +(g177 +(I0 +tp10142 +g179 +tp10143 +Rp10144 +(I1 +(I1 +I1 +I1 +tp10145 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10146 +tp10147 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10148 +g179 +tp10149 +Rp10150 +(I1 +(I1 +I1 +I1 +tp10151 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10152 +tp10153 +bsg252 +g513 +sg48 +(lp10154 +g0 +(g52 +g2 +Ntp10155 +Rp10156 +(dp10157 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp10158 +g179 +tp10159 +Rp10160 +(I1 +(I1 +I1 +I1 +tp10161 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10162 +tp10163 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp10164 +g664 +asg113 +I10318 +sg280 +I01 +sbaa(lp10165 +g666 +ag0 +(g190 +g2 +Ntp10166 +Rp10167 +(dp10168 +g194 +I01 +sg195 +(lp10169 +g0 +(g197 +g2 +Ntp10170 +Rp10171 +(dp10172 +g201 +g176 +(g177 +(I0 +tp10173 +g179 +tp10174 +Rp10175 +(I1 +(I1 +tp10176 +g208 +I00 +S"$'\x00\x00\x00\x00\x00\x00" +p10177 +tp10178 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10179 +Rp10180 +(dp10181 +g201 +g176 +(g177 +(I0 +tp10182 +g179 +tp10183 +Rp10184 +(I1 +(I2 +tp10185 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10186 +tp10187 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp10188 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10189 +g179 +tp10190 +Rp10191 +(I1 +(I1 +I1 +I1 +tp10192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10193 +tp10194 +bsg238 +g176 +(g177 +(I0 +tp10195 +g179 +tp10196 +Rp10197 +(I1 +(I1 +I1 +I1 +tp10198 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10199 +tp10200 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10201 +g179 +tp10202 +Rp10203 +(I1 +(I1 +I1 +I1 +tp10204 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10205 +tp10206 +bsg252 +g713 +sg48 +(lp10207 +g0 +(g52 +g2 +Ntp10208 +Rp10209 +(dp10210 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp10211 +g179 +tp10212 +Rp10213 +(I1 +(I1 +I1 +I1 +tp10214 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10215 +tp10216 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp10217 +g727 +asg113 +I10319 +sg280 +I01 +sbaatp10218 +Rp10219 +sg337 +I00 +sg338 +Nsbaatp10220 +Rp10221 +aa(lp10222 +I10021 +ag7 +((lp10223 +(lp10224 +g12 +ag0 +(g13 +g2 +Ntp10225 +Rp10226 +(dp10227 +g17 +g0 +(g18 +g2 +Ntp10228 +Rp10229 +(dp10230 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p10231 +sg116 +g0 +(g117 +g2 +Ntp10232 +Rp10233 +(dp10234 +g121 +(lp10235 +g0 +(g123 +g2 +Ntp10236 +Rp10237 +(dp10238 +g127 +g0 +(g128 +g2 +Ntp10239 +Rp10240 +(dp10241 +g23 +g132 +sg133 +(dp10242 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xe1z\x14\xaeG\xe1\x10@' +p10243 +tp10244 +Rp10245 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p10246 +sg113 +I42 +sg146 +(lp10247 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp10248 +Rp10249 +(dp10250 +g127 +g0 +(g128 +g2 +Ntp10251 +Rp10252 +(dp10253 +g23 +g132 +sg133 +(dp10254 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xa4p=\n\xd7#\x11@' +p10255 +tp10256 +Rp10257 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p10258 +sg113 +I43 +sg146 +(lp10259 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10021 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10260 +(lp10261 +g189 +ag0 +(g190 +g2 +Ntp10262 +Rp10263 +(dp10264 +g194 +I01 +sg195 +(lp10265 +g0 +(g197 +g2 +Ntp10266 +Rp10267 +(dp10268 +g201 +g176 +(g177 +(I0 +tp10269 +g179 +tp10270 +Rp10271 +(I1 +(I1 +tp10272 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10273 +tp10274 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10275 +Rp10276 +(dp10277 +g201 +g176 +(g177 +(I0 +tp10278 +g179 +tp10279 +Rp10280 +(I1 +(I2 +tp10281 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10282 +tp10283 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10284 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10285 +g179 +tp10286 +Rp10287 +(I1 +(I1 +I1 +I1 +tp10288 +g38 +I00 +S'9*\x80tZ\xf4H@' +p10289 +tp10290 +bsg238 +g176 +(g177 +(I0 +tp10291 +g179 +tp10292 +Rp10293 +(I1 +(I1 +I1 +I1 +tp10294 +g38 +I00 +S'0\x08c\xde,\xa7D?' +p10295 +tp10296 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10297 +g179 +tp10298 +Rp10299 +(I1 +(I1 +I1 +I1 +tp10300 +g38 +I00 +S'=]\x1b\x194\xd4\xe7?' +p10301 +tp10302 +bsg252 +g260 +sg48 +(lp10303 +g0 +(g52 +g2 +Ntp10304 +Rp10305 +(dp10306 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10307 +g179 +tp10308 +Rp10309 +(I1 +(I1 +I1 +I1 +tp10310 +g38 +I00 +S'\x8f=\xa7\xa14\xc1P@' +p10311 +tp10312 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10313 +g279 +asg113 +I10322 +sg280 +I01 +sbaa(lp10314 +g12 +ag0 +(g190 +g2 +Ntp10315 +Rp10316 +(dp10317 +g194 +I01 +sg195 +(lp10318 +g0 +(g197 +g2 +Ntp10319 +Rp10320 +(dp10321 +g201 +g176 +(g177 +(I0 +tp10322 +g179 +tp10323 +Rp10324 +(I1 +(I1 +tp10325 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10326 +tp10327 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10328 +Rp10329 +(dp10330 +g201 +g176 +(g177 +(I0 +tp10331 +g179 +tp10332 +Rp10333 +(I1 +(I2 +tp10334 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10335 +tp10336 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10337 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10338 +g179 +tp10339 +Rp10340 +(I1 +(I1 +I1 +I1 +tp10341 +g38 +I00 +S'p\x98E\xff\xeb\xf6L@' +p10342 +tp10343 +bsg238 +g176 +(g177 +(I0 +tp10344 +g179 +tp10345 +Rp10346 +(I1 +(I1 +I1 +I1 +tp10347 +g38 +I00 +S'b{\xcc\x10\xd0xP?' +p10348 +tp10349 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10350 +g179 +tp10351 +Rp10352 +(I1 +(I1 +I1 +I1 +tp10353 +g38 +I00 +S'\xdeOm\xba\xd5\xab\xe9?' +p10354 +tp10355 +bsg252 +g260 +sg48 +(lp10356 +g0 +(g52 +g2 +Ntp10357 +Rp10358 +(dp10359 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10360 +g179 +tp10361 +Rp10362 +(I1 +(I1 +I1 +I1 +tp10363 +g38 +I00 +S'(\xdc\x14G\xd2\x0cR@' +p10364 +tp10365 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10366 +g334 +asg113 +I10323 +sg280 +I01 +sbaatp10367 +Rp10368 +sg337 +I00 +sg338 +Nsbaa(lp10369 +g340 +ag0 +(g341 +g2 +Ntp10370 +Rp10371 +(dp10372 +g17 +g10229 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10373 +(lp10374 +g189 +ag0 +(g190 +g2 +Ntp10375 +Rp10376 +(dp10377 +g194 +I01 +sg195 +(lp10378 +g0 +(g197 +g2 +Ntp10379 +Rp10380 +(dp10381 +g201 +g176 +(g177 +(I0 +tp10382 +g179 +tp10383 +Rp10384 +(I1 +(I1 +tp10385 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10386 +tp10387 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10388 +Rp10389 +(dp10390 +g201 +g176 +(g177 +(I0 +tp10391 +g179 +tp10392 +Rp10393 +(I1 +(I2 +tp10394 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10395 +tp10396 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10397 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10398 +g179 +tp10399 +Rp10400 +(I1 +(I1 +I1 +I1 +tp10401 +g38 +I00 +S'9*\x80tZ\xf4H@' +p10402 +tp10403 +bsg238 +g176 +(g177 +(I0 +tp10404 +g179 +tp10405 +Rp10406 +(I1 +(I1 +I1 +I1 +tp10407 +g38 +I00 +S'0\x08c\xde,\xa7D?' +p10408 +tp10409 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10410 +g179 +tp10411 +Rp10412 +(I1 +(I1 +I1 +I1 +tp10413 +g38 +I00 +S'=]\x1b\x194\xd4\xe7?' +p10414 +tp10415 +bsg252 +g260 +sg48 +(lp10416 +g0 +(g52 +g2 +Ntp10417 +Rp10418 +(dp10419 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10420 +g179 +tp10421 +Rp10422 +(I1 +(I1 +I1 +I1 +tp10423 +g38 +I00 +S'\x8f=\xa7\xa14\xc1P@' +p10424 +tp10425 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10426 +g279 +asg113 +I10326 +sg280 +I01 +sbaa(lp10427 +g401 +ag0 +(g190 +g2 +Ntp10428 +Rp10429 +(dp10430 +g194 +I01 +sg195 +(lp10431 +g0 +(g197 +g2 +Ntp10432 +Rp10433 +(dp10434 +g201 +g176 +(g177 +(I0 +tp10435 +g179 +tp10436 +Rp10437 +(I1 +(I1 +tp10438 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10439 +tp10440 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10441 +Rp10442 +(dp10443 +g201 +g176 +(g177 +(I0 +tp10444 +g179 +tp10445 +Rp10446 +(I1 +(I2 +tp10447 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10448 +tp10449 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10450 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10451 +g179 +tp10452 +Rp10453 +(I1 +(I1 +I1 +I1 +tp10454 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10455 +tp10456 +bsg238 +g176 +(g177 +(I0 +tp10457 +g179 +tp10458 +Rp10459 +(I1 +(I1 +I1 +I1 +tp10460 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10461 +tp10462 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10463 +g179 +tp10464 +Rp10465 +(I1 +(I1 +I1 +I1 +tp10466 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10467 +tp10468 +bsg252 +g260 +sg48 +(lp10469 +g0 +(g52 +g2 +Ntp10470 +Rp10471 +(dp10472 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10473 +g179 +tp10474 +Rp10475 +(I1 +(I1 +I1 +I1 +tp10476 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10477 +tp10478 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10479 +g454 +asg113 +I10327 +sg280 +I01 +sbaatp10480 +Rp10481 +sg337 +I00 +sg338 +Nsbaa(lp10482 +g458 +ag0 +(g459 +g2 +Ntp10483 +Rp10484 +(dp10485 +g17 +g10229 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10486 +(lp10487 +g189 +ag0 +(g190 +g2 +Ntp10488 +Rp10489 +(dp10490 +g194 +I01 +sg195 +(lp10491 +g0 +(g197 +g2 +Ntp10492 +Rp10493 +(dp10494 +g201 +g176 +(g177 +(I0 +tp10495 +g179 +tp10496 +Rp10497 +(I1 +(I1 +tp10498 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10499 +tp10500 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10501 +Rp10502 +(dp10503 +g201 +g176 +(g177 +(I0 +tp10504 +g179 +tp10505 +Rp10506 +(I1 +(I2 +tp10507 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10508 +tp10509 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp10510 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10511 +g179 +tp10512 +Rp10513 +(I1 +(I1 +I1 +I1 +tp10514 +g38 +I00 +S'\xed\x84R\xf5\x84\xdeH@' +p10515 +tp10516 +bsg238 +g176 +(g177 +(I0 +tp10517 +g179 +tp10518 +Rp10519 +(I1 +(I1 +I1 +I1 +tp10520 +g38 +I00 +S'\xe9\x89\x08\xdc\x1a\xb1V?' +p10521 +tp10522 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10523 +g179 +tp10524 +Rp10525 +(I1 +(I1 +I1 +I1 +tp10526 +g38 +I00 +S'\x17\xbc@\x00\x06\xc9\xe7?' +p10527 +tp10528 +bsg252 +g513 +sg48 +(lp10529 +g0 +(g52 +g2 +Ntp10530 +Rp10531 +(dp10532 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp10533 +g179 +tp10534 +Rp10535 +(I1 +(I1 +I1 +I1 +tp10536 +g38 +I00 +S'@\x84-8X\xb9P@' +p10537 +tp10538 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp10539 +g527 +asg113 +I10330 +sg280 +I01 +sbaa(lp10540 +g529 +ag0 +(g190 +g2 +Ntp10541 +Rp10542 +(dp10543 +g194 +I01 +sg195 +(lp10544 +g0 +(g197 +g2 +Ntp10545 +Rp10546 +(dp10547 +g201 +g176 +(g177 +(I0 +tp10548 +g179 +tp10549 +Rp10550 +(I1 +(I1 +tp10551 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10552 +tp10553 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10554 +Rp10555 +(dp10556 +g201 +g176 +(g177 +(I0 +tp10557 +g179 +tp10558 +Rp10559 +(I1 +(I2 +tp10560 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10561 +tp10562 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10563 +Rp10564 +(dp10565 +g201 +g176 +(g177 +(I0 +tp10566 +g179 +tp10567 +Rp10568 +(I1 +(I2 +tp10569 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10570 +tp10571 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp10572 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10573 +g179 +tp10574 +Rp10575 +(I1 +(I1 +I1 +I1 +tp10576 +g38 +I00 +S'e8\xa6@\xc97L@' +p10577 +tp10578 +bsg238 +g176 +(g177 +(I0 +tp10579 +g179 +tp10580 +Rp10581 +(I1 +(I1 +I1 +I1 +tp10582 +g38 +I00 +S'\x9c-i\x1e.\xaaV?' +p10583 +tp10584 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10585 +g179 +tp10586 +Rp10587 +(I1 +(I1 +I1 +I1 +tp10588 +g38 +I00 +S"9\xael\x0c'V\xe9?" +p10589 +tp10590 +bsg252 +g586 +sg48 +(lp10591 +g0 +(g52 +g2 +Ntp10592 +Rp10593 +(dp10594 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp10595 +g179 +tp10596 +Rp10597 +(I1 +(I1 +I1 +I1 +tp10598 +g38 +I00 +S'\x80j\xbct\x93\xd0Q@' +p10599 +tp10600 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp10601 +g600 +asg113 +I10331 +sg280 +I01 +sbaatp10602 +Rp10603 +sg337 +I00 +sg338 +Nsbaa(lp10604 +g604 +ag0 +(g605 +g2 +Ntp10605 +Rp10606 +(dp10607 +g17 +g10229 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10608 +(lp10609 +g611 +ag0 +(g190 +g2 +Ntp10610 +Rp10611 +(dp10612 +g194 +I01 +sg195 +(lp10613 +g0 +(g197 +g2 +Ntp10614 +Rp10615 +(dp10616 +g201 +g176 +(g177 +(I0 +tp10617 +g179 +tp10618 +Rp10619 +(I1 +(I1 +tp10620 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10621 +tp10622 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10623 +Rp10624 +(dp10625 +g201 +g176 +(g177 +(I0 +tp10626 +g179 +tp10627 +Rp10628 +(I1 +(I2 +tp10629 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10630 +tp10631 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp10632 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10633 +g179 +tp10634 +Rp10635 +(I1 +(I1 +I1 +I1 +tp10636 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10637 +tp10638 +bsg238 +g176 +(g177 +(I0 +tp10639 +g179 +tp10640 +Rp10641 +(I1 +(I1 +I1 +I1 +tp10642 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10643 +tp10644 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10645 +g179 +tp10646 +Rp10647 +(I1 +(I1 +I1 +I1 +tp10648 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10649 +tp10650 +bsg252 +g513 +sg48 +(lp10651 +g0 +(g52 +g2 +Ntp10652 +Rp10653 +(dp10654 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp10655 +g179 +tp10656 +Rp10657 +(I1 +(I1 +I1 +I1 +tp10658 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10659 +tp10660 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp10661 +g664 +asg113 +I10334 +sg280 +I01 +sbaa(lp10662 +g666 +ag0 +(g190 +g2 +Ntp10663 +Rp10664 +(dp10665 +g194 +I01 +sg195 +(lp10666 +g0 +(g197 +g2 +Ntp10667 +Rp10668 +(dp10669 +g201 +g176 +(g177 +(I0 +tp10670 +g179 +tp10671 +Rp10672 +(I1 +(I1 +tp10673 +g208 +I00 +S"%'\x00\x00\x00\x00\x00\x00" +p10674 +tp10675 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10676 +Rp10677 +(dp10678 +g201 +g176 +(g177 +(I0 +tp10679 +g179 +tp10680 +Rp10681 +(I1 +(I2 +tp10682 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10683 +tp10684 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp10685 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10686 +g179 +tp10687 +Rp10688 +(I1 +(I1 +I1 +I1 +tp10689 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10690 +tp10691 +bsg238 +g176 +(g177 +(I0 +tp10692 +g179 +tp10693 +Rp10694 +(I1 +(I1 +I1 +I1 +tp10695 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10696 +tp10697 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10698 +g179 +tp10699 +Rp10700 +(I1 +(I1 +I1 +I1 +tp10701 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10702 +tp10703 +bsg252 +g713 +sg48 +(lp10704 +g0 +(g52 +g2 +Ntp10705 +Rp10706 +(dp10707 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp10708 +g179 +tp10709 +Rp10710 +(I1 +(I1 +I1 +I1 +tp10711 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10712 +tp10713 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp10714 +g727 +asg113 +I10335 +sg280 +I01 +sbaatp10715 +Rp10716 +sg337 +I00 +sg338 +Nsbaatp10717 +Rp10718 +aa(lp10719 +I10022 +ag7 +((lp10720 +(lp10721 +g12 +ag0 +(g13 +g2 +Ntp10722 +Rp10723 +(dp10724 +g17 +g0 +(g18 +g2 +Ntp10725 +Rp10726 +(dp10727 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p10728 +sg116 +g0 +(g117 +g2 +Ntp10729 +Rp10730 +(dp10731 +g121 +(lp10732 +g0 +(g123 +g2 +Ntp10733 +Rp10734 +(dp10735 +g127 +g0 +(g128 +g2 +Ntp10736 +Rp10737 +(dp10738 +g23 +g132 +sg133 +(dp10739 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xe1z\x14\xaeG\xe1\x07@' +p10740 +tp10741 +Rp10742 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p10743 +sg113 +I44 +sg146 +(lp10744 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp10745 +Rp10746 +(dp10747 +g127 +g0 +(g128 +g2 +Ntp10748 +Rp10749 +(dp10750 +g23 +g132 +sg133 +(dp10751 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\x08@' +p10752 +tp10753 +Rp10754 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p10755 +sg113 +I45 +sg146 +(lp10756 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10022 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10757 +(lp10758 +g189 +ag0 +(g190 +g2 +Ntp10759 +Rp10760 +(dp10761 +g194 +I01 +sg195 +(lp10762 +g0 +(g197 +g2 +Ntp10763 +Rp10764 +(dp10765 +g201 +g176 +(g177 +(I0 +tp10766 +g179 +tp10767 +Rp10768 +(I1 +(I1 +tp10769 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p10770 +tp10771 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10772 +Rp10773 +(dp10774 +g201 +g176 +(g177 +(I0 +tp10775 +g179 +tp10776 +Rp10777 +(I1 +(I2 +tp10778 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10779 +tp10780 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10781 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10782 +g179 +tp10783 +Rp10784 +(I1 +(I1 +I1 +I1 +tp10785 +g38 +I00 +S'\xeb\x01\xdd\x9a\xc0\xe0E@' +p10786 +tp10787 +bsg238 +g176 +(g177 +(I0 +tp10788 +g179 +tp10789 +Rp10790 +(I1 +(I1 +I1 +I1 +tp10791 +g38 +I00 +S'7\xad\xa9\x1b\xc2\xf1D?' +p10792 +tp10793 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10794 +g179 +tp10795 +Rp10796 +(I1 +(I1 +I1 +I1 +tp10797 +g38 +I00 +S'\xa3\xc0$\xe9\xc4O\xe6?' +p10798 +tp10799 +bsg252 +g260 +sg48 +(lp10800 +g0 +(g52 +g2 +Ntp10801 +Rp10802 +(dp10803 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10804 +g179 +tp10805 +Rp10806 +(I1 +(I1 +I1 +I1 +tp10807 +g38 +I00 +S'\xe5\xae\xdb\xe7,`O@' +p10808 +tp10809 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10810 +g279 +asg113 +I10338 +sg280 +I01 +sbaa(lp10811 +g12 +ag0 +(g190 +g2 +Ntp10812 +Rp10813 +(dp10814 +g194 +I01 +sg195 +(lp10815 +g0 +(g197 +g2 +Ntp10816 +Rp10817 +(dp10818 +g201 +g176 +(g177 +(I0 +tp10819 +g179 +tp10820 +Rp10821 +(I1 +(I1 +tp10822 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p10823 +tp10824 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10825 +Rp10826 +(dp10827 +g201 +g176 +(g177 +(I0 +tp10828 +g179 +tp10829 +Rp10830 +(I1 +(I2 +tp10831 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10832 +tp10833 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10834 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10835 +g179 +tp10836 +Rp10837 +(I1 +(I1 +I1 +I1 +tp10838 +g38 +I00 +S'b\xb7k9\xd0\xa9B@' +p10839 +tp10840 +bsg238 +g176 +(g177 +(I0 +tp10841 +g179 +tp10842 +Rp10843 +(I1 +(I1 +I1 +I1 +tp10844 +g38 +I00 +S'\xe9\xd9\x8a\x1bm\x0fH?' +p10845 +tp10846 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10847 +g179 +tp10848 +Rp10849 +(I1 +(I1 +I1 +I1 +tp10850 +g38 +I00 +S'fC\xca{_\x9b\xe4?' +p10851 +tp10852 +bsg252 +g260 +sg48 +(lp10853 +g0 +(g52 +g2 +Ntp10854 +Rp10855 +(dp10856 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10857 +g179 +tp10858 +Rp10859 +(I1 +(I1 +I1 +I1 +tp10860 +g38 +I00 +S'\xc7n\x14F~\xfaL@' +p10861 +tp10862 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10863 +g334 +asg113 +I10339 +sg280 +I01 +sbaatp10864 +Rp10865 +sg337 +I00 +sg338 +Nsbaa(lp10866 +g340 +ag0 +(g341 +g2 +Ntp10867 +Rp10868 +(dp10869 +g17 +g10726 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10870 +(lp10871 +g189 +ag0 +(g190 +g2 +Ntp10872 +Rp10873 +(dp10874 +g194 +I01 +sg195 +(lp10875 +g0 +(g197 +g2 +Ntp10876 +Rp10877 +(dp10878 +g201 +g176 +(g177 +(I0 +tp10879 +g179 +tp10880 +Rp10881 +(I1 +(I1 +tp10882 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p10883 +tp10884 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10885 +Rp10886 +(dp10887 +g201 +g176 +(g177 +(I0 +tp10888 +g179 +tp10889 +Rp10890 +(I1 +(I2 +tp10891 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10892 +tp10893 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10894 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10895 +g179 +tp10896 +Rp10897 +(I1 +(I1 +I1 +I1 +tp10898 +g38 +I00 +S'\xeb\x01\xdd\x9a\xc0\xe0E@' +p10899 +tp10900 +bsg238 +g176 +(g177 +(I0 +tp10901 +g179 +tp10902 +Rp10903 +(I1 +(I1 +I1 +I1 +tp10904 +g38 +I00 +S'7\xad\xa9\x1b\xc2\xf1D?' +p10905 +tp10906 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10907 +g179 +tp10908 +Rp10909 +(I1 +(I1 +I1 +I1 +tp10910 +g38 +I00 +S'\xa3\xc0$\xe9\xc4O\xe6?' +p10911 +tp10912 +bsg252 +g260 +sg48 +(lp10913 +g0 +(g52 +g2 +Ntp10914 +Rp10915 +(dp10916 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10917 +g179 +tp10918 +Rp10919 +(I1 +(I1 +I1 +I1 +tp10920 +g38 +I00 +S'\xe5\xae\xdb\xe7,`O@' +p10921 +tp10922 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10923 +g279 +asg113 +I10342 +sg280 +I01 +sbaa(lp10924 +g401 +ag0 +(g190 +g2 +Ntp10925 +Rp10926 +(dp10927 +g194 +I01 +sg195 +(lp10928 +g0 +(g197 +g2 +Ntp10929 +Rp10930 +(dp10931 +g201 +g176 +(g177 +(I0 +tp10932 +g179 +tp10933 +Rp10934 +(I1 +(I1 +tp10935 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p10936 +tp10937 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10938 +Rp10939 +(dp10940 +g201 +g176 +(g177 +(I0 +tp10941 +g179 +tp10942 +Rp10943 +(I1 +(I2 +tp10944 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p10945 +tp10946 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp10947 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp10948 +g179 +tp10949 +Rp10950 +(I1 +(I1 +I1 +I1 +tp10951 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10952 +tp10953 +bsg238 +g176 +(g177 +(I0 +tp10954 +g179 +tp10955 +Rp10956 +(I1 +(I1 +I1 +I1 +tp10957 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10958 +tp10959 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp10960 +g179 +tp10961 +Rp10962 +(I1 +(I1 +I1 +I1 +tp10963 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10964 +tp10965 +bsg252 +g260 +sg48 +(lp10966 +g0 +(g52 +g2 +Ntp10967 +Rp10968 +(dp10969 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp10970 +g179 +tp10971 +Rp10972 +(I1 +(I1 +I1 +I1 +tp10973 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p10974 +tp10975 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp10976 +g454 +asg113 +I10343 +sg280 +I01 +sbaatp10977 +Rp10978 +sg337 +I00 +sg338 +Nsbaa(lp10979 +g458 +ag0 +(g459 +g2 +Ntp10980 +Rp10981 +(dp10982 +g17 +g10726 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp10983 +(lp10984 +g189 +ag0 +(g190 +g2 +Ntp10985 +Rp10986 +(dp10987 +g194 +I01 +sg195 +(lp10988 +g0 +(g197 +g2 +Ntp10989 +Rp10990 +(dp10991 +g201 +g176 +(g177 +(I0 +tp10992 +g179 +tp10993 +Rp10994 +(I1 +(I1 +tp10995 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p10996 +tp10997 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp10998 +Rp10999 +(dp11000 +g201 +g176 +(g177 +(I0 +tp11001 +g179 +tp11002 +Rp11003 +(I1 +(I2 +tp11004 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11005 +tp11006 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp11007 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11008 +g179 +tp11009 +Rp11010 +(I1 +(I1 +I1 +I1 +tp11011 +g38 +I00 +S'\x1f\x92\xa6\x84\xef\xceE@' +p11012 +tp11013 +bsg238 +g176 +(g177 +(I0 +tp11014 +g179 +tp11015 +Rp11016 +(I1 +(I1 +I1 +I1 +tp11017 +g38 +I00 +S'-Z\xbb=\x04\x06Y?' +p11018 +tp11019 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11020 +g179 +tp11021 +Rp11022 +(I1 +(I1 +I1 +I1 +tp11023 +g38 +I00 +S'\xfd*B)\xabE\xe6?' +p11024 +tp11025 +bsg252 +g513 +sg48 +(lp11026 +g0 +(g52 +g2 +Ntp11027 +Rp11028 +(dp11029 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp11030 +g179 +tp11031 +Rp11032 +(I1 +(I1 +I1 +I1 +tp11033 +g38 +I00 +S't\x0c\x05\xb2\xf8QO@' +p11034 +tp11035 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp11036 +g527 +asg113 +I10346 +sg280 +I01 +sbaa(lp11037 +g529 +ag0 +(g190 +g2 +Ntp11038 +Rp11039 +(dp11040 +g194 +I01 +sg195 +(lp11041 +g0 +(g197 +g2 +Ntp11042 +Rp11043 +(dp11044 +g201 +g176 +(g177 +(I0 +tp11045 +g179 +tp11046 +Rp11047 +(I1 +(I1 +tp11048 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p11049 +tp11050 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11051 +Rp11052 +(dp11053 +g201 +g176 +(g177 +(I0 +tp11054 +g179 +tp11055 +Rp11056 +(I1 +(I2 +tp11057 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11058 +tp11059 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11060 +Rp11061 +(dp11062 +g201 +g176 +(g177 +(I0 +tp11063 +g179 +tp11064 +Rp11065 +(I1 +(I2 +tp11066 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11067 +tp11068 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp11069 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11070 +g179 +tp11071 +Rp11072 +(I1 +(I1 +I1 +I1 +tp11073 +g38 +I00 +S'sG9w\xbfLB@' +p11074 +tp11075 +bsg238 +g176 +(g177 +(I0 +tp11076 +g179 +tp11077 +Rp11078 +(I1 +(I1 +I1 +I1 +tp11079 +g38 +I00 +S'H\x88\xf5\xe4\xc1\xf9Q?' +p11080 +tp11081 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11082 +g179 +tp11083 +Rp11084 +(I1 +(I1 +I1 +I1 +tp11085 +g38 +I00 +S'\xc4\xf8V\x11[g\xe4?' +p11086 +tp11087 +bsg252 +g586 +sg48 +(lp11088 +g0 +(g52 +g2 +Ntp11089 +Rp11090 +(dp11091 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp11092 +g179 +tp11093 +Rp11094 +(I1 +(I1 +I1 +I1 +tp11095 +g38 +I00 +S'\xd3Mb\x10X\xb1L@' +p11096 +tp11097 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp11098 +g600 +asg113 +I10347 +sg280 +I01 +sbaatp11099 +Rp11100 +sg337 +I00 +sg338 +Nsbaa(lp11101 +g604 +ag0 +(g605 +g2 +Ntp11102 +Rp11103 +(dp11104 +g17 +g10726 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp11105 +(lp11106 +g611 +ag0 +(g190 +g2 +Ntp11107 +Rp11108 +(dp11109 +g194 +I01 +sg195 +(lp11110 +g0 +(g197 +g2 +Ntp11111 +Rp11112 +(dp11113 +g201 +g176 +(g177 +(I0 +tp11114 +g179 +tp11115 +Rp11116 +(I1 +(I1 +tp11117 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p11118 +tp11119 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11120 +Rp11121 +(dp11122 +g201 +g176 +(g177 +(I0 +tp11123 +g179 +tp11124 +Rp11125 +(I1 +(I2 +tp11126 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11127 +tp11128 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp11129 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11130 +g179 +tp11131 +Rp11132 +(I1 +(I1 +I1 +I1 +tp11133 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11134 +tp11135 +bsg238 +g176 +(g177 +(I0 +tp11136 +g179 +tp11137 +Rp11138 +(I1 +(I1 +I1 +I1 +tp11139 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11140 +tp11141 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11142 +g179 +tp11143 +Rp11144 +(I1 +(I1 +I1 +I1 +tp11145 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11146 +tp11147 +bsg252 +g513 +sg48 +(lp11148 +g0 +(g52 +g2 +Ntp11149 +Rp11150 +(dp11151 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp11152 +g179 +tp11153 +Rp11154 +(I1 +(I1 +I1 +I1 +tp11155 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11156 +tp11157 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp11158 +g664 +asg113 +I10350 +sg280 +I01 +sbaa(lp11159 +g666 +ag0 +(g190 +g2 +Ntp11160 +Rp11161 +(dp11162 +g194 +I01 +sg195 +(lp11163 +g0 +(g197 +g2 +Ntp11164 +Rp11165 +(dp11166 +g201 +g176 +(g177 +(I0 +tp11167 +g179 +tp11168 +Rp11169 +(I1 +(I1 +tp11170 +g208 +I00 +S"&'\x00\x00\x00\x00\x00\x00" +p11171 +tp11172 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11173 +Rp11174 +(dp11175 +g201 +g176 +(g177 +(I0 +tp11176 +g179 +tp11177 +Rp11178 +(I1 +(I2 +tp11179 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11180 +tp11181 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp11182 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11183 +g179 +tp11184 +Rp11185 +(I1 +(I1 +I1 +I1 +tp11186 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11187 +tp11188 +bsg238 +g176 +(g177 +(I0 +tp11189 +g179 +tp11190 +Rp11191 +(I1 +(I1 +I1 +I1 +tp11192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11193 +tp11194 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11195 +g179 +tp11196 +Rp11197 +(I1 +(I1 +I1 +I1 +tp11198 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11199 +tp11200 +bsg252 +g713 +sg48 +(lp11201 +g0 +(g52 +g2 +Ntp11202 +Rp11203 +(dp11204 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp11205 +g179 +tp11206 +Rp11207 +(I1 +(I1 +I1 +I1 +tp11208 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11209 +tp11210 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp11211 +g727 +asg113 +I10351 +sg280 +I01 +sbaatp11212 +Rp11213 +sg337 +I00 +sg338 +Nsbaatp11214 +Rp11215 +aa(lp11216 +I10023 +ag7 +((lp11217 +(lp11218 +g12 +ag0 +(g13 +g2 +Ntp11219 +Rp11220 +(dp11221 +g17 +g0 +(g18 +g2 +Ntp11222 +Rp11223 +(dp11224 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p11225 +sg116 +g0 +(g117 +g2 +Ntp11226 +Rp11227 +(dp11228 +g121 +(lp11229 +g0 +(g123 +g2 +Ntp11230 +Rp11231 +(dp11232 +g127 +g0 +(g128 +g2 +Ntp11233 +Rp11234 +(dp11235 +g23 +g132 +sg133 +(dp11236 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xa4p=\n\xd7\xa3\x00@' +p11237 +tp11238 +Rp11239 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p11240 +sg113 +I46 +sg146 +(lp11241 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp11242 +Rp11243 +(dp11244 +g127 +g0 +(g128 +g2 +Ntp11245 +Rp11246 +(dp11247 +g23 +g132 +sg133 +(dp11248 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'{\x14\xaeG\xe1z\x00@' +p11249 +tp11250 +Rp11251 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p11252 +sg113 +I47 +sg146 +(lp11253 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10023 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp11254 +(lp11255 +g189 +ag0 +(g190 +g2 +Ntp11256 +Rp11257 +(dp11258 +g194 +I01 +sg195 +(lp11259 +g0 +(g197 +g2 +Ntp11260 +Rp11261 +(dp11262 +g201 +g176 +(g177 +(I0 +tp11263 +g179 +tp11264 +Rp11265 +(I1 +(I1 +tp11266 +g208 +I00 +S"''\x00\x00\x00\x00\x00\x00" +p11267 +tp11268 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11269 +Rp11270 +(dp11271 +g201 +g176 +(g177 +(I0 +tp11272 +g179 +tp11273 +Rp11274 +(I1 +(I2 +tp11275 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11276 +tp11277 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp11278 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11279 +g179 +tp11280 +Rp11281 +(I1 +(I1 +I1 +I1 +tp11282 +g38 +I00 +S'\xeb\x8a[N\xb5\xcd\x0e@' +p11283 +tp11284 +bsg238 +g176 +(g177 +(I0 +tp11285 +g179 +tp11286 +Rp11287 +(I1 +(I1 +I1 +I1 +tp11288 +g38 +I00 +S'G\xc6\x97\x9fN\xe2-?' +p11289 +tp11290 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11291 +g179 +tp11292 +Rp11293 +(I1 +(I1 +I1 +I1 +tp11294 +g38 +I00 +S'\xce\xe8";\\y\xca?' +p11295 +tp11296 +bsg252 +g260 +sg48 +(lp11297 +g0 +(g52 +g2 +Ntp11298 +Rp11299 +(dp11300 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp11301 +g179 +tp11302 +Rp11303 +(I1 +(I1 +I1 +I1 +tp11304 +g38 +I00 +S'\xb1\x8b\x94\xd9T\x9d2@' +p11305 +tp11306 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp11307 +g279 +asg113 +I10354 +sg280 +I01 +sbaa(lp11308 +g12 +ag0 +(g190 +g2 +Ntp11309 +Rp11310 +(dp11311 +g194 +I01 +sg195 +(lp11312 +g0 +(g197 +g2 +Ntp11313 +Rp11314 +(dp11315 +g201 +g176 +(g177 +(I0 +tp11316 +g179 +tp11317 +Rp11318 +(I1 +(I1 +tp11319 +g208 +I00 +S"''\x00\x00\x00\x00\x00\x00" +p11320 +tp11321 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11322 +Rp11323 +(dp11324 +g201 +g176 +(g177 +(I0 +tp11325 +g179 +tp11326 +Rp11327 +(I1 +(I2 +tp11328 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11329 +tp11330 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp11331 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11332 +g179 +tp11333 +Rp11334 +(I1 +(I1 +I1 +I1 +tp11335 +g38 +I00 +S'\xcd \xa1\x92d\x99\xd7?' +p11336 +tp11337 +bsg238 +g176 +(g177 +(I0 +tp11338 +g179 +tp11339 +Rp11340 +(I1 +(I1 +I1 +I1 +tp11341 +g38 +I00 +S'J\xe8\xaf\x1d\xb9\x01\x13?' +p11342 +tp11343 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11344 +g179 +tp11345 +Rp11346 +(I1 +(I1 +I1 +I1 +tp11347 +g38 +I00 +S't\x01\x82H\x9eb\xb0?' +p11348 +tp11349 +bsg252 +g260 +sg48 +(lp11350 +g0 +(g52 +g2 +Ntp11351 +Rp11352 +(dp11353 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp11354 +g179 +tp11355 +Rp11356 +(I1 +(I1 +I1 +I1 +tp11357 +g38 +I00 +S'\x0b\xd2\xf6\x95\xae\n\x17@' +p11358 +tp11359 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp11360 +g334 +asg113 +I10355 +sg280 +I01 +sbaatp11361 +Rp11362 +sg337 +I00 +sg338 +Nsbaa(lp11363 +g340 +ag0 +(g341 +g2 +Ntp11364 +Rp11365 +(dp11366 +g17 +g11223 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp11367 +(lp11368 +g189 +ag0 +(g190 +g2 +Ntp11369 +Rp11370 +(dp11371 +g194 +I01 +sg195 +(lp11372 +g0 +(g197 +g2 +Ntp11373 +Rp11374 +(dp11375 +g201 +g176 +(g177 +(I0 +tp11376 +g179 +tp11377 +Rp11378 +(I1 +(I1 +tp11379 +g208 +I00 +S"''\x00\x00\x00\x00\x00\x00" +p11380 +tp11381 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11382 +Rp11383 +(dp11384 +g201 +g176 +(g177 +(I0 +tp11385 +g179 +tp11386 +Rp11387 +(I1 +(I2 +tp11388 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11389 +tp11390 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp11391 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11392 +g179 +tp11393 +Rp11394 +(I1 +(I1 +I1 +I1 +tp11395 +g38 +I00 +S'\xeb\x8a[N\xb5\xcd\x0e@' +p11396 +tp11397 +bsg238 +g176 +(g177 +(I0 +tp11398 +g179 +tp11399 +Rp11400 +(I1 +(I1 +I1 +I1 +tp11401 +g38 +I00 +S'G\xc6\x97\x9fN\xe2-?' +p11402 +tp11403 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11404 +g179 +tp11405 +Rp11406 +(I1 +(I1 +I1 +I1 +tp11407 +g38 +I00 +S'\xce\xe8";\\y\xca?' +p11408 +tp11409 +bsg252 +g260 +sg48 +(lp11410 +g0 +(g52 +g2 +Ntp11411 +Rp11412 +(dp11413 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp11414 +g179 +tp11415 +Rp11416 +(I1 +(I1 +I1 +I1 +tp11417 +g38 +I00 +S'\xb1\x8b\x94\xd9T\x9d2@' +p11418 +tp11419 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp11420 +g279 +asg113 +I10358 +sg280 +I01 +sbaa(lp11421 +g401 +ag0 +(g190 +g2 +Ntp11422 +Rp11423 +(dp11424 +g194 +I01 +sg195 +(lp11425 +g0 +(g197 +g2 +Ntp11426 +Rp11427 +(dp11428 +g201 +g176 +(g177 +(I0 +tp11429 +g179 +tp11430 +Rp11431 +(I1 +(I1 +tp11432 +g208 +I00 +S"''\x00\x00\x00\x00\x00\x00" +p11433 +tp11434 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11435 +Rp11436 +(dp11437 +g201 +g176 +(g177 +(I0 +tp11438 +g179 +tp11439 +Rp11440 +(I1 +(I2 +tp11441 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11442 +tp11443 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp11444 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11445 +g179 +tp11446 +Rp11447 +(I1 +(I1 +I1 +I1 +tp11448 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11449 +tp11450 +bsg238 +g176 +(g177 +(I0 +tp11451 +g179 +tp11452 +Rp11453 +(I1 +(I1 +I1 +I1 +tp11454 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11455 +tp11456 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11457 +g179 +tp11458 +Rp11459 +(I1 +(I1 +I1 +I1 +tp11460 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11461 +tp11462 +bsg252 +g260 +sg48 +(lp11463 +g0 +(g52 +g2 +Ntp11464 +Rp11465 +(dp11466 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp11467 +g179 +tp11468 +Rp11469 +(I1 +(I1 +I1 +I1 +tp11470 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p11471 +tp11472 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp11473 +g454 +asg113 +I10359 +sg280 +I01 +sbaatp11474 +Rp11475 +sg337 +I00 +sg338 +Nsbaa(lp11476 +g458 +ag0 +(g459 +g2 +Ntp11477 +Rp11478 +(dp11479 +g17 +g11223 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp11480 +(lp11481 +g189 +ag0 +(g190 +g2 +Ntp11482 +Rp11483 +(dp11484 +g194 +I01 +sg195 +(lp11485 +g0 +(g197 +g2 +Ntp11486 +Rp11487 +(dp11488 +g201 +g176 +(g177 +(I0 +tp11489 +g179 +tp11490 +Rp11491 +(I1 +(I1 +tp11492 +g208 +I00 +S"''\x00\x00\x00\x00\x00\x00" +p11493 +tp11494 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp11495 +Rp11496 +(dp11497 +g201 +g176 +(g177 +(I0 +tp11498 +g179 +tp11499 +Rp11500 +(I1 +(I2 +tp11501 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p11502 +tp11503 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp11504 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp11505 +g179 +tp11506 +Rp11507 +(I1 +(I1 +I1 +I1 +tp11508 +g38 +I00 +S'\x1aa\x7fg\xadR\x0e@' +p11509 +tp11510 +bsg238 +g176 +(g177 +(I0 +tp11511 +g179 +tp11512 +Rp11513 +(I1 +(I1 +I1 +I1 +tp11514 +g38 +I00 +S'\xa7Cz;\x85\x95L?' +p11515 +tp11516 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp11517 +g179 +tp11518 +Rp11519 +(I1 +(I1 +I1 +I1 +tp11520 +g38 +I00 +S'\xd2\xcb\xcd\xdc\xec\xdb\xb3C?' +p13259 +tp13260 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13261 +g179 +tp13262 +Rp13263 +(I1 +(I1 +I1 +I1 +tp13264 +g38 +I00 +S'\xbf\x8cD\xb4\xd8\xce\xe5?' +p13265 +tp13266 +bsg252 +g260 +sg48 +(lp13267 +g0 +(g52 +g2 +Ntp13268 +Rp13269 +(dp13270 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp13271 +g179 +tp13272 +Rp13273 +(I1 +(I1 +I1 +I1 +tp13274 +g38 +I00 +S'\xece\x80\xbd\xe0\xaaN@' +p13275 +tp13276 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp13277 +g279 +asg113 +I10418 +sg280 +I01 +sbaa(lp13278 +g12 +ag0 +(g190 +g2 +Ntp13279 +Rp13280 +(dp13281 +g194 +I01 +sg195 +(lp13282 +g0 +(g197 +g2 +Ntp13283 +Rp13284 +(dp13285 +g201 +g176 +(g177 +(I0 +tp13286 +g179 +tp13287 +Rp13288 +(I1 +(I1 +tp13289 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13290 +tp13291 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13292 +Rp13293 +(dp13294 +g201 +g176 +(g177 +(I0 +tp13295 +g179 +tp13296 +Rp13297 +(I1 +(I2 +tp13298 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13299 +tp13300 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp13301 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13302 +g179 +tp13303 +Rp13304 +(I1 +(I1 +I1 +I1 +tp13305 +g38 +I00 +S'\x81k\x0f\x93z2?@' +p13306 +tp13307 +bsg238 +g176 +(g177 +(I0 +tp13308 +g179 +tp13309 +Rp13310 +(I1 +(I1 +I1 +I1 +tp13311 +g38 +I00 +S'\xd2)\xce^r\xb0F?' +p13312 +tp13313 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13314 +g179 +tp13315 +Rp13316 +(I1 +(I1 +I1 +I1 +tp13317 +g38 +I00 +S'X\\\x11\xeb\xcd\xd6\xe2?' +p13318 +tp13319 +bsg252 +g260 +sg48 +(lp13320 +g0 +(g52 +g2 +Ntp13321 +Rp13322 +(dp13323 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp13324 +g179 +tp13325 +Rp13326 +(I1 +(I1 +I1 +I1 +tp13327 +g38 +I00 +S'\xdci\x90\x92\x11~J@' +p13328 +tp13329 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp13330 +g334 +asg113 +I10419 +sg280 +I01 +sbaatp13331 +Rp13332 +sg337 +I00 +sg338 +Nsbaa(lp13333 +g340 +ag0 +(g341 +g2 +Ntp13334 +Rp13335 +(dp13336 +g17 +g13193 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp13337 +(lp13338 +g189 +ag0 +(g190 +g2 +Ntp13339 +Rp13340 +(dp13341 +g194 +I01 +sg195 +(lp13342 +g0 +(g197 +g2 +Ntp13343 +Rp13344 +(dp13345 +g201 +g176 +(g177 +(I0 +tp13346 +g179 +tp13347 +Rp13348 +(I1 +(I1 +tp13349 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13350 +tp13351 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13352 +Rp13353 +(dp13354 +g201 +g176 +(g177 +(I0 +tp13355 +g179 +tp13356 +Rp13357 +(I1 +(I2 +tp13358 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13359 +tp13360 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp13361 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13362 +g179 +tp13363 +Rp13364 +(I1 +(I1 +I1 +I1 +tp13365 +g38 +I00 +S'\n\xf6\x9a\x15\xbe\xe6D@' +p13366 +tp13367 +bsg238 +g176 +(g177 +(I0 +tp13368 +g179 +tp13369 +Rp13370 +(I1 +(I1 +I1 +I1 +tp13371 +g38 +I00 +S'\x87<>\xec\xdb\xb3C?' +p13372 +tp13373 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13374 +g179 +tp13375 +Rp13376 +(I1 +(I1 +I1 +I1 +tp13377 +g38 +I00 +S'\xbf\x8cD\xb4\xd8\xce\xe5?' +p13378 +tp13379 +bsg252 +g260 +sg48 +(lp13380 +g0 +(g52 +g2 +Ntp13381 +Rp13382 +(dp13383 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp13384 +g179 +tp13385 +Rp13386 +(I1 +(I1 +I1 +I1 +tp13387 +g38 +I00 +S'\xece\x80\xbd\xe0\xaaN@' +p13388 +tp13389 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp13390 +g279 +asg113 +I10422 +sg280 +I01 +sbaa(lp13391 +g401 +ag0 +(g190 +g2 +Ntp13392 +Rp13393 +(dp13394 +g194 +I01 +sg195 +(lp13395 +g0 +(g197 +g2 +Ntp13396 +Rp13397 +(dp13398 +g201 +g176 +(g177 +(I0 +tp13399 +g179 +tp13400 +Rp13401 +(I1 +(I1 +tp13402 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13403 +tp13404 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13405 +Rp13406 +(dp13407 +g201 +g176 +(g177 +(I0 +tp13408 +g179 +tp13409 +Rp13410 +(I1 +(I2 +tp13411 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13412 +tp13413 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp13414 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13415 +g179 +tp13416 +Rp13417 +(I1 +(I1 +I1 +I1 +tp13418 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13419 +tp13420 +bsg238 +g176 +(g177 +(I0 +tp13421 +g179 +tp13422 +Rp13423 +(I1 +(I1 +I1 +I1 +tp13424 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13425 +tp13426 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13427 +g179 +tp13428 +Rp13429 +(I1 +(I1 +I1 +I1 +tp13430 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13431 +tp13432 +bsg252 +g260 +sg48 +(lp13433 +g0 +(g52 +g2 +Ntp13434 +Rp13435 +(dp13436 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp13437 +g179 +tp13438 +Rp13439 +(I1 +(I1 +I1 +I1 +tp13440 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13441 +tp13442 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp13443 +g454 +asg113 +I10423 +sg280 +I01 +sbaatp13444 +Rp13445 +sg337 +I00 +sg338 +Nsbaa(lp13446 +g458 +ag0 +(g459 +g2 +Ntp13447 +Rp13448 +(dp13449 +g17 +g13193 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp13450 +(lp13451 +g189 +ag0 +(g190 +g2 +Ntp13452 +Rp13453 +(dp13454 +g194 +I01 +sg195 +(lp13455 +g0 +(g197 +g2 +Ntp13456 +Rp13457 +(dp13458 +g201 +g176 +(g177 +(I0 +tp13459 +g179 +tp13460 +Rp13461 +(I1 +(I1 +tp13462 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13463 +tp13464 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13465 +Rp13466 +(dp13467 +g201 +g176 +(g177 +(I0 +tp13468 +g179 +tp13469 +Rp13470 +(I1 +(I2 +tp13471 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13472 +tp13473 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp13474 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13475 +g179 +tp13476 +Rp13477 +(I1 +(I1 +I1 +I1 +tp13478 +g38 +I00 +S'6$\xd5-\xcf\xe3D@' +p13479 +tp13480 +bsg238 +g176 +(g177 +(I0 +tp13481 +g179 +tp13482 +Rp13483 +(I1 +(I1 +I1 +I1 +tp13484 +g38 +I00 +S'\xd1\x838\xef\xba%V?' +p13485 +tp13486 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13487 +g179 +tp13488 +Rp13489 +(I1 +(I1 +I1 +I1 +tp13490 +g38 +I00 +S'p\xda3\x19\x88\xcc\xe5?' +p13491 +tp13492 +bsg252 +g513 +sg48 +(lp13493 +g0 +(g52 +g2 +Ntp13494 +Rp13495 +(dp13496 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp13497 +g179 +tp13498 +Rp13499 +(I1 +(I1 +I1 +I1 +tp13500 +g38 +I00 +S'-\xebpc\x9f\xa7N@' +p13501 +tp13502 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp13503 +g527 +asg113 +I10426 +sg280 +I01 +sbaa(lp13504 +g529 +ag0 +(g190 +g2 +Ntp13505 +Rp13506 +(dp13507 +g194 +I01 +sg195 +(lp13508 +g0 +(g197 +g2 +Ntp13509 +Rp13510 +(dp13511 +g201 +g176 +(g177 +(I0 +tp13512 +g179 +tp13513 +Rp13514 +(I1 +(I1 +tp13515 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13516 +tp13517 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13518 +Rp13519 +(dp13520 +g201 +g176 +(g177 +(I0 +tp13521 +g179 +tp13522 +Rp13523 +(I1 +(I2 +tp13524 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13525 +tp13526 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13527 +Rp13528 +(dp13529 +g201 +g176 +(g177 +(I0 +tp13530 +g179 +tp13531 +Rp13532 +(I1 +(I2 +tp13533 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13534 +tp13535 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp13536 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13537 +g179 +tp13538 +Rp13539 +(I1 +(I1 +I1 +I1 +tp13540 +g38 +I00 +S'\x96j\x1bV#\xc2>@' +p13541 +tp13542 +bsg238 +g176 +(g177 +(I0 +tp13543 +g179 +tp13544 +Rp13545 +(I1 +(I1 +I1 +I1 +tp13546 +g38 +I00 +S'q\x0c\xbc\xa7\xb6,P?' +p13547 +tp13548 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13549 +g179 +tp13550 +Rp13551 +(I1 +(I1 +I1 +I1 +tp13552 +g38 +I00 +S'p\x17%\x99s\xb4\xe2?' +p13553 +tp13554 +bsg252 +g586 +sg48 +(lp13555 +g0 +(g52 +g2 +Ntp13556 +Rp13557 +(dp13558 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp13559 +g179 +tp13560 +Rp13561 +(I1 +(I1 +I1 +I1 +tp13562 +g38 +I00 +S'\xf6(\\\x8f\xc2MJ@' +p13563 +tp13564 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp13565 +g600 +asg113 +I10427 +sg280 +I01 +sbaatp13566 +Rp13567 +sg337 +I00 +sg338 +Nsbaa(lp13568 +g604 +ag0 +(g605 +g2 +Ntp13569 +Rp13570 +(dp13571 +g17 +g13193 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp13572 +(lp13573 +g611 +ag0 +(g190 +g2 +Ntp13574 +Rp13575 +(dp13576 +g194 +I01 +sg195 +(lp13577 +g0 +(g197 +g2 +Ntp13578 +Rp13579 +(dp13580 +g201 +g176 +(g177 +(I0 +tp13581 +g179 +tp13582 +Rp13583 +(I1 +(I1 +tp13584 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13585 +tp13586 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13587 +Rp13588 +(dp13589 +g201 +g176 +(g177 +(I0 +tp13590 +g179 +tp13591 +Rp13592 +(I1 +(I2 +tp13593 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13594 +tp13595 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp13596 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13597 +g179 +tp13598 +Rp13599 +(I1 +(I1 +I1 +I1 +tp13600 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13601 +tp13602 +bsg238 +g176 +(g177 +(I0 +tp13603 +g179 +tp13604 +Rp13605 +(I1 +(I1 +I1 +I1 +tp13606 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13607 +tp13608 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13609 +g179 +tp13610 +Rp13611 +(I1 +(I1 +I1 +I1 +tp13612 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13613 +tp13614 +bsg252 +g513 +sg48 +(lp13615 +g0 +(g52 +g2 +Ntp13616 +Rp13617 +(dp13618 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp13619 +g179 +tp13620 +Rp13621 +(I1 +(I1 +I1 +I1 +tp13622 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13623 +tp13624 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp13625 +g664 +asg113 +I10430 +sg280 +I01 +sbaa(lp13626 +g666 +ag0 +(g190 +g2 +Ntp13627 +Rp13628 +(dp13629 +g194 +I01 +sg195 +(lp13630 +g0 +(g197 +g2 +Ntp13631 +Rp13632 +(dp13633 +g201 +g176 +(g177 +(I0 +tp13634 +g179 +tp13635 +Rp13636 +(I1 +(I1 +tp13637 +g208 +I00 +S"+'\x00\x00\x00\x00\x00\x00" +p13638 +tp13639 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13640 +Rp13641 +(dp13642 +g201 +g176 +(g177 +(I0 +tp13643 +g179 +tp13644 +Rp13645 +(I1 +(I2 +tp13646 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13647 +tp13648 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp13649 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13650 +g179 +tp13651 +Rp13652 +(I1 +(I1 +I1 +I1 +tp13653 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13654 +tp13655 +bsg238 +g176 +(g177 +(I0 +tp13656 +g179 +tp13657 +Rp13658 +(I1 +(I1 +I1 +I1 +tp13659 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13660 +tp13661 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13662 +g179 +tp13663 +Rp13664 +(I1 +(I1 +I1 +I1 +tp13665 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13666 +tp13667 +bsg252 +g713 +sg48 +(lp13668 +g0 +(g52 +g2 +Ntp13669 +Rp13670 +(dp13671 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp13672 +g179 +tp13673 +Rp13674 +(I1 +(I1 +I1 +I1 +tp13675 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p13676 +tp13677 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp13678 +g727 +asg113 +I10431 +sg280 +I01 +sbaatp13679 +Rp13680 +sg337 +I00 +sg338 +Nsbaatp13681 +Rp13682 +aa(lp13683 +I10028 +ag7 +((lp13684 +(lp13685 +g12 +ag0 +(g13 +g2 +Ntp13686 +Rp13687 +(dp13688 +g17 +g0 +(g18 +g2 +Ntp13689 +Rp13690 +(dp13691 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p13692 +sg116 +g0 +(g117 +g2 +Ntp13693 +Rp13694 +(dp13695 +g121 +(lp13696 +g0 +(g123 +g2 +Ntp13697 +Rp13698 +(dp13699 +g127 +g0 +(g128 +g2 +Ntp13700 +Rp13701 +(dp13702 +g23 +g132 +sg133 +(dp13703 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xd6?' +p13704 +tp13705 +Rp13706 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p13707 +sg113 +I54 +sg146 +(lp13708 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp13709 +Rp13710 +(dp13711 +g127 +g0 +(g128 +g2 +Ntp13712 +Rp13713 +(dp13714 +g23 +g132 +sg133 +(dp13715 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xd3?' +p13716 +tp13717 +Rp13718 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p13719 +sg113 +I55 +sg146 +(lp13720 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10028 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp13721 +(lp13722 +g189 +ag0 +(g190 +g2 +Ntp13723 +Rp13724 +(dp13725 +g194 +I01 +sg195 +(lp13726 +g0 +(g197 +g2 +Ntp13727 +Rp13728 +(dp13729 +g201 +g176 +(g177 +(I0 +tp13730 +g179 +tp13731 +Rp13732 +(I1 +(I1 +tp13733 +g208 +I00 +S",'\x00\x00\x00\x00\x00\x00" +p13734 +tp13735 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp13736 +Rp13737 +(dp13738 +g201 +g176 +(g177 +(I0 +tp13739 +g179 +tp13740 +Rp13741 +(I1 +(I2 +tp13742 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p13743 +tp13744 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp13745 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp13746 +g179 +tp13747 +Rp13748 +(I1 +(I1 +I1 +I1 +tp13749 +g38 +I00 +S'!b\xb2\xbc\xc8`8@' +p13750 +tp13751 +bsg238 +g176 +(g177 +(I0 +tp13752 +g179 +tp13753 +Rp13754 +(I1 +(I1 +I1 +I1 +tp13755 +g38 +I00 +S'\xb5\xdd3\xc3\xe20C?' +p13756 +tp13757 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp13758 +g179 +tp13759 +Rp13760 +(I1 +(I1 +I1 +I1 +tp13761 +g38 +I00 +S'\x91\x90\x8b\x91G\xa7\xe0?' +p13762 +tp13763 +bsg252 +g260 +sg48 +(lp13764 +g0 +(g52 +g2 +Ntp13765 +Rp13766 +(dp13767 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp13768 +g179 +tp13769 +Rp13770 +(I1 +(I1 +I1 +I1 +tp13771 +g38 +I00 +S'LC\xac\xa4\xad\xb60?' +p14794 +tp14795 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp14796 +g179 +tp14797 +Rp14798 +(I1 +(I1 +I1 +I1 +tp14799 +g38 +I00 +S'\xc3\xd7\x9e\xe3}\x03\xcb?' +p14800 +tp14801 +bsg252 +g260 +sg48 +(lp14802 +g0 +(g52 +g2 +Ntp14803 +Rp14804 +(dp14805 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp14806 +g179 +tp14807 +Rp14808 +(I1 +(I1 +I1 +I1 +tp14809 +g38 +I00 +S'\xb5\xaf\x0b\x84t\xfe2@' +p14810 +tp14811 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp14812 +g334 +asg113 +I10467 +sg280 +I01 +sbaatp14813 +Rp14814 +sg337 +I00 +sg338 +Nsbaa(lp14815 +g340 +ag0 +(g341 +g2 +Ntp14816 +Rp14817 +(dp14818 +g17 +g14684 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp14819 +(lp14820 +g189 +ag0 +(g190 +g2 +Ntp14821 +Rp14822 +(dp14823 +g194 +I01 +sg195 +(lp14824 +g0 +(g197 +g2 +Ntp14825 +Rp14826 +(dp14827 +g201 +g176 +(g177 +(I0 +tp14828 +g179 +tp14829 +Rp14830 +(I1 +(I1 +tp14831 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p14832 +tp14833 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp14834 +Rp14835 +(dp14836 +g201 +g176 +(g177 +(I0 +tp14837 +g179 +tp14838 +Rp14839 +(I1 +(I2 +tp14840 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p14841 +tp14842 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp14843 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp14844 +g179 +tp14845 +Rp14846 +(I1 +(I1 +I1 +I1 +tp14847 +g38 +I00 +S'\x97\x99\xda\xd7S\x898@' +p14848 +tp14849 +bsg238 +g176 +(g177 +(I0 +tp14850 +g179 +tp14851 +Rp14852 +(I1 +(I1 +I1 +I1 +tp14853 +g38 +I00 +S'0\x10\xe1\xa6?\x8cB?' +p14854 +tp14855 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp14856 +g179 +tp14857 +Rp14858 +(I1 +(I1 +I1 +I1 +tp14859 +g38 +I00 +S'Y\x97\xf6j\x1f\xb5\xe0?' +p14860 +tp14861 +bsg252 +g260 +sg48 +(lp14862 +g0 +(g52 +g2 +Ntp14863 +Rp14864 +(dp14865 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp14866 +g179 +tp14867 +Rp14868 +(I1 +(I1 +I1 +I1 +tp14869 +g38 +I00 +S'\xd5\xc4j.\xb4~G@' +p14870 +tp14871 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp14872 +g279 +asg113 +I10470 +sg280 +I01 +sbaa(lp14873 +g401 +ag0 +(g190 +g2 +Ntp14874 +Rp14875 +(dp14876 +g194 +I01 +sg195 +(lp14877 +g0 +(g197 +g2 +Ntp14878 +Rp14879 +(dp14880 +g201 +g176 +(g177 +(I0 +tp14881 +g179 +tp14882 +Rp14883 +(I1 +(I1 +tp14884 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p14885 +tp14886 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp14887 +Rp14888 +(dp14889 +g201 +g176 +(g177 +(I0 +tp14890 +g179 +tp14891 +Rp14892 +(I1 +(I2 +tp14893 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p14894 +tp14895 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp14896 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp14897 +g179 +tp14898 +Rp14899 +(I1 +(I1 +I1 +I1 +tp14900 +g38 +I00 +S']E\xa7\xcdB|\xa6?' +p14901 +tp14902 +bsg238 +g176 +(g177 +(I0 +tp14903 +g179 +tp14904 +Rp14905 +(I1 +(I1 +I1 +I1 +tp14906 +g38 +I00 +S'9\xce\x841\xa09\r?' +p14907 +tp14908 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp14909 +g179 +tp14910 +Rp14911 +(I1 +(I1 +I1 +I1 +tp14912 +g38 +I00 +S'ZD7\xe3\x18\x9d\x96?' +p14913 +tp14914 +bsg252 +g260 +sg48 +(lp14915 +g0 +(g52 +g2 +Ntp14916 +Rp14917 +(dp14918 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp14919 +g179 +tp14920 +Rp14921 +(I1 +(I1 +I1 +I1 +tp14922 +g38 +I00 +S'\x1e\xb8\x85\xff\xea\xcc\xff?' +p14923 +tp14924 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp14925 +g454 +asg113 +I10471 +sg280 +I01 +sbaatp14926 +Rp14927 +sg337 +I00 +sg338 +Nsbaa(lp14928 +g458 +ag0 +(g459 +g2 +Ntp14929 +Rp14930 +(dp14931 +g17 +g14684 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp14932 +(lp14933 +g189 +ag0 +(g190 +g2 +Ntp14934 +Rp14935 +(dp14936 +g194 +I01 +sg195 +(lp14937 +g0 +(g197 +g2 +Ntp14938 +Rp14939 +(dp14940 +g201 +g176 +(g177 +(I0 +tp14941 +g179 +tp14942 +Rp14943 +(I1 +(I1 +tp14944 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p14945 +tp14946 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp14947 +Rp14948 +(dp14949 +g201 +g176 +(g177 +(I0 +tp14950 +g179 +tp14951 +Rp14952 +(I1 +(I2 +tp14953 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p14954 +tp14955 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp14956 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp14957 +g179 +tp14958 +Rp14959 +(I1 +(I1 +I1 +I1 +tp14960 +g38 +I00 +S'9\x95\n\x1a\xc9\x8b8@' +p14961 +tp14962 +bsg238 +g176 +(g177 +(I0 +tp14963 +g179 +tp14964 +Rp14965 +(I1 +(I1 +I1 +I1 +tp14966 +g38 +I00 +S'$\xa4E4\xe0\xabU?' +p14967 +tp14968 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp14969 +g179 +tp14970 +Rp14971 +(I1 +(I1 +I1 +I1 +tp14972 +g38 +I00 +S'Ud\x0f9\xf6\xb4\xe0?' +p14973 +tp14974 +bsg252 +g513 +sg48 +(lp14975 +g0 +(g52 +g2 +Ntp14976 +Rp14977 +(dp14978 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp14979 +g179 +tp14980 +Rp14981 +(I1 +(I1 +I1 +I1 +tp14982 +g38 +I00 +S'\x18\xa5=@z~G@' +p14983 +tp14984 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp14985 +g527 +asg113 +I10474 +sg280 +I01 +sbaa(lp14986 +g529 +ag0 +(g190 +g2 +Ntp14987 +Rp14988 +(dp14989 +g194 +I01 +sg195 +(lp14990 +g0 +(g197 +g2 +Ntp14991 +Rp14992 +(dp14993 +g201 +g176 +(g177 +(I0 +tp14994 +g179 +tp14995 +Rp14996 +(I1 +(I1 +tp14997 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p14998 +tp14999 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15000 +Rp15001 +(dp15002 +g201 +g176 +(g177 +(I0 +tp15003 +g179 +tp15004 +Rp15005 +(I1 +(I2 +tp15006 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15007 +tp15008 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15009 +Rp15010 +(dp15011 +g201 +g176 +(g177 +(I0 +tp15012 +g179 +tp15013 +Rp15014 +(I1 +(I2 +tp15015 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15016 +tp15017 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp15018 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15019 +g179 +tp15020 +Rp15021 +(I1 +(I1 +I1 +I1 +tp15022 +g38 +I00 +S'\xfe\x8b\xd1!\r\x9a\x0b@' +p15023 +tp15024 +bsg238 +g176 +(g177 +(I0 +tp15025 +g179 +tp15026 +Rp15027 +(I1 +(I1 +I1 +I1 +tp15028 +g38 +I00 +S'\x98\x07\xf2Y\xf2\xca@?' +p15029 +tp15030 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15031 +g179 +tp15032 +Rp15033 +(I1 +(I1 +I1 +I1 +tp15034 +g38 +I00 +S'\xa8C\xe3\xd8\xdc\r\xc9?' +p15035 +tp15036 +bsg252 +g586 +sg48 +(lp15037 +g0 +(g52 +g2 +Ntp15038 +Rp15039 +(dp15040 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp15041 +g179 +tp15042 +Rp15043 +(I1 +(I1 +I1 +I1 +tp15044 +g38 +I00 +S'\x92\xcb\x7fH\xbf\x9d1@' +p15045 +tp15046 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp15047 +g600 +asg113 +I10475 +sg280 +I01 +sbaatp15048 +Rp15049 +sg337 +I00 +sg338 +Nsbaa(lp15050 +g604 +ag0 +(g605 +g2 +Ntp15051 +Rp15052 +(dp15053 +g17 +g14684 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15054 +(lp15055 +g611 +ag0 +(g190 +g2 +Ntp15056 +Rp15057 +(dp15058 +g194 +I01 +sg195 +(lp15059 +g0 +(g197 +g2 +Ntp15060 +Rp15061 +(dp15062 +g201 +g176 +(g177 +(I0 +tp15063 +g179 +tp15064 +Rp15065 +(I1 +(I1 +tp15066 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p15067 +tp15068 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15069 +Rp15070 +(dp15071 +g201 +g176 +(g177 +(I0 +tp15072 +g179 +tp15073 +Rp15074 +(I1 +(I2 +tp15075 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15076 +tp15077 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp15078 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15079 +g179 +tp15080 +Rp15081 +(I1 +(I1 +I1 +I1 +tp15082 +g38 +I00 +S'(^\xc7Z\x8bK\xa6?' +p15083 +tp15084 +bsg238 +g176 +(g177 +(I0 +tp15085 +g179 +tp15086 +Rp15087 +(I1 +(I1 +I1 +I1 +tp15088 +g38 +I00 +S'\x7f\xb5\x91\x17\xfc#,?' +p15089 +tp15090 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15091 +g179 +tp15092 +Rp15093 +(I1 +(I1 +I1 +I1 +tp15094 +g38 +I00 +S'\xc7C\xc9C\xafm\x96?' +p15095 +tp15096 +bsg252 +g513 +sg48 +(lp15097 +g0 +(g52 +g2 +Ntp15098 +Rp15099 +(dp15100 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp15101 +g179 +tp15102 +Rp15103 +(I1 +(I1 +I1 +I1 +tp15104 +g38 +I00 +S'P\x07Sw>\x8a\xff?' +p15105 +tp15106 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp15107 +g664 +asg113 +I10478 +sg280 +I01 +sbaa(lp15108 +g666 +ag0 +(g190 +g2 +Ntp15109 +Rp15110 +(dp15111 +g194 +I01 +sg195 +(lp15112 +g0 +(g197 +g2 +Ntp15113 +Rp15114 +(dp15115 +g201 +g176 +(g177 +(I0 +tp15116 +g179 +tp15117 +Rp15118 +(I1 +(I1 +tp15119 +g208 +I00 +S".'\x00\x00\x00\x00\x00\x00" +p15120 +tp15121 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15122 +Rp15123 +(dp15124 +g201 +g176 +(g177 +(I0 +tp15125 +g179 +tp15126 +Rp15127 +(I1 +(I2 +tp15128 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15129 +tp15130 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp15131 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15132 +g179 +tp15133 +Rp15134 +(I1 +(I1 +I1 +I1 +tp15135 +g38 +I00 +S',^\xc7Z\x8bK\xa6?' +p15136 +tp15137 +bsg238 +g176 +(g177 +(I0 +tp15138 +g179 +tp15139 +Rp15140 +(I1 +(I1 +I1 +I1 +tp15141 +g38 +I00 +S'\xb4\xb5\x91\x17\xfc#,?' +p15142 +tp15143 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15144 +g179 +tp15145 +Rp15146 +(I1 +(I1 +I1 +I1 +tp15147 +g38 +I00 +S'\xc9C\xc9C\xafm\x96?' +p15148 +tp15149 +bsg252 +g713 +sg48 +(lp15150 +g0 +(g52 +g2 +Ntp15151 +Rp15152 +(dp15153 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp15154 +g179 +tp15155 +Rp15156 +(I1 +(I1 +I1 +I1 +tp15157 +g38 +I00 +S'S\x07Sw>\x8a\xff?' +p15158 +tp15159 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp15160 +g727 +asg113 +I10479 +sg280 +I01 +sbaatp15161 +Rp15162 +sg337 +I00 +sg338 +Nsbaatp15163 +Rp15164 +aa(lp15165 +I10031 +ag7 +((lp15166 +(lp15167 +g12 +ag0 +(g13 +g2 +Ntp15168 +Rp15169 +(dp15170 +g17 +g0 +(g18 +g2 +Ntp15171 +Rp15172 +(dp15173 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p15174 +sg116 +g0 +(g117 +g2 +Ntp15175 +Rp15176 +(dp15177 +g121 +(lp15178 +g0 +(g123 +g2 +Ntp15179 +Rp15180 +(dp15181 +g127 +g0 +(g128 +g2 +Ntp15182 +Rp15183 +(dp15184 +g23 +g132 +sg133 +(dp15185 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\x01@' +p15186 +tp15187 +Rp15188 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p15189 +sg113 +I59 +sg146 +(lp15190 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp15191 +Rp15192 +(dp15193 +g127 +g0 +(g128 +g2 +Ntp15194 +Rp15195 +(dp15196 +g23 +g132 +sg133 +(dp15197 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'q=\n\xd7\xa3p\x01@' +p15198 +tp15199 +Rp15200 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p15201 +sg113 +I60 +sg146 +(lp15202 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10031 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15203 +(lp15204 +g189 +ag0 +(g190 +g2 +Ntp15205 +Rp15206 +(dp15207 +g194 +I01 +sg195 +(lp15208 +g0 +(g197 +g2 +Ntp15209 +Rp15210 +(dp15211 +g201 +g176 +(g177 +(I0 +tp15212 +g179 +tp15213 +Rp15214 +(I1 +(I1 +tp15215 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15216 +tp15217 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15218 +Rp15219 +(dp15220 +g201 +g176 +(g177 +(I0 +tp15221 +g179 +tp15222 +Rp15223 +(I1 +(I2 +tp15224 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15225 +tp15226 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15227 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15228 +g179 +tp15229 +Rp15230 +(I1 +(I1 +I1 +I1 +tp15231 +g38 +I00 +S'ewS\xebs1\x0e@' +p15232 +tp15233 +bsg238 +g176 +(g177 +(I0 +tp15234 +g179 +tp15235 +Rp15236 +(I1 +(I1 +I1 +I1 +tp15237 +g38 +I00 +S'\x19\x03\xb2\x99\xde\xdf*?' +p15238 +tp15239 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15240 +g179 +tp15241 +Rp15242 +(I1 +(I1 +I1 +I1 +tp15243 +g38 +I00 +S'\x00-\xc3\xe7\xf05\xca?' +p15244 +tp15245 +bsg252 +g260 +sg48 +(lp15246 +g0 +(g52 +g2 +Ntp15247 +Rp15248 +(dp15249 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15250 +g179 +tp15251 +Rp15252 +(I1 +(I1 +I1 +I1 +tp15253 +g38 +I00 +S'\xa4;\xf5b\xedm2@' +p15254 +tp15255 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15256 +g279 +asg113 +I10482 +sg280 +I01 +sbaa(lp15257 +g12 +ag0 +(g190 +g2 +Ntp15258 +Rp15259 +(dp15260 +g194 +I01 +sg195 +(lp15261 +g0 +(g197 +g2 +Ntp15262 +Rp15263 +(dp15264 +g201 +g176 +(g177 +(I0 +tp15265 +g179 +tp15266 +Rp15267 +(I1 +(I1 +tp15268 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15269 +tp15270 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15271 +Rp15272 +(dp15273 +g201 +g176 +(g177 +(I0 +tp15274 +g179 +tp15275 +Rp15276 +(I1 +(I2 +tp15277 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15278 +tp15279 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15280 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15281 +g179 +tp15282 +Rp15283 +(I1 +(I1 +I1 +I1 +tp15284 +g38 +I00 +S'\x1e\x8f\x9d\x04\x8e\x00\xd7?' +p15285 +tp15286 +bsg238 +g176 +(g177 +(I0 +tp15287 +g179 +tp15288 +Rp15289 +(I1 +(I1 +I1 +I1 +tp15290 +g38 +I00 +S'\xc9Y\x85\x8a\xf1\xb4\x11?' +p15291 +tp15292 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15293 +g179 +tp15294 +Rp15295 +(I1 +(I1 +I1 +I1 +tp15296 +g38 +I00 +S'\x90\x10\x8c\xdd>-\xb0?' +p15297 +tp15298 +bsg252 +g260 +sg48 +(lp15299 +g0 +(g52 +g2 +Ntp15300 +Rp15301 +(dp15302 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15303 +g179 +tp15304 +Rp15305 +(I1 +(I1 +I1 +I1 +tp15306 +g38 +I00 +S'K\xf7\x8cg\xa0\xbf\x16@' +p15307 +tp15308 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15309 +g334 +asg113 +I10483 +sg280 +I01 +sbaatp15310 +Rp15311 +sg337 +I00 +sg338 +Nsbaa(lp15312 +g340 +ag0 +(g341 +g2 +Ntp15313 +Rp15314 +(dp15315 +g17 +g15172 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15316 +(lp15317 +g189 +ag0 +(g190 +g2 +Ntp15318 +Rp15319 +(dp15320 +g194 +I01 +sg195 +(lp15321 +g0 +(g197 +g2 +Ntp15322 +Rp15323 +(dp15324 +g201 +g176 +(g177 +(I0 +tp15325 +g179 +tp15326 +Rp15327 +(I1 +(I1 +tp15328 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15329 +tp15330 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15331 +Rp15332 +(dp15333 +g201 +g176 +(g177 +(I0 +tp15334 +g179 +tp15335 +Rp15336 +(I1 +(I2 +tp15337 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15338 +tp15339 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15340 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15341 +g179 +tp15342 +Rp15343 +(I1 +(I1 +I1 +I1 +tp15344 +g38 +I00 +S'ewS\xebs1\x0e@' +p15345 +tp15346 +bsg238 +g176 +(g177 +(I0 +tp15347 +g179 +tp15348 +Rp15349 +(I1 +(I1 +I1 +I1 +tp15350 +g38 +I00 +S'\x19\x03\xb2\x99\xde\xdf*?' +p15351 +tp15352 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15353 +g179 +tp15354 +Rp15355 +(I1 +(I1 +I1 +I1 +tp15356 +g38 +I00 +S'\x00-\xc3\xe7\xf05\xca?' +p15357 +tp15358 +bsg252 +g260 +sg48 +(lp15359 +g0 +(g52 +g2 +Ntp15360 +Rp15361 +(dp15362 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15363 +g179 +tp15364 +Rp15365 +(I1 +(I1 +I1 +I1 +tp15366 +g38 +I00 +S'\xa4;\xf5b\xedm2@' +p15367 +tp15368 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15369 +g279 +asg113 +I10486 +sg280 +I01 +sbaa(lp15370 +g401 +ag0 +(g190 +g2 +Ntp15371 +Rp15372 +(dp15373 +g194 +I01 +sg195 +(lp15374 +g0 +(g197 +g2 +Ntp15375 +Rp15376 +(dp15377 +g201 +g176 +(g177 +(I0 +tp15378 +g179 +tp15379 +Rp15380 +(I1 +(I1 +tp15381 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15382 +tp15383 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15384 +Rp15385 +(dp15386 +g201 +g176 +(g177 +(I0 +tp15387 +g179 +tp15388 +Rp15389 +(I1 +(I2 +tp15390 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15391 +tp15392 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15393 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15394 +g179 +tp15395 +Rp15396 +(I1 +(I1 +I1 +I1 +tp15397 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15398 +tp15399 +bsg238 +g176 +(g177 +(I0 +tp15400 +g179 +tp15401 +Rp15402 +(I1 +(I1 +I1 +I1 +tp15403 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15404 +tp15405 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15406 +g179 +tp15407 +Rp15408 +(I1 +(I1 +I1 +I1 +tp15409 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15410 +tp15411 +bsg252 +g260 +sg48 +(lp15412 +g0 +(g52 +g2 +Ntp15413 +Rp15414 +(dp15415 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15416 +g179 +tp15417 +Rp15418 +(I1 +(I1 +I1 +I1 +tp15419 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15420 +tp15421 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15422 +g454 +asg113 +I10487 +sg280 +I01 +sbaatp15423 +Rp15424 +sg337 +I00 +sg338 +Nsbaa(lp15425 +g458 +ag0 +(g459 +g2 +Ntp15426 +Rp15427 +(dp15428 +g17 +g15172 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15429 +(lp15430 +g189 +ag0 +(g190 +g2 +Ntp15431 +Rp15432 +(dp15433 +g194 +I01 +sg195 +(lp15434 +g0 +(g197 +g2 +Ntp15435 +Rp15436 +(dp15437 +g201 +g176 +(g177 +(I0 +tp15438 +g179 +tp15439 +Rp15440 +(I1 +(I1 +tp15441 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15442 +tp15443 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15444 +Rp15445 +(dp15446 +g201 +g176 +(g177 +(I0 +tp15447 +g179 +tp15448 +Rp15449 +(I1 +(I2 +tp15450 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15451 +tp15452 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp15453 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15454 +g179 +tp15455 +Rp15456 +(I1 +(I1 +I1 +I1 +tp15457 +g38 +I00 +S'P\xe7\xf2\xc4\xdfE\x0e@' +p15458 +tp15459 +bsg238 +g176 +(g177 +(I0 +tp15460 +g179 +tp15461 +Rp15462 +(I1 +(I1 +I1 +I1 +tp15463 +g38 +I00 +S'$c\x03/\x80\x18J?' +p15464 +tp15465 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15466 +g179 +tp15467 +Rp15468 +(I1 +(I1 +I1 +I1 +tp15469 +g38 +I00 +S'\\\xe5\xb2Q\x96:\xca?' +p15470 +tp15471 +bsg252 +g513 +sg48 +(lp15472 +g0 +(g52 +g2 +Ntp15473 +Rp15474 +(dp15475 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp15476 +g179 +tp15477 +Rp15478 +(I1 +(I1 +I1 +I1 +tp15479 +g38 +I00 +S'E\xc9q\xb11q2@' +p15480 +tp15481 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp15482 +g527 +asg113 +I10490 +sg280 +I01 +sbaa(lp15483 +g529 +ag0 +(g190 +g2 +Ntp15484 +Rp15485 +(dp15486 +g194 +I01 +sg195 +(lp15487 +g0 +(g197 +g2 +Ntp15488 +Rp15489 +(dp15490 +g201 +g176 +(g177 +(I0 +tp15491 +g179 +tp15492 +Rp15493 +(I1 +(I1 +tp15494 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15495 +tp15496 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15497 +Rp15498 +(dp15499 +g201 +g176 +(g177 +(I0 +tp15500 +g179 +tp15501 +Rp15502 +(I1 +(I2 +tp15503 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15504 +tp15505 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15506 +Rp15507 +(dp15508 +g201 +g176 +(g177 +(I0 +tp15509 +g179 +tp15510 +Rp15511 +(I1 +(I2 +tp15512 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15513 +tp15514 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp15515 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15516 +g179 +tp15517 +Rp15518 +(I1 +(I1 +I1 +I1 +tp15519 +g38 +I00 +S'\xca\xce\xf4u\x8d\xd4\xd6?' +p15520 +tp15521 +bsg238 +g176 +(g177 +(I0 +tp15522 +g179 +tp15523 +Rp15524 +(I1 +(I1 +I1 +I1 +tp15525 +g38 +I00 +S'\x8e{_I\xb1\x01.?' +p15526 +tp15527 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15528 +g179 +tp15529 +Rp15530 +(I1 +(I1 +I1 +I1 +tp15531 +g38 +I00 +S'z\xaaCn\x86\x1b\xb0?' +p15532 +tp15533 +bsg252 +g586 +sg48 +(lp15534 +g0 +(g52 +g2 +Ntp15535 +Rp15536 +(dp15537 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp15538 +g179 +tp15539 +Rp15540 +(I1 +(I1 +I1 +I1 +tp15541 +g38 +I00 +S"\xbc'\x0f\x0b\xb5\xa6\x16@" +p15542 +tp15543 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp15544 +g600 +asg113 +I10491 +sg280 +I01 +sbaatp15545 +Rp15546 +sg337 +I00 +sg338 +Nsbaa(lp15547 +g604 +ag0 +(g605 +g2 +Ntp15548 +Rp15549 +(dp15550 +g17 +g15172 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15551 +(lp15552 +g611 +ag0 +(g190 +g2 +Ntp15553 +Rp15554 +(dp15555 +g194 +I01 +sg195 +(lp15556 +g0 +(g197 +g2 +Ntp15557 +Rp15558 +(dp15559 +g201 +g176 +(g177 +(I0 +tp15560 +g179 +tp15561 +Rp15562 +(I1 +(I1 +tp15563 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15564 +tp15565 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15566 +Rp15567 +(dp15568 +g201 +g176 +(g177 +(I0 +tp15569 +g179 +tp15570 +Rp15571 +(I1 +(I2 +tp15572 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15573 +tp15574 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp15575 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15576 +g179 +tp15577 +Rp15578 +(I1 +(I1 +I1 +I1 +tp15579 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15580 +tp15581 +bsg238 +g176 +(g177 +(I0 +tp15582 +g179 +tp15583 +Rp15584 +(I1 +(I1 +I1 +I1 +tp15585 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15586 +tp15587 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15588 +g179 +tp15589 +Rp15590 +(I1 +(I1 +I1 +I1 +tp15591 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15592 +tp15593 +bsg252 +g513 +sg48 +(lp15594 +g0 +(g52 +g2 +Ntp15595 +Rp15596 +(dp15597 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp15598 +g179 +tp15599 +Rp15600 +(I1 +(I1 +I1 +I1 +tp15601 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15602 +tp15603 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp15604 +g664 +asg113 +I10494 +sg280 +I01 +sbaa(lp15605 +g666 +ag0 +(g190 +g2 +Ntp15606 +Rp15607 +(dp15608 +g194 +I01 +sg195 +(lp15609 +g0 +(g197 +g2 +Ntp15610 +Rp15611 +(dp15612 +g201 +g176 +(g177 +(I0 +tp15613 +g179 +tp15614 +Rp15615 +(I1 +(I1 +tp15616 +g208 +I00 +S"/'\x00\x00\x00\x00\x00\x00" +p15617 +tp15618 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15619 +Rp15620 +(dp15621 +g201 +g176 +(g177 +(I0 +tp15622 +g179 +tp15623 +Rp15624 +(I1 +(I2 +tp15625 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15626 +tp15627 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp15628 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15629 +g179 +tp15630 +Rp15631 +(I1 +(I1 +I1 +I1 +tp15632 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15633 +tp15634 +bsg238 +g176 +(g177 +(I0 +tp15635 +g179 +tp15636 +Rp15637 +(I1 +(I1 +I1 +I1 +tp15638 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15639 +tp15640 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15641 +g179 +tp15642 +Rp15643 +(I1 +(I1 +I1 +I1 +tp15644 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15645 +tp15646 +bsg252 +g713 +sg48 +(lp15647 +g0 +(g52 +g2 +Ntp15648 +Rp15649 +(dp15650 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp15651 +g179 +tp15652 +Rp15653 +(I1 +(I1 +I1 +I1 +tp15654 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15655 +tp15656 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp15657 +g727 +asg113 +I10495 +sg280 +I01 +sbaatp15658 +Rp15659 +sg337 +I00 +sg338 +Nsbaatp15660 +Rp15661 +aa(lp15662 +I10032 +ag7 +((lp15663 +(lp15664 +g12 +ag0 +(g13 +g2 +Ntp15665 +Rp15666 +(dp15667 +g17 +g0 +(g18 +g2 +Ntp15668 +Rp15669 +(dp15670 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p15671 +sg116 +g0 +(g117 +g2 +Ntp15672 +Rp15673 +(dp15674 +g121 +(lp15675 +g0 +(g123 +g2 +Ntp15676 +Rp15677 +(dp15678 +g127 +g4342 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp15679 +Rp15680 +(dp15681 +g127 +g8788 +sg148 +g149 +sbasbsg163 +Nsg113 +I10032 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15682 +(lp15683 +g189 +ag0 +(g190 +g2 +Ntp15684 +Rp15685 +(dp15686 +g194 +I01 +sg195 +(lp15687 +g0 +(g197 +g2 +Ntp15688 +Rp15689 +(dp15690 +g201 +g176 +(g177 +(I0 +tp15691 +g179 +tp15692 +Rp15693 +(I1 +(I1 +tp15694 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15695 +tp15696 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15697 +Rp15698 +(dp15699 +g201 +g176 +(g177 +(I0 +tp15700 +g179 +tp15701 +Rp15702 +(I1 +(I2 +tp15703 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15704 +tp15705 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15706 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15707 +g179 +tp15708 +Rp15709 +(I1 +(I1 +I1 +I1 +tp15710 +g38 +I00 +S'\x83k\xd7Fw`I@' +p15711 +tp15712 +bsg238 +g176 +(g177 +(I0 +tp15713 +g179 +tp15714 +Rp15715 +(I1 +(I1 +I1 +I1 +tp15716 +g38 +I00 +S'\xa2Z\xdb\x10\x85%L?' +p15717 +tp15718 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15719 +g179 +tp15720 +Rp15721 +(I1 +(I1 +I1 +I1 +tp15722 +g38 +I00 +S'\x81\xa4:dq\x07\xe8?' +p15723 +tp15724 +bsg252 +g260 +sg48 +(lp15725 +g0 +(g52 +g2 +Ntp15726 +Rp15727 +(dp15728 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15729 +g179 +tp15730 +Rp15731 +(I1 +(I1 +I1 +I1 +tp15732 +g38 +I00 +S'\xab;y\xba;\xe5P@' +p15733 +tp15734 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15735 +g279 +asg113 +I10498 +sg280 +I01 +sbaa(lp15736 +g12 +ag0 +(g190 +g2 +Ntp15737 +Rp15738 +(dp15739 +g194 +I01 +sg195 +(lp15740 +g0 +(g197 +g2 +Ntp15741 +Rp15742 +(dp15743 +g201 +g176 +(g177 +(I0 +tp15744 +g179 +tp15745 +Rp15746 +(I1 +(I1 +tp15747 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15748 +tp15749 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15750 +Rp15751 +(dp15752 +g201 +g176 +(g177 +(I0 +tp15753 +g179 +tp15754 +Rp15755 +(I1 +(I2 +tp15756 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15757 +tp15758 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15759 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15760 +g179 +tp15761 +Rp15762 +(I1 +(I1 +I1 +I1 +tp15763 +g38 +I00 +S'\x8fg\xbc\xcb\x01\xa7N@' +p15764 +tp15765 +bsg238 +g176 +(g177 +(I0 +tp15766 +g179 +tp15767 +Rp15768 +(I1 +(I1 +I1 +I1 +tp15769 +g38 +I00 +S'\x96/\xd8X^\x1bV?' +p15770 +tp15771 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15772 +g179 +tp15773 +Rp15774 +(I1 +(I1 +I1 +I1 +tp15775 +g38 +I00 +S'|\xb4E5Eh\xea?' +p15776 +tp15777 +bsg252 +g260 +sg48 +(lp15778 +g0 +(g52 +g2 +Ntp15779 +Rp15780 +(dp15781 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15782 +g179 +tp15783 +Rp15784 +(I1 +(I1 +I1 +I1 +tp15785 +g38 +I00 +S'\xe7\x02u\xa9P\x91R@' +p15786 +tp15787 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15788 +g334 +asg113 +I10499 +sg280 +I01 +sbaatp15789 +Rp15790 +sg337 +I00 +sg338 +Nsbaa(lp15791 +g340 +ag0 +(g341 +g2 +Ntp15792 +Rp15793 +(dp15794 +g17 +g15669 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15795 +(lp15796 +g189 +ag0 +(g190 +g2 +Ntp15797 +Rp15798 +(dp15799 +g194 +I01 +sg195 +(lp15800 +g0 +(g197 +g2 +Ntp15801 +Rp15802 +(dp15803 +g201 +g176 +(g177 +(I0 +tp15804 +g179 +tp15805 +Rp15806 +(I1 +(I1 +tp15807 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15808 +tp15809 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15810 +Rp15811 +(dp15812 +g201 +g176 +(g177 +(I0 +tp15813 +g179 +tp15814 +Rp15815 +(I1 +(I2 +tp15816 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15817 +tp15818 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15819 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15820 +g179 +tp15821 +Rp15822 +(I1 +(I1 +I1 +I1 +tp15823 +g38 +I00 +S'\x83k\xd7Fw`I@' +p15824 +tp15825 +bsg238 +g176 +(g177 +(I0 +tp15826 +g179 +tp15827 +Rp15828 +(I1 +(I1 +I1 +I1 +tp15829 +g38 +I00 +S'\xa2Z\xdb\x10\x85%L?' +p15830 +tp15831 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15832 +g179 +tp15833 +Rp15834 +(I1 +(I1 +I1 +I1 +tp15835 +g38 +I00 +S'\x81\xa4:dq\x07\xe8?' +p15836 +tp15837 +bsg252 +g260 +sg48 +(lp15838 +g0 +(g52 +g2 +Ntp15839 +Rp15840 +(dp15841 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15842 +g179 +tp15843 +Rp15844 +(I1 +(I1 +I1 +I1 +tp15845 +g38 +I00 +S'\xab;y\xba;\xe5P@' +p15846 +tp15847 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15848 +g279 +asg113 +I10502 +sg280 +I01 +sbaa(lp15849 +g401 +ag0 +(g190 +g2 +Ntp15850 +Rp15851 +(dp15852 +g194 +I01 +sg195 +(lp15853 +g0 +(g197 +g2 +Ntp15854 +Rp15855 +(dp15856 +g201 +g176 +(g177 +(I0 +tp15857 +g179 +tp15858 +Rp15859 +(I1 +(I1 +tp15860 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15861 +tp15862 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15863 +Rp15864 +(dp15865 +g201 +g176 +(g177 +(I0 +tp15866 +g179 +tp15867 +Rp15868 +(I1 +(I2 +tp15869 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15870 +tp15871 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp15872 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15873 +g179 +tp15874 +Rp15875 +(I1 +(I1 +I1 +I1 +tp15876 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15877 +tp15878 +bsg238 +g176 +(g177 +(I0 +tp15879 +g179 +tp15880 +Rp15881 +(I1 +(I1 +I1 +I1 +tp15882 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15883 +tp15884 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15885 +g179 +tp15886 +Rp15887 +(I1 +(I1 +I1 +I1 +tp15888 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15889 +tp15890 +bsg252 +g260 +sg48 +(lp15891 +g0 +(g52 +g2 +Ntp15892 +Rp15893 +(dp15894 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp15895 +g179 +tp15896 +Rp15897 +(I1 +(I1 +I1 +I1 +tp15898 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p15899 +tp15900 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp15901 +g454 +asg113 +I10503 +sg280 +I01 +sbaatp15902 +Rp15903 +sg337 +I00 +sg338 +Nsbaa(lp15904 +g458 +ag0 +(g459 +g2 +Ntp15905 +Rp15906 +(dp15907 +g17 +g15669 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp15908 +(lp15909 +g189 +ag0 +(g190 +g2 +Ntp15910 +Rp15911 +(dp15912 +g194 +I01 +sg195 +(lp15913 +g0 +(g197 +g2 +Ntp15914 +Rp15915 +(dp15916 +g201 +g176 +(g177 +(I0 +tp15917 +g179 +tp15918 +Rp15919 +(I1 +(I1 +tp15920 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15921 +tp15922 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15923 +Rp15924 +(dp15925 +g201 +g176 +(g177 +(I0 +tp15926 +g179 +tp15927 +Rp15928 +(I1 +(I2 +tp15929 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15930 +tp15931 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp15932 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15933 +g179 +tp15934 +Rp15935 +(I1 +(I1 +I1 +I1 +tp15936 +g38 +I00 +S'\x85:\xc6\xbe\xa4iI@' +p15937 +tp15938 +bsg238 +g176 +(g177 +(I0 +tp15939 +g179 +tp15940 +Rp15941 +(I1 +(I1 +I1 +I1 +tp15942 +g38 +I00 +S'c\x97}\x91\xef[[?' +p15943 +tp15944 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp15945 +g179 +tp15946 +Rp15947 +(I1 +(I1 +I1 +I1 +tp15948 +g38 +I00 +S'\xd4\xd0/\xc7\xca\n\xe8?' +p15949 +tp15950 +bsg252 +g513 +sg48 +(lp15951 +g0 +(g52 +g2 +Ntp15952 +Rp15953 +(dp15954 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp15955 +g179 +tp15956 +Rp15957 +(I1 +(I1 +I1 +I1 +tp15958 +g38 +I00 +S'\xd5\x9e\r\x94\x96\xe7P@' +p15959 +tp15960 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp15961 +g527 +asg113 +I10506 +sg280 +I01 +sbaa(lp15962 +g529 +ag0 +(g190 +g2 +Ntp15963 +Rp15964 +(dp15965 +g194 +I01 +sg195 +(lp15966 +g0 +(g197 +g2 +Ntp15967 +Rp15968 +(dp15969 +g201 +g176 +(g177 +(I0 +tp15970 +g179 +tp15971 +Rp15972 +(I1 +(I1 +tp15973 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p15974 +tp15975 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15976 +Rp15977 +(dp15978 +g201 +g176 +(g177 +(I0 +tp15979 +g179 +tp15980 +Rp15981 +(I1 +(I2 +tp15982 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15983 +tp15984 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp15985 +Rp15986 +(dp15987 +g201 +g176 +(g177 +(I0 +tp15988 +g179 +tp15989 +Rp15990 +(I1 +(I2 +tp15991 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p15992 +tp15993 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp15994 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp15995 +g179 +tp15996 +Rp15997 +(I1 +(I1 +I1 +I1 +tp15998 +g38 +I00 +S'\x19\xed\n\xe0\xda\xedM@' +p15999 +tp16000 +bsg238 +g176 +(g177 +(I0 +tp16001 +g179 +tp16002 +Rp16003 +(I1 +(I1 +I1 +I1 +tp16004 +g38 +I00 +S'\xc4\xa5\xacQ\xe2x\\?' +p16005 +tp16006 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16007 +g179 +tp16008 +Rp16009 +(I1 +(I1 +I1 +I1 +tp16010 +g38 +I00 +S'\xa5\x9e\xf2\xd5{\x17\xea?' +p16011 +tp16012 +bsg252 +g586 +sg48 +(lp16013 +g0 +(g52 +g2 +Ntp16014 +Rp16015 +(dp16016 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp16017 +g179 +tp16018 +Rp16019 +(I1 +(I1 +I1 +I1 +tp16020 +g38 +I00 +S'\x8c\x97n\x12\x83XR@' +p16021 +tp16022 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp16023 +g600 +asg113 +I10507 +sg280 +I01 +sbaatp16024 +Rp16025 +sg337 +I00 +sg338 +Nsbaa(lp16026 +g604 +ag0 +(g605 +g2 +Ntp16027 +Rp16028 +(dp16029 +g17 +g15669 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16030 +(lp16031 +g611 +ag0 +(g190 +g2 +Ntp16032 +Rp16033 +(dp16034 +g194 +I01 +sg195 +(lp16035 +g0 +(g197 +g2 +Ntp16036 +Rp16037 +(dp16038 +g201 +g176 +(g177 +(I0 +tp16039 +g179 +tp16040 +Rp16041 +(I1 +(I1 +tp16042 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p16043 +tp16044 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16045 +Rp16046 +(dp16047 +g201 +g176 +(g177 +(I0 +tp16048 +g179 +tp16049 +Rp16050 +(I1 +(I2 +tp16051 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16052 +tp16053 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp16054 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16055 +g179 +tp16056 +Rp16057 +(I1 +(I1 +I1 +I1 +tp16058 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16059 +tp16060 +bsg238 +g176 +(g177 +(I0 +tp16061 +g179 +tp16062 +Rp16063 +(I1 +(I1 +I1 +I1 +tp16064 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16065 +tp16066 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16067 +g179 +tp16068 +Rp16069 +(I1 +(I1 +I1 +I1 +tp16070 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16071 +tp16072 +bsg252 +g513 +sg48 +(lp16073 +g0 +(g52 +g2 +Ntp16074 +Rp16075 +(dp16076 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp16077 +g179 +tp16078 +Rp16079 +(I1 +(I1 +I1 +I1 +tp16080 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16081 +tp16082 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp16083 +g664 +asg113 +I10510 +sg280 +I01 +sbaa(lp16084 +g666 +ag0 +(g190 +g2 +Ntp16085 +Rp16086 +(dp16087 +g194 +I01 +sg195 +(lp16088 +g0 +(g197 +g2 +Ntp16089 +Rp16090 +(dp16091 +g201 +g176 +(g177 +(I0 +tp16092 +g179 +tp16093 +Rp16094 +(I1 +(I1 +tp16095 +g208 +I00 +S"0'\x00\x00\x00\x00\x00\x00" +p16096 +tp16097 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16098 +Rp16099 +(dp16100 +g201 +g176 +(g177 +(I0 +tp16101 +g179 +tp16102 +Rp16103 +(I1 +(I2 +tp16104 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16105 +tp16106 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp16107 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16108 +g179 +tp16109 +Rp16110 +(I1 +(I1 +I1 +I1 +tp16111 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16112 +tp16113 +bsg238 +g176 +(g177 +(I0 +tp16114 +g179 +tp16115 +Rp16116 +(I1 +(I1 +I1 +I1 +tp16117 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16118 +tp16119 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16120 +g179 +tp16121 +Rp16122 +(I1 +(I1 +I1 +I1 +tp16123 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16124 +tp16125 +bsg252 +g713 +sg48 +(lp16126 +g0 +(g52 +g2 +Ntp16127 +Rp16128 +(dp16129 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp16130 +g179 +tp16131 +Rp16132 +(I1 +(I1 +I1 +I1 +tp16133 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16134 +tp16135 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp16136 +g727 +asg113 +I10511 +sg280 +I01 +sbaatp16137 +Rp16138 +sg337 +I00 +sg338 +Nsbaatp16139 +Rp16140 +aa(lp16141 +I10033 +ag7 +((lp16142 +(lp16143 +g12 +ag0 +(g13 +g2 +Ntp16144 +Rp16145 +(dp16146 +g17 +g0 +(g18 +g2 +Ntp16147 +Rp16148 +(dp16149 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p16150 +sg116 +g0 +(g117 +g2 +Ntp16151 +Rp16152 +(dp16153 +g121 +(lp16154 +g0 +(g123 +g2 +Ntp16155 +Rp16156 +(dp16157 +g127 +g12219 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp16158 +Rp16159 +(dp16160 +g127 +g0 +(g128 +g2 +Ntp16161 +Rp16162 +(dp16163 +g23 +g132 +sg133 +(dp16164 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x8f\xc2\xf5(\\\x8f\x0c@' +p16165 +tp16166 +Rp16167 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p16168 +sg113 +I61 +sg146 +(lp16169 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10033 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16170 +(lp16171 +g189 +ag0 +(g190 +g2 +Ntp16172 +Rp16173 +(dp16174 +g194 +I01 +sg195 +(lp16175 +g0 +(g197 +g2 +Ntp16176 +Rp16177 +(dp16178 +g201 +g176 +(g177 +(I0 +tp16179 +g179 +tp16180 +Rp16181 +(I1 +(I1 +tp16182 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16183 +tp16184 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16185 +Rp16186 +(dp16187 +g201 +g176 +(g177 +(I0 +tp16188 +g179 +tp16189 +Rp16190 +(I1 +(I2 +tp16191 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16192 +tp16193 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16194 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16195 +g179 +tp16196 +Rp16197 +(I1 +(I1 +I1 +I1 +tp16198 +g38 +I00 +S'\xfb\xbbf\x14\xbb\xc8G@' +p16199 +tp16200 +bsg238 +g176 +(g177 +(I0 +tp16201 +g179 +tp16202 +Rp16203 +(I1 +(I1 +I1 +I1 +tp16204 +g38 +I00 +S'\xdc\x04\x8b\x86\x0b1E?' +p16205 +tp16206 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16207 +g179 +tp16208 +Rp16209 +(I1 +(I1 +I1 +I1 +tp16210 +g38 +I00 +S'\xc6d\xf2jiC\xe7?' +p16211 +tp16212 +bsg252 +g260 +sg48 +(lp16213 +g0 +(g52 +g2 +Ntp16214 +Rp16215 +(dp16216 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16217 +g179 +tp16218 +Rp16219 +(I1 +(I1 +I1 +I1 +tp16220 +g38 +I00 +S'\xdbn2\x1ff[P@' +p16221 +tp16222 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16223 +g279 +asg113 +I10514 +sg280 +I01 +sbaa(lp16224 +g12 +ag0 +(g190 +g2 +Ntp16225 +Rp16226 +(dp16227 +g194 +I01 +sg195 +(lp16228 +g0 +(g197 +g2 +Ntp16229 +Rp16230 +(dp16231 +g201 +g176 +(g177 +(I0 +tp16232 +g179 +tp16233 +Rp16234 +(I1 +(I1 +tp16235 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16236 +tp16237 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16238 +Rp16239 +(dp16240 +g201 +g176 +(g177 +(I0 +tp16241 +g179 +tp16242 +Rp16243 +(I1 +(I2 +tp16244 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16245 +tp16246 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16247 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16248 +g179 +tp16249 +Rp16250 +(I1 +(I1 +I1 +I1 +tp16251 +g38 +I00 +S'\xa9v\xd0\xa1\x94\xb1H@' +p16252 +tp16253 +bsg238 +g176 +(g177 +(I0 +tp16254 +g179 +tp16255 +Rp16256 +(I1 +(I1 +I1 +I1 +tp16257 +g38 +I00 +S"\xd9_'\xe8KrP?" +p16258 +tp16259 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16260 +g179 +tp16261 +Rp16262 +(I1 +(I1 +I1 +I1 +tp16263 +g38 +I00 +S'|\x9a \xd6\xef\xb3\xe7?' +p16264 +tp16265 +bsg252 +g260 +sg48 +(lp16266 +g0 +(g52 +g2 +Ntp16267 +Rp16268 +(dp16269 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16270 +g179 +tp16271 +Rp16272 +(I1 +(I1 +I1 +I1 +tp16273 +g38 +I00 +S'\x9f\xec\x8e\xa2\x84\xaaP@' +p16274 +tp16275 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16276 +g334 +asg113 +I10515 +sg280 +I01 +sbaatp16277 +Rp16278 +sg337 +I00 +sg338 +Nsbaa(lp16279 +g340 +ag0 +(g341 +g2 +Ntp16280 +Rp16281 +(dp16282 +g17 +g16148 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16283 +(lp16284 +g189 +ag0 +(g190 +g2 +Ntp16285 +Rp16286 +(dp16287 +g194 +I01 +sg195 +(lp16288 +g0 +(g197 +g2 +Ntp16289 +Rp16290 +(dp16291 +g201 +g176 +(g177 +(I0 +tp16292 +g179 +tp16293 +Rp16294 +(I1 +(I1 +tp16295 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16296 +tp16297 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16298 +Rp16299 +(dp16300 +g201 +g176 +(g177 +(I0 +tp16301 +g179 +tp16302 +Rp16303 +(I1 +(I2 +tp16304 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16305 +tp16306 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16307 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16308 +g179 +tp16309 +Rp16310 +(I1 +(I1 +I1 +I1 +tp16311 +g38 +I00 +S'\xfb\xbbf\x14\xbb\xc8G@' +p16312 +tp16313 +bsg238 +g176 +(g177 +(I0 +tp16314 +g179 +tp16315 +Rp16316 +(I1 +(I1 +I1 +I1 +tp16317 +g38 +I00 +S'\xdc\x04\x8b\x86\x0b1E?' +p16318 +tp16319 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16320 +g179 +tp16321 +Rp16322 +(I1 +(I1 +I1 +I1 +tp16323 +g38 +I00 +S'\xc6d\xf2jiC\xe7?' +p16324 +tp16325 +bsg252 +g260 +sg48 +(lp16326 +g0 +(g52 +g2 +Ntp16327 +Rp16328 +(dp16329 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16330 +g179 +tp16331 +Rp16332 +(I1 +(I1 +I1 +I1 +tp16333 +g38 +I00 +S'\xdbn2\x1ff[P@' +p16334 +tp16335 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16336 +g279 +asg113 +I10518 +sg280 +I01 +sbaa(lp16337 +g401 +ag0 +(g190 +g2 +Ntp16338 +Rp16339 +(dp16340 +g194 +I01 +sg195 +(lp16341 +g0 +(g197 +g2 +Ntp16342 +Rp16343 +(dp16344 +g201 +g176 +(g177 +(I0 +tp16345 +g179 +tp16346 +Rp16347 +(I1 +(I1 +tp16348 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16349 +tp16350 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16351 +Rp16352 +(dp16353 +g201 +g176 +(g177 +(I0 +tp16354 +g179 +tp16355 +Rp16356 +(I1 +(I2 +tp16357 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16358 +tp16359 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16360 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16361 +g179 +tp16362 +Rp16363 +(I1 +(I1 +I1 +I1 +tp16364 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16365 +tp16366 +bsg238 +g176 +(g177 +(I0 +tp16367 +g179 +tp16368 +Rp16369 +(I1 +(I1 +I1 +I1 +tp16370 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16371 +tp16372 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16373 +g179 +tp16374 +Rp16375 +(I1 +(I1 +I1 +I1 +tp16376 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16377 +tp16378 +bsg252 +g260 +sg48 +(lp16379 +g0 +(g52 +g2 +Ntp16380 +Rp16381 +(dp16382 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16383 +g179 +tp16384 +Rp16385 +(I1 +(I1 +I1 +I1 +tp16386 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16387 +tp16388 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16389 +g454 +asg113 +I10519 +sg280 +I01 +sbaatp16390 +Rp16391 +sg337 +I00 +sg338 +Nsbaa(lp16392 +g458 +ag0 +(g459 +g2 +Ntp16393 +Rp16394 +(dp16395 +g17 +g16148 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16396 +(lp16397 +g189 +ag0 +(g190 +g2 +Ntp16398 +Rp16399 +(dp16400 +g194 +I01 +sg195 +(lp16401 +g0 +(g197 +g2 +Ntp16402 +Rp16403 +(dp16404 +g201 +g176 +(g177 +(I0 +tp16405 +g179 +tp16406 +Rp16407 +(I1 +(I1 +tp16408 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16409 +tp16410 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16411 +Rp16412 +(dp16413 +g201 +g176 +(g177 +(I0 +tp16414 +g179 +tp16415 +Rp16416 +(I1 +(I2 +tp16417 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16418 +tp16419 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp16420 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16421 +g179 +tp16422 +Rp16423 +(I1 +(I1 +I1 +I1 +tp16424 +g38 +I00 +S'x\xa3\x81\x06X\xa0G@' +p16425 +tp16426 +bsg238 +g176 +(g177 +(I0 +tp16427 +g179 +tp16428 +Rp16429 +(I1 +(I1 +I1 +I1 +tp16430 +g38 +I00 +S'\x92Wp,@\xd9X?' +p16431 +tp16432 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16433 +g179 +tp16434 +Rp16435 +(I1 +(I1 +I1 +I1 +tp16436 +g38 +I00 +S'i\xe5\x16\xe6\xad.\xe7?' +p16437 +tp16438 +bsg252 +g513 +sg48 +(lp16439 +g0 +(g52 +g2 +Ntp16440 +Rp16441 +(dp16442 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp16443 +g179 +tp16444 +Rp16445 +(I1 +(I1 +I1 +I1 +tp16446 +g38 +I00 +S'N\x19\xc8E\xd2LP@' +p16447 +tp16448 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp16449 +g527 +asg113 +I10522 +sg280 +I01 +sbaa(lp16450 +g529 +ag0 +(g190 +g2 +Ntp16451 +Rp16452 +(dp16453 +g194 +I01 +sg195 +(lp16454 +g0 +(g197 +g2 +Ntp16455 +Rp16456 +(dp16457 +g201 +g176 +(g177 +(I0 +tp16458 +g179 +tp16459 +Rp16460 +(I1 +(I1 +tp16461 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16462 +tp16463 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16464 +Rp16465 +(dp16466 +g201 +g176 +(g177 +(I0 +tp16467 +g179 +tp16468 +Rp16469 +(I1 +(I2 +tp16470 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16471 +tp16472 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16473 +Rp16474 +(dp16475 +g201 +g176 +(g177 +(I0 +tp16476 +g179 +tp16477 +Rp16478 +(I1 +(I2 +tp16479 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16480 +tp16481 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp16482 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16483 +g179 +tp16484 +Rp16485 +(I1 +(I1 +I1 +I1 +tp16486 +g38 +I00 +S'!\x1a\xc4\xa4\xcb\x03H@' +p16487 +tp16488 +bsg238 +g176 +(g177 +(I0 +tp16489 +g179 +tp16490 +Rp16491 +(I1 +(I1 +I1 +I1 +tp16492 +g38 +I00 +S'5\xb0N\xcez\x8bX?' +p16493 +tp16494 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16495 +g179 +tp16496 +Rp16497 +(I1 +(I1 +I1 +I1 +tp16498 +g38 +I00 +S'\xf0\x9eR\x87Q_\xe7?' +p16499 +tp16500 +bsg252 +g586 +sg48 +(lp16501 +g0 +(g52 +g2 +Ntp16502 +Rp16503 +(dp16504 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp16505 +g179 +tp16506 +Rp16507 +(I1 +(I1 +I1 +I1 +tp16508 +g38 +I00 +S'\xc1\x17&S\x05oP@' +p16509 +tp16510 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp16511 +g600 +asg113 +I10523 +sg280 +I01 +sbaatp16512 +Rp16513 +sg337 +I00 +sg338 +Nsbaa(lp16514 +g604 +ag0 +(g605 +g2 +Ntp16515 +Rp16516 +(dp16517 +g17 +g16148 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16518 +(lp16519 +g611 +ag0 +(g190 +g2 +Ntp16520 +Rp16521 +(dp16522 +g194 +I01 +sg195 +(lp16523 +g0 +(g197 +g2 +Ntp16524 +Rp16525 +(dp16526 +g201 +g176 +(g177 +(I0 +tp16527 +g179 +tp16528 +Rp16529 +(I1 +(I1 +tp16530 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16531 +tp16532 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16533 +Rp16534 +(dp16535 +g201 +g176 +(g177 +(I0 +tp16536 +g179 +tp16537 +Rp16538 +(I1 +(I2 +tp16539 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16540 +tp16541 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp16542 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16543 +g179 +tp16544 +Rp16545 +(I1 +(I1 +I1 +I1 +tp16546 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16547 +tp16548 +bsg238 +g176 +(g177 +(I0 +tp16549 +g179 +tp16550 +Rp16551 +(I1 +(I1 +I1 +I1 +tp16552 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16553 +tp16554 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16555 +g179 +tp16556 +Rp16557 +(I1 +(I1 +I1 +I1 +tp16558 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16559 +tp16560 +bsg252 +g513 +sg48 +(lp16561 +g0 +(g52 +g2 +Ntp16562 +Rp16563 +(dp16564 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp16565 +g179 +tp16566 +Rp16567 +(I1 +(I1 +I1 +I1 +tp16568 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16569 +tp16570 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp16571 +g664 +asg113 +I10526 +sg280 +I01 +sbaa(lp16572 +g666 +ag0 +(g190 +g2 +Ntp16573 +Rp16574 +(dp16575 +g194 +I01 +sg195 +(lp16576 +g0 +(g197 +g2 +Ntp16577 +Rp16578 +(dp16579 +g201 +g176 +(g177 +(I0 +tp16580 +g179 +tp16581 +Rp16582 +(I1 +(I1 +tp16583 +g208 +I00 +S"1'\x00\x00\x00\x00\x00\x00" +p16584 +tp16585 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16586 +Rp16587 +(dp16588 +g201 +g176 +(g177 +(I0 +tp16589 +g179 +tp16590 +Rp16591 +(I1 +(I2 +tp16592 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16593 +tp16594 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp16595 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16596 +g179 +tp16597 +Rp16598 +(I1 +(I1 +I1 +I1 +tp16599 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16600 +tp16601 +bsg238 +g176 +(g177 +(I0 +tp16602 +g179 +tp16603 +Rp16604 +(I1 +(I1 +I1 +I1 +tp16605 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16606 +tp16607 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16608 +g179 +tp16609 +Rp16610 +(I1 +(I1 +I1 +I1 +tp16611 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16612 +tp16613 +bsg252 +g713 +sg48 +(lp16614 +g0 +(g52 +g2 +Ntp16615 +Rp16616 +(dp16617 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp16618 +g179 +tp16619 +Rp16620 +(I1 +(I1 +I1 +I1 +tp16621 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16622 +tp16623 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp16624 +g727 +asg113 +I10527 +sg280 +I01 +sbaatp16625 +Rp16626 +sg337 +I00 +sg338 +Nsbaatp16627 +Rp16628 +aa(lp16629 +I10034 +ag7 +((lp16630 +(lp16631 +g12 +ag0 +(g13 +g2 +Ntp16632 +Rp16633 +(dp16634 +g17 +g0 +(g18 +g2 +Ntp16635 +Rp16636 +(dp16637 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p16638 +sg116 +g0 +(g117 +g2 +Ntp16639 +Rp16640 +(dp16641 +g121 +(lp16642 +g0 +(g123 +g2 +Ntp16643 +Rp16644 +(dp16645 +g127 +g0 +(g128 +g2 +Ntp16646 +Rp16647 +(dp16648 +g23 +g132 +sg133 +(dp16649 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'H\xe1z\x14\xaeG\x01@' +p16650 +tp16651 +Rp16652 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p16653 +sg113 +I62 +sg146 +(lp16654 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp16655 +Rp16656 +(dp16657 +g127 +g0 +(g128 +g2 +Ntp16658 +Rp16659 +(dp16660 +g23 +g132 +sg133 +(dp16661 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x1f\x85\xebQ\xb8\x1e\x01@' +p16662 +tp16663 +Rp16664 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p16665 +sg113 +I63 +sg146 +(lp16666 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10034 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16667 +(lp16668 +g189 +ag0 +(g190 +g2 +Ntp16669 +Rp16670 +(dp16671 +g194 +I01 +sg195 +(lp16672 +g0 +(g197 +g2 +Ntp16673 +Rp16674 +(dp16675 +g201 +g176 +(g177 +(I0 +tp16676 +g179 +tp16677 +Rp16678 +(I1 +(I1 +tp16679 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16680 +tp16681 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16682 +Rp16683 +(dp16684 +g201 +g176 +(g177 +(I0 +tp16685 +g179 +tp16686 +Rp16687 +(I1 +(I2 +tp16688 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16689 +tp16690 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16691 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16692 +g179 +tp16693 +Rp16694 +(I1 +(I1 +I1 +I1 +tp16695 +g38 +I00 +S'\x14\x11\xf5p\x19_\x0e@' +p16696 +tp16697 +bsg238 +g176 +(g177 +(I0 +tp16698 +g179 +tp16699 +Rp16700 +(I1 +(I1 +I1 +I1 +tp16701 +g38 +I00 +S'\xca\xb3\x04\xc0\x07l)?' +p16702 +tp16703 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16704 +g179 +tp16705 +Rp16706 +(I1 +(I1 +I1 +I1 +tp16707 +g38 +I00 +S'\xf0\x14\xa8\x07\xc2I\xca?' +p16708 +tp16709 +bsg252 +g260 +sg48 +(lp16710 +g0 +(g52 +g2 +Ntp16711 +Rp16712 +(dp16713 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16714 +g179 +tp16715 +Rp16716 +(I1 +(I1 +I1 +I1 +tp16717 +g38 +I00 +S'\xb9.bm\xdc{2@' +p16718 +tp16719 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16720 +g279 +asg113 +I10530 +sg280 +I01 +sbaa(lp16721 +g12 +ag0 +(g190 +g2 +Ntp16722 +Rp16723 +(dp16724 +g194 +I01 +sg195 +(lp16725 +g0 +(g197 +g2 +Ntp16726 +Rp16727 +(dp16728 +g201 +g176 +(g177 +(I0 +tp16729 +g179 +tp16730 +Rp16731 +(I1 +(I1 +tp16732 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16733 +tp16734 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16735 +Rp16736 +(dp16737 +g201 +g176 +(g177 +(I0 +tp16738 +g179 +tp16739 +Rp16740 +(I1 +(I2 +tp16741 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16742 +tp16743 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16744 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16745 +g179 +tp16746 +Rp16747 +(I1 +(I1 +I1 +I1 +tp16748 +g38 +I00 +S' \x83r\xc6L%\xd7?' +p16749 +tp16750 +bsg238 +g176 +(g177 +(I0 +tp16751 +g179 +tp16752 +Rp16753 +(I1 +(I1 +I1 +I1 +tp16754 +g38 +I00 +S'=\xbf\xc6J|\x04\x11?' +p16755 +tp16756 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16757 +g179 +tp16758 +Rp16759 +(I1 +(I1 +I1 +I1 +tp16760 +g38 +I00 +S'U\x03\xc5\xe7):\xb0?' +p16761 +tp16762 +bsg252 +g260 +sg48 +(lp16763 +g0 +(g52 +g2 +Ntp16764 +Rp16765 +(dp16766 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16767 +g179 +tp16768 +Rp16769 +(I1 +(I1 +I1 +I1 +tp16770 +g38 +I00 +S'\xb0\x0c\xed\xed\xca\xd1\x16@' +p16771 +tp16772 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16773 +g334 +asg113 +I10531 +sg280 +I01 +sbaatp16774 +Rp16775 +sg337 +I00 +sg338 +Nsbaa(lp16776 +g340 +ag0 +(g341 +g2 +Ntp16777 +Rp16778 +(dp16779 +g17 +g16636 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16780 +(lp16781 +g189 +ag0 +(g190 +g2 +Ntp16782 +Rp16783 +(dp16784 +g194 +I01 +sg195 +(lp16785 +g0 +(g197 +g2 +Ntp16786 +Rp16787 +(dp16788 +g201 +g176 +(g177 +(I0 +tp16789 +g179 +tp16790 +Rp16791 +(I1 +(I1 +tp16792 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16793 +tp16794 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16795 +Rp16796 +(dp16797 +g201 +g176 +(g177 +(I0 +tp16798 +g179 +tp16799 +Rp16800 +(I1 +(I2 +tp16801 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16802 +tp16803 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16804 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16805 +g179 +tp16806 +Rp16807 +(I1 +(I1 +I1 +I1 +tp16808 +g38 +I00 +S'\x14\x11\xf5p\x19_\x0e@' +p16809 +tp16810 +bsg238 +g176 +(g177 +(I0 +tp16811 +g179 +tp16812 +Rp16813 +(I1 +(I1 +I1 +I1 +tp16814 +g38 +I00 +S'\xca\xb3\x04\xc0\x07l)?' +p16815 +tp16816 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16817 +g179 +tp16818 +Rp16819 +(I1 +(I1 +I1 +I1 +tp16820 +g38 +I00 +S'\xf0\x14\xa8\x07\xc2I\xca?' +p16821 +tp16822 +bsg252 +g260 +sg48 +(lp16823 +g0 +(g52 +g2 +Ntp16824 +Rp16825 +(dp16826 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16827 +g179 +tp16828 +Rp16829 +(I1 +(I1 +I1 +I1 +tp16830 +g38 +I00 +S'\xb9.bm\xdc{2@' +p16831 +tp16832 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16833 +g279 +asg113 +I10534 +sg280 +I01 +sbaa(lp16834 +g401 +ag0 +(g190 +g2 +Ntp16835 +Rp16836 +(dp16837 +g194 +I01 +sg195 +(lp16838 +g0 +(g197 +g2 +Ntp16839 +Rp16840 +(dp16841 +g201 +g176 +(g177 +(I0 +tp16842 +g179 +tp16843 +Rp16844 +(I1 +(I1 +tp16845 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16846 +tp16847 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16848 +Rp16849 +(dp16850 +g201 +g176 +(g177 +(I0 +tp16851 +g179 +tp16852 +Rp16853 +(I1 +(I2 +tp16854 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16855 +tp16856 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp16857 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16858 +g179 +tp16859 +Rp16860 +(I1 +(I1 +I1 +I1 +tp16861 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16862 +tp16863 +bsg238 +g176 +(g177 +(I0 +tp16864 +g179 +tp16865 +Rp16866 +(I1 +(I1 +I1 +I1 +tp16867 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16868 +tp16869 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16870 +g179 +tp16871 +Rp16872 +(I1 +(I1 +I1 +I1 +tp16873 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16874 +tp16875 +bsg252 +g260 +sg48 +(lp16876 +g0 +(g52 +g2 +Ntp16877 +Rp16878 +(dp16879 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp16880 +g179 +tp16881 +Rp16882 +(I1 +(I1 +I1 +I1 +tp16883 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p16884 +tp16885 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp16886 +g454 +asg113 +I10535 +sg280 +I01 +sbaatp16887 +Rp16888 +sg337 +I00 +sg338 +Nsbaa(lp16889 +g458 +ag0 +(g459 +g2 +Ntp16890 +Rp16891 +(dp16892 +g17 +g16636 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp16893 +(lp16894 +g189 +ag0 +(g190 +g2 +Ntp16895 +Rp16896 +(dp16897 +g194 +I01 +sg195 +(lp16898 +g0 +(g197 +g2 +Ntp16899 +Rp16900 +(dp16901 +g201 +g176 +(g177 +(I0 +tp16902 +g179 +tp16903 +Rp16904 +(I1 +(I1 +tp16905 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16906 +tp16907 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16908 +Rp16909 +(dp16910 +g201 +g176 +(g177 +(I0 +tp16911 +g179 +tp16912 +Rp16913 +(I1 +(I2 +tp16914 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16915 +tp16916 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp16917 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16918 +g179 +tp16919 +Rp16920 +(I1 +(I1 +I1 +I1 +tp16921 +g38 +I00 +S'\n\xc6\xe3\x86\xe9\xa0\x0e@' +p16922 +tp16923 +bsg238 +g176 +(g177 +(I0 +tp16924 +g179 +tp16925 +Rp16926 +(I1 +(I1 +I1 +I1 +tp16927 +g38 +I00 +S'\xeb\x18n\x1bcWN?' +p16928 +tp16929 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16930 +g179 +tp16931 +Rp16932 +(I1 +(I1 +I1 +I1 +tp16933 +g38 +I00 +S'\x15\xa0nTb`\xca?' +p16934 +tp16935 +bsg252 +g513 +sg48 +(lp16936 +g0 +(g52 +g2 +Ntp16937 +Rp16938 +(dp16939 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp16940 +g179 +tp16941 +Rp16942 +(I1 +(I1 +I1 +I1 +tp16943 +g38 +I00 +S'\x8f\xc8]#\xc5\x8b2@' +p16944 +tp16945 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp16946 +g527 +asg113 +I10538 +sg280 +I01 +sbaa(lp16947 +g529 +ag0 +(g190 +g2 +Ntp16948 +Rp16949 +(dp16950 +g194 +I01 +sg195 +(lp16951 +g0 +(g197 +g2 +Ntp16952 +Rp16953 +(dp16954 +g201 +g176 +(g177 +(I0 +tp16955 +g179 +tp16956 +Rp16957 +(I1 +(I1 +tp16958 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p16959 +tp16960 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16961 +Rp16962 +(dp16963 +g201 +g176 +(g177 +(I0 +tp16964 +g179 +tp16965 +Rp16966 +(I1 +(I2 +tp16967 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16968 +tp16969 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp16970 +Rp16971 +(dp16972 +g201 +g176 +(g177 +(I0 +tp16973 +g179 +tp16974 +Rp16975 +(I1 +(I2 +tp16976 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p16977 +tp16978 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp16979 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp16980 +g179 +tp16981 +Rp16982 +(I1 +(I1 +I1 +I1 +tp16983 +g38 +I00 +S'(n7\x1c\xf1\xff\xd6?' +p16984 +tp16985 +bsg238 +g176 +(g177 +(I0 +tp16986 +g179 +tp16987 +Rp16988 +(I1 +(I1 +I1 +I1 +tp16989 +g38 +I00 +S'\x8avVF\xe4\xb41?' +p16990 +tp16991 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp16992 +g179 +tp16993 +Rp16994 +(I1 +(I1 +I1 +I1 +tp16995 +g38 +I00 +S'\xb20\xe2\xc6\xde)\xb0?' +p16996 +tp16997 +bsg252 +g586 +sg48 +(lp16998 +g0 +(g52 +g2 +Ntp16999 +Rp17000 +(dp17001 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp17002 +g179 +tp17003 +Rp17004 +(I1 +(I1 +I1 +I1 +tp17005 +g38 +I00 +S'z\x14\xaeG\xe1\xba\x16@' +p17006 +tp17007 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp17008 +g600 +asg113 +I10539 +sg280 +I01 +sbaatp17009 +Rp17010 +sg337 +I00 +sg338 +Nsbaa(lp17011 +g604 +ag0 +(g605 +g2 +Ntp17012 +Rp17013 +(dp17014 +g17 +g16636 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17015 +(lp17016 +g611 +ag0 +(g190 +g2 +Ntp17017 +Rp17018 +(dp17019 +g194 +I01 +sg195 +(lp17020 +g0 +(g197 +g2 +Ntp17021 +Rp17022 +(dp17023 +g201 +g176 +(g177 +(I0 +tp17024 +g179 +tp17025 +Rp17026 +(I1 +(I1 +tp17027 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p17028 +tp17029 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17030 +Rp17031 +(dp17032 +g201 +g176 +(g177 +(I0 +tp17033 +g179 +tp17034 +Rp17035 +(I1 +(I2 +tp17036 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17037 +tp17038 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp17039 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17040 +g179 +tp17041 +Rp17042 +(I1 +(I1 +I1 +I1 +tp17043 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17044 +tp17045 +bsg238 +g176 +(g177 +(I0 +tp17046 +g179 +tp17047 +Rp17048 +(I1 +(I1 +I1 +I1 +tp17049 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17050 +tp17051 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17052 +g179 +tp17053 +Rp17054 +(I1 +(I1 +I1 +I1 +tp17055 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17056 +tp17057 +bsg252 +g513 +sg48 +(lp17058 +g0 +(g52 +g2 +Ntp17059 +Rp17060 +(dp17061 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp17062 +g179 +tp17063 +Rp17064 +(I1 +(I1 +I1 +I1 +tp17065 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17066 +tp17067 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp17068 +g664 +asg113 +I10542 +sg280 +I01 +sbaa(lp17069 +g666 +ag0 +(g190 +g2 +Ntp17070 +Rp17071 +(dp17072 +g194 +I01 +sg195 +(lp17073 +g0 +(g197 +g2 +Ntp17074 +Rp17075 +(dp17076 +g201 +g176 +(g177 +(I0 +tp17077 +g179 +tp17078 +Rp17079 +(I1 +(I1 +tp17080 +g208 +I00 +S"2'\x00\x00\x00\x00\x00\x00" +p17081 +tp17082 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17083 +Rp17084 +(dp17085 +g201 +g176 +(g177 +(I0 +tp17086 +g179 +tp17087 +Rp17088 +(I1 +(I2 +tp17089 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17090 +tp17091 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp17092 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17093 +g179 +tp17094 +Rp17095 +(I1 +(I1 +I1 +I1 +tp17096 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17097 +tp17098 +bsg238 +g176 +(g177 +(I0 +tp17099 +g179 +tp17100 +Rp17101 +(I1 +(I1 +I1 +I1 +tp17102 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17103 +tp17104 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17105 +g179 +tp17106 +Rp17107 +(I1 +(I1 +I1 +I1 +tp17108 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17109 +tp17110 +bsg252 +g713 +sg48 +(lp17111 +g0 +(g52 +g2 +Ntp17112 +Rp17113 +(dp17114 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp17115 +g179 +tp17116 +Rp17117 +(I1 +(I1 +I1 +I1 +tp17118 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17119 +tp17120 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp17121 +g727 +asg113 +I10543 +sg280 +I01 +sbaatp17122 +Rp17123 +sg337 +I00 +sg338 +Nsbaatp17124 +Rp17125 +aa(lp17126 +I10035 +ag7 +((lp17127 +(lp17128 +g12 +ag0 +(g13 +g2 +Ntp17129 +Rp17130 +(dp17131 +g17 +g0 +(g18 +g2 +Ntp17132 +Rp17133 +(dp17134 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p17135 +sg116 +g0 +(g117 +g2 +Ntp17136 +Rp17137 +(dp17138 +g121 +(lp17139 +g0 +(g123 +g2 +Ntp17140 +Rp17141 +(dp17142 +g127 +g0 +(g128 +g2 +Ntp17143 +Rp17144 +(dp17145 +g23 +g132 +sg133 +(dp17146 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xf4?' +p17147 +tp17148 +Rp17149 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p17150 +sg113 +I64 +sg146 +(lp17151 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp17152 +Rp17153 +(dp17154 +g127 +g0 +(g128 +g2 +Ntp17155 +Rp17156 +(dp17157 +g23 +g132 +sg133 +(dp17158 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xf4?' +p17159 +tp17160 +Rp17161 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p17162 +sg113 +I65 +sg146 +(lp17163 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10035 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17164 +(lp17165 +g189 +ag0 +(g190 +g2 +Ntp17166 +Rp17167 +(dp17168 +g194 +I01 +sg195 +(lp17169 +g0 +(g197 +g2 +Ntp17170 +Rp17171 +(dp17172 +g201 +g176 +(g177 +(I0 +tp17173 +g179 +tp17174 +Rp17175 +(I1 +(I1 +tp17176 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17177 +tp17178 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17179 +Rp17180 +(dp17181 +g201 +g176 +(g177 +(I0 +tp17182 +g179 +tp17183 +Rp17184 +(I1 +(I2 +tp17185 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17186 +tp17187 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17188 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17189 +g179 +tp17190 +Rp17191 +(I1 +(I1 +I1 +I1 +tp17192 +g38 +I00 +S"\x85'kF~\x808@" +p17193 +tp17194 +bsg238 +g176 +(g177 +(I0 +tp17195 +g179 +tp17196 +Rp17197 +(I1 +(I1 +I1 +I1 +tp17198 +g38 +I00 +S'\xc9\xbeD\xb2Y\xc6B?' +p17199 +tp17200 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17201 +g179 +tp17202 +Rp17203 +(I1 +(I1 +I1 +I1 +tp17204 +g38 +I00 +S'u\xea\x9f\xac\x1b\xb2\xe0?' +p17205 +tp17206 +bsg252 +g260 +sg48 +(lp17207 +g0 +(g52 +g2 +Ntp17208 +Rp17209 +(dp17210 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17211 +g179 +tp17212 +Rp17213 +(I1 +(I1 +I1 +I1 +tp17214 +g38 +I00 +S'\xb4\xe1\xc0\xeavzG@' +p17215 +tp17216 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17217 +g279 +asg113 +I10546 +sg280 +I01 +sbaa(lp17218 +g12 +ag0 +(g190 +g2 +Ntp17219 +Rp17220 +(dp17221 +g194 +I01 +sg195 +(lp17222 +g0 +(g197 +g2 +Ntp17223 +Rp17224 +(dp17225 +g201 +g176 +(g177 +(I0 +tp17226 +g179 +tp17227 +Rp17228 +(I1 +(I1 +tp17229 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17230 +tp17231 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17232 +Rp17233 +(dp17234 +g201 +g176 +(g177 +(I0 +tp17235 +g179 +tp17236 +Rp17237 +(I1 +(I2 +tp17238 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17239 +tp17240 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17241 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17242 +g179 +tp17243 +Rp17244 +(I1 +(I1 +I1 +I1 +tp17245 +g38 +I00 +S'\x89\xd3{\x9a\xa0N\x10@' +p17246 +tp17247 +bsg238 +g176 +(g177 +(I0 +tp17248 +g179 +tp17249 +Rp17250 +(I1 +(I1 +I1 +I1 +tp17251 +g38 +I00 +S'\xd5y\xc4\xdb\x19\xde.?' +p17252 +tp17253 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17254 +g179 +tp17255 +Rp17256 +(I1 +(I1 +I1 +I1 +tp17257 +g38 +I00 +S'\x03\xd4\xb2\xcf\xb5=\xcb?' +p17258 +tp17259 +bsg252 +g260 +sg48 +(lp17260 +g0 +(g52 +g2 +Ntp17261 +Rp17262 +(dp17263 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17264 +g179 +tp17265 +Rp17266 +(I1 +(I1 +I1 +I1 +tp17267 +g38 +I00 +S"\x12\xbd\t\xd6c'3@" +p17268 +tp17269 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17270 +g334 +asg113 +I10547 +sg280 +I01 +sbaatp17271 +Rp17272 +sg337 +I00 +sg338 +Nsbaa(lp17273 +g340 +ag0 +(g341 +g2 +Ntp17274 +Rp17275 +(dp17276 +g17 +g17133 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17277 +(lp17278 +g189 +ag0 +(g190 +g2 +Ntp17279 +Rp17280 +(dp17281 +g194 +I01 +sg195 +(lp17282 +g0 +(g197 +g2 +Ntp17283 +Rp17284 +(dp17285 +g201 +g176 +(g177 +(I0 +tp17286 +g179 +tp17287 +Rp17288 +(I1 +(I1 +tp17289 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17290 +tp17291 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17292 +Rp17293 +(dp17294 +g201 +g176 +(g177 +(I0 +tp17295 +g179 +tp17296 +Rp17297 +(I1 +(I2 +tp17298 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17299 +tp17300 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17301 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17302 +g179 +tp17303 +Rp17304 +(I1 +(I1 +I1 +I1 +tp17305 +g38 +I00 +S"\x85'kF~\x808@" +p17306 +tp17307 +bsg238 +g176 +(g177 +(I0 +tp17308 +g179 +tp17309 +Rp17310 +(I1 +(I1 +I1 +I1 +tp17311 +g38 +I00 +S'\xc9\xbeD\xb2Y\xc6B?' +p17312 +tp17313 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17314 +g179 +tp17315 +Rp17316 +(I1 +(I1 +I1 +I1 +tp17317 +g38 +I00 +S'u\xea\x9f\xac\x1b\xb2\xe0?' +p17318 +tp17319 +bsg252 +g260 +sg48 +(lp17320 +g0 +(g52 +g2 +Ntp17321 +Rp17322 +(dp17323 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17324 +g179 +tp17325 +Rp17326 +(I1 +(I1 +I1 +I1 +tp17327 +g38 +I00 +S'\xb4\xe1\xc0\xeavzG@' +p17328 +tp17329 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17330 +g279 +asg113 +I10550 +sg280 +I01 +sbaa(lp17331 +g401 +ag0 +(g190 +g2 +Ntp17332 +Rp17333 +(dp17334 +g194 +I01 +sg195 +(lp17335 +g0 +(g197 +g2 +Ntp17336 +Rp17337 +(dp17338 +g201 +g176 +(g177 +(I0 +tp17339 +g179 +tp17340 +Rp17341 +(I1 +(I1 +tp17342 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17343 +tp17344 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17345 +Rp17346 +(dp17347 +g201 +g176 +(g177 +(I0 +tp17348 +g179 +tp17349 +Rp17350 +(I1 +(I2 +tp17351 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17352 +tp17353 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17354 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17355 +g179 +tp17356 +Rp17357 +(I1 +(I1 +I1 +I1 +tp17358 +g38 +I00 +S'\x18\xfe\xd8]\xe5\xcd\xab?' +p17359 +tp17360 +bsg238 +g176 +(g177 +(I0 +tp17361 +g179 +tp17362 +Rp17363 +(I1 +(I1 +I1 +I1 +tp17364 +g38 +I00 +S'\xc5\xf3\x84\xe1V\xae\x0b?' +p17365 +tp17366 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17367 +g179 +tp17368 +Rp17369 +(I1 +(I1 +I1 +I1 +tp17370 +g38 +I00 +S'b\x18\xaf%\xfd%\x99?' +p17371 +tp17372 +bsg252 +g260 +sg48 +(lp17373 +g0 +(g52 +g2 +Ntp17374 +Rp17375 +(dp17376 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17377 +g179 +tp17378 +Rp17379 +(I1 +(I1 +I1 +I1 +tp17380 +g38 +I00 +S'%\x1d\x7f\xfe\xb5\xae\x01@' +p17381 +tp17382 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17383 +g454 +asg113 +I10551 +sg280 +I01 +sbaatp17384 +Rp17385 +sg337 +I00 +sg338 +Nsbaa(lp17386 +g458 +ag0 +(g459 +g2 +Ntp17387 +Rp17388 +(dp17389 +g17 +g17133 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17390 +(lp17391 +g189 +ag0 +(g190 +g2 +Ntp17392 +Rp17393 +(dp17394 +g194 +I01 +sg195 +(lp17395 +g0 +(g197 +g2 +Ntp17396 +Rp17397 +(dp17398 +g201 +g176 +(g177 +(I0 +tp17399 +g179 +tp17400 +Rp17401 +(I1 +(I1 +tp17402 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17403 +tp17404 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17405 +Rp17406 +(dp17407 +g201 +g176 +(g177 +(I0 +tp17408 +g179 +tp17409 +Rp17410 +(I1 +(I2 +tp17411 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17412 +tp17413 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp17414 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17415 +g179 +tp17416 +Rp17417 +(I1 +(I1 +I1 +I1 +tp17418 +g38 +I00 +S'\xfa\xcf\xf0\xf6\x15\x7f8@' +p17419 +tp17420 +bsg238 +g176 +(g177 +(I0 +tp17421 +g179 +tp17422 +Rp17423 +(I1 +(I1 +I1 +I1 +tp17424 +g38 +I00 +S'\xc9\x9fS>\x16\x7fS?' +p17425 +tp17426 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17427 +g179 +tp17428 +Rp17429 +(I1 +(I1 +I1 +I1 +tp17430 +g38 +I00 +S'\xe1,HK\xde\xb0\xe0?' +p17431 +tp17432 +bsg252 +g513 +sg48 +(lp17433 +g0 +(g52 +g2 +Ntp17434 +Rp17435 +(dp17436 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp17437 +g179 +tp17438 +Rp17439 +(I1 +(I1 +I1 +I1 +tp17440 +g38 +I00 +S'\x1c\x7f\xdd\x99\xb8xG@' +p17441 +tp17442 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp17443 +g527 +asg113 +I10554 +sg280 +I01 +sbaa(lp17444 +g529 +ag0 +(g190 +g2 +Ntp17445 +Rp17446 +(dp17447 +g194 +I01 +sg195 +(lp17448 +g0 +(g197 +g2 +Ntp17449 +Rp17450 +(dp17451 +g201 +g176 +(g177 +(I0 +tp17452 +g179 +tp17453 +Rp17454 +(I1 +(I1 +tp17455 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17456 +tp17457 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17458 +Rp17459 +(dp17460 +g201 +g176 +(g177 +(I0 +tp17461 +g179 +tp17462 +Rp17463 +(I1 +(I2 +tp17464 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17465 +tp17466 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17467 +Rp17468 +(dp17469 +g201 +g176 +(g177 +(I0 +tp17470 +g179 +tp17471 +Rp17472 +(I1 +(I2 +tp17473 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17474 +tp17475 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp17476 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17477 +g179 +tp17478 +Rp17479 +(I1 +(I1 +I1 +I1 +tp17480 +g38 +I00 +S'*\x87O:\x91\xb8\x0b@' +p17481 +tp17482 +bsg238 +g176 +(g177 +(I0 +tp17483 +g179 +tp17484 +Rp17485 +(I1 +(I1 +I1 +I1 +tp17486 +g38 +I00 +S'\xa3z\xa4\xc6\x19\xb6>?' +p17487 +tp17488 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17489 +g179 +tp17490 +Rp17491 +(I1 +(I1 +I1 +I1 +tp17492 +g38 +I00 +S'\x91\xd2\n\x97\x06\x1c\xc9?' +p17493 +tp17494 +bsg252 +g586 +sg48 +(lp17495 +g0 +(g52 +g2 +Ntp17496 +Rp17497 +(dp17498 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp17499 +g179 +tp17500 +Rp17501 +(I1 +(I1 +I1 +I1 +tp17502 +g38 +I00 +S'\x0e\x9c3\xa2\xb4\xa71@' +p17503 +tp17504 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp17505 +g600 +asg113 +I10555 +sg280 +I01 +sbaatp17506 +Rp17507 +sg337 +I00 +sg338 +Nsbaa(lp17508 +g604 +ag0 +(g605 +g2 +Ntp17509 +Rp17510 +(dp17511 +g17 +g17133 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17512 +(lp17513 +g611 +ag0 +(g190 +g2 +Ntp17514 +Rp17515 +(dp17516 +g194 +I01 +sg195 +(lp17517 +g0 +(g197 +g2 +Ntp17518 +Rp17519 +(dp17520 +g201 +g176 +(g177 +(I0 +tp17521 +g179 +tp17522 +Rp17523 +(I1 +(I1 +tp17524 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17525 +tp17526 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17527 +Rp17528 +(dp17529 +g201 +g176 +(g177 +(I0 +tp17530 +g179 +tp17531 +Rp17532 +(I1 +(I2 +tp17533 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17534 +tp17535 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp17536 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17537 +g179 +tp17538 +Rp17539 +(I1 +(I1 +I1 +I1 +tp17540 +g38 +I00 +S'\x9bn5\\\xde\xfe\xaa?' +p17541 +tp17542 +bsg238 +g176 +(g177 +(I0 +tp17543 +g179 +tp17544 +Rp17545 +(I1 +(I1 +I1 +I1 +tp17546 +g38 +I00 +S'X\xe9\xe1\x87\x13\xb3/?' +p17547 +tp17548 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17549 +g179 +tp17550 +Rp17551 +(I1 +(I1 +I1 +I1 +tp17552 +g38 +I00 +S'r\xeb\x82@\xb9\xac\x98?' +p17553 +tp17554 +bsg252 +g513 +sg48 +(lp17555 +g0 +(g52 +g2 +Ntp17556 +Rp17557 +(dp17558 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp17559 +g179 +tp17560 +Rp17561 +(I1 +(I1 +I1 +I1 +tp17562 +g38 +I00 +S'\x8c\r\\ArY\x01@' +p17563 +tp17564 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp17565 +g664 +asg113 +I10558 +sg280 +I01 +sbaa(lp17566 +g666 +ag0 +(g190 +g2 +Ntp17567 +Rp17568 +(dp17569 +g194 +I01 +sg195 +(lp17570 +g0 +(g197 +g2 +Ntp17571 +Rp17572 +(dp17573 +g201 +g176 +(g177 +(I0 +tp17574 +g179 +tp17575 +Rp17576 +(I1 +(I1 +tp17577 +g208 +I00 +S"3'\x00\x00\x00\x00\x00\x00" +p17578 +tp17579 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17580 +Rp17581 +(dp17582 +g201 +g176 +(g177 +(I0 +tp17583 +g179 +tp17584 +Rp17585 +(I1 +(I2 +tp17586 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17587 +tp17588 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp17589 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17590 +g179 +tp17591 +Rp17592 +(I1 +(I1 +I1 +I1 +tp17593 +g38 +I00 +S'\x9bn5\\\xde\xfe\xaa?' +p17594 +tp17595 +bsg238 +g176 +(g177 +(I0 +tp17596 +g179 +tp17597 +Rp17598 +(I1 +(I1 +I1 +I1 +tp17599 +g38 +I00 +S'X\xe9\xe1\x87\x13\xb3/?' +p17600 +tp17601 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17602 +g179 +tp17603 +Rp17604 +(I1 +(I1 +I1 +I1 +tp17605 +g38 +I00 +S'r\xeb\x82@\xb9\xac\x98?' +p17606 +tp17607 +bsg252 +g713 +sg48 +(lp17608 +g0 +(g52 +g2 +Ntp17609 +Rp17610 +(dp17611 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp17612 +g179 +tp17613 +Rp17614 +(I1 +(I1 +I1 +I1 +tp17615 +g38 +I00 +S'\x8c\r\\ArY\x01@' +p17616 +tp17617 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp17618 +g727 +asg113 +I10559 +sg280 +I01 +sbaatp17619 +Rp17620 +sg337 +I00 +sg338 +Nsbaatp17621 +Rp17622 +aa(lp17623 +I10036 +ag7 +((lp17624 +(lp17625 +g12 +ag0 +(g13 +g2 +Ntp17626 +Rp17627 +(dp17628 +g17 +g0 +(g18 +g2 +Ntp17629 +Rp17630 +(dp17631 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p17632 +sg116 +g0 +(g117 +g2 +Ntp17633 +Rp17634 +(dp17635 +g121 +(lp17636 +g0 +(g123 +g2 +Ntp17637 +Rp17638 +(dp17639 +g127 +g0 +(g128 +g2 +Ntp17640 +Rp17641 +(dp17642 +g23 +g132 +sg133 +(dp17643 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\x03@' +p17644 +tp17645 +Rp17646 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p17647 +sg113 +I2 +sg146 +(lp17648 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp17649 +Rp17650 +(dp17651 +g127 +g0 +(g128 +g2 +Ntp17652 +Rp17653 +(dp17654 +g23 +g132 +sg133 +(dp17655 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xb8\x1e\x85\xebQ\xb8\x03@' +p17656 +tp17657 +Rp17658 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p17659 +sg113 +I66 +sg146 +(lp17660 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10036 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17661 +(lp17662 +g189 +ag0 +(g190 +g2 +Ntp17663 +Rp17664 +(dp17665 +g194 +I01 +sg195 +(lp17666 +g0 +(g197 +g2 +Ntp17667 +Rp17668 +(dp17669 +g201 +g176 +(g177 +(I0 +tp17670 +g179 +tp17671 +Rp17672 +(I1 +(I1 +tp17673 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17674 +tp17675 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17676 +Rp17677 +(dp17678 +g201 +g176 +(g177 +(I0 +tp17679 +g179 +tp17680 +Rp17681 +(I1 +(I2 +tp17682 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17683 +tp17684 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17685 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17686 +g179 +tp17687 +Rp17688 +(I1 +(I1 +I1 +I1 +tp17689 +g38 +I00 +S'Nm\\\x0fqSC@' +p17690 +tp17691 +bsg238 +g176 +(g177 +(I0 +tp17692 +g179 +tp17693 +Rp17694 +(I1 +(I1 +I1 +I1 +tp17695 +g38 +I00 +S'Y\xc5\\\xb7s\x89D?' +p17696 +tp17697 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17698 +g179 +tp17699 +Rp17700 +(I1 +(I1 +I1 +I1 +tp17701 +g38 +I00 +S'Z\xdd=\x80K\xf8\xe4?' +p17702 +tp17703 +bsg252 +g260 +sg48 +(lp17704 +g0 +(g52 +g2 +Ntp17705 +Rp17706 +(dp17707 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17708 +g179 +tp17709 +Rp17710 +(I1 +(I1 +I1 +I1 +tp17711 +g38 +I00 +S'F\xffV,*}M@' +p17712 +tp17713 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17714 +g279 +asg113 +I10562 +sg280 +I01 +sbaa(lp17715 +g12 +ag0 +(g190 +g2 +Ntp17716 +Rp17717 +(dp17718 +g194 +I01 +sg195 +(lp17719 +g0 +(g197 +g2 +Ntp17720 +Rp17721 +(dp17722 +g201 +g176 +(g177 +(I0 +tp17723 +g179 +tp17724 +Rp17725 +(I1 +(I1 +tp17726 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17727 +tp17728 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17729 +Rp17730 +(dp17731 +g201 +g176 +(g177 +(I0 +tp17732 +g179 +tp17733 +Rp17734 +(I1 +(I2 +tp17735 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17736 +tp17737 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17738 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17739 +g179 +tp17740 +Rp17741 +(I1 +(I1 +I1 +I1 +tp17742 +g38 +I00 +S'U]\x1b\x93\xedW6@' +p17743 +tp17744 +bsg238 +g176 +(g177 +(I0 +tp17745 +g179 +tp17746 +Rp17747 +(I1 +(I1 +I1 +I1 +tp17748 +g38 +I00 +S'(\xd01=f\xccB?' +p17749 +tp17750 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17751 +g179 +tp17752 +Rp17753 +(I1 +(I1 +I1 +I1 +tp17754 +g38 +I00 +S'G\\y\x19\xf9\xe2\xdf?' +p17755 +tp17756 +bsg252 +g260 +sg48 +(lp17757 +g0 +(g52 +g2 +Ntp17758 +Rp17759 +(dp17760 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17761 +g179 +tp17762 +Rp17763 +(I1 +(I1 +I1 +I1 +tp17764 +g38 +I00 +S'\xe2T\xe9%\x97kF@' +p17765 +tp17766 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17767 +g334 +asg113 +I10563 +sg280 +I01 +sbaatp17768 +Rp17769 +sg337 +I00 +sg338 +Nsbaa(lp17770 +g340 +ag0 +(g341 +g2 +Ntp17771 +Rp17772 +(dp17773 +g17 +g17630 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17774 +(lp17775 +g189 +ag0 +(g190 +g2 +Ntp17776 +Rp17777 +(dp17778 +g194 +I01 +sg195 +(lp17779 +g0 +(g197 +g2 +Ntp17780 +Rp17781 +(dp17782 +g201 +g176 +(g177 +(I0 +tp17783 +g179 +tp17784 +Rp17785 +(I1 +(I1 +tp17786 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17787 +tp17788 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17789 +Rp17790 +(dp17791 +g201 +g176 +(g177 +(I0 +tp17792 +g179 +tp17793 +Rp17794 +(I1 +(I2 +tp17795 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17796 +tp17797 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17798 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17799 +g179 +tp17800 +Rp17801 +(I1 +(I1 +I1 +I1 +tp17802 +g38 +I00 +S'Nm\\\x0fqSC@' +p17803 +tp17804 +bsg238 +g176 +(g177 +(I0 +tp17805 +g179 +tp17806 +Rp17807 +(I1 +(I1 +I1 +I1 +tp17808 +g38 +I00 +S'Y\xc5\\\xb7s\x89D?' +p17809 +tp17810 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17811 +g179 +tp17812 +Rp17813 +(I1 +(I1 +I1 +I1 +tp17814 +g38 +I00 +S'Z\xdd=\x80K\xf8\xe4?' +p17815 +tp17816 +bsg252 +g260 +sg48 +(lp17817 +g0 +(g52 +g2 +Ntp17818 +Rp17819 +(dp17820 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17821 +g179 +tp17822 +Rp17823 +(I1 +(I1 +I1 +I1 +tp17824 +g38 +I00 +S'F\xffV,*}M@' +p17825 +tp17826 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17827 +g279 +asg113 +I10566 +sg280 +I01 +sbaa(lp17828 +g401 +ag0 +(g190 +g2 +Ntp17829 +Rp17830 +(dp17831 +g194 +I01 +sg195 +(lp17832 +g0 +(g197 +g2 +Ntp17833 +Rp17834 +(dp17835 +g201 +g176 +(g177 +(I0 +tp17836 +g179 +tp17837 +Rp17838 +(I1 +(I1 +tp17839 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17840 +tp17841 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17842 +Rp17843 +(dp17844 +g201 +g176 +(g177 +(I0 +tp17845 +g179 +tp17846 +Rp17847 +(I1 +(I2 +tp17848 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17849 +tp17850 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp17851 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17852 +g179 +tp17853 +Rp17854 +(I1 +(I1 +I1 +I1 +tp17855 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17856 +tp17857 +bsg238 +g176 +(g177 +(I0 +tp17858 +g179 +tp17859 +Rp17860 +(I1 +(I1 +I1 +I1 +tp17861 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17862 +tp17863 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17864 +g179 +tp17865 +Rp17866 +(I1 +(I1 +I1 +I1 +tp17867 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17868 +tp17869 +bsg252 +g260 +sg48 +(lp17870 +g0 +(g52 +g2 +Ntp17871 +Rp17872 +(dp17873 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp17874 +g179 +tp17875 +Rp17876 +(I1 +(I1 +I1 +I1 +tp17877 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p17878 +tp17879 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp17880 +g454 +asg113 +I10567 +sg280 +I01 +sbaatp17881 +Rp17882 +sg337 +I00 +sg338 +Nsbaa(lp17883 +g458 +ag0 +(g459 +g2 +Ntp17884 +Rp17885 +(dp17886 +g17 +g17630 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp17887 +(lp17888 +g189 +ag0 +(g190 +g2 +Ntp17889 +Rp17890 +(dp17891 +g194 +I01 +sg195 +(lp17892 +g0 +(g197 +g2 +Ntp17893 +Rp17894 +(dp17895 +g201 +g176 +(g177 +(I0 +tp17896 +g179 +tp17897 +Rp17898 +(I1 +(I1 +tp17899 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17900 +tp17901 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17902 +Rp17903 +(dp17904 +g201 +g176 +(g177 +(I0 +tp17905 +g179 +tp17906 +Rp17907 +(I1 +(I2 +tp17908 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17909 +tp17910 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp17911 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17912 +g179 +tp17913 +Rp17914 +(I1 +(I1 +I1 +I1 +tp17915 +g38 +I00 +S's\xb6\xc9U{OC@' +p17916 +tp17917 +bsg238 +g176 +(g177 +(I0 +tp17918 +g179 +tp17919 +Rp17920 +(I1 +(I1 +I1 +I1 +tp17921 +g38 +I00 +S'\xea\xa3\x88W\xf7\nY?' +p17922 +tp17923 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17924 +g179 +tp17925 +Rp17926 +(I1 +(I1 +I1 +I1 +tp17927 +g38 +I00 +S'(C7t\x10\xf5\xe4?' +p17928 +tp17929 +bsg252 +g513 +sg48 +(lp17930 +g0 +(g52 +g2 +Ntp17931 +Rp17932 +(dp17933 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp17934 +g179 +tp17935 +Rp17936 +(I1 +(I1 +I1 +I1 +tp17937 +g38 +I00 +S'p\xb6m#\x9fxM@' +p17938 +tp17939 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp17940 +g527 +asg113 +I10570 +sg280 +I01 +sbaa(lp17941 +g529 +ag0 +(g190 +g2 +Ntp17942 +Rp17943 +(dp17944 +g194 +I01 +sg195 +(lp17945 +g0 +(g197 +g2 +Ntp17946 +Rp17947 +(dp17948 +g201 +g176 +(g177 +(I0 +tp17949 +g179 +tp17950 +Rp17951 +(I1 +(I1 +tp17952 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p17953 +tp17954 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17955 +Rp17956 +(dp17957 +g201 +g176 +(g177 +(I0 +tp17958 +g179 +tp17959 +Rp17960 +(I1 +(I2 +tp17961 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17962 +tp17963 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp17964 +Rp17965 +(dp17966 +g201 +g176 +(g177 +(I0 +tp17967 +g179 +tp17968 +Rp17969 +(I1 +(I2 +tp17970 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p17971 +tp17972 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp17973 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp17974 +g179 +tp17975 +Rp17976 +(I1 +(I1 +I1 +I1 +tp17977 +g38 +I00 +S"\x85\xd2\x83'\x99\x016@" +p17978 +tp17979 +bsg238 +g176 +(g177 +(I0 +tp17980 +g179 +tp17981 +Rp17982 +(I1 +(I1 +I1 +I1 +tp17983 +g38 +I00 +S'\xc3\x82\x8b\xd50\x8aO?' +p17984 +tp17985 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp17986 +g179 +tp17987 +Rp17988 +(I1 +(I1 +I1 +I1 +tp17989 +g38 +I00 +S'\x14\x1d\xc9\xe5?\xa4\xdf?' +p17990 +tp17991 +bsg252 +g586 +sg48 +(lp17992 +g0 +(g52 +g2 +Ntp17993 +Rp17994 +(dp17995 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp17996 +g179 +tp17997 +Rp17998 +(I1 +(I1 +I1 +I1 +tp17999 +g38 +I00 +S'rh\x91\xed|?F@' +p18000 +tp18001 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp18002 +g600 +asg113 +I10571 +sg280 +I01 +sbaatp18003 +Rp18004 +sg337 +I00 +sg338 +Nsbaa(lp18005 +g604 +ag0 +(g605 +g2 +Ntp18006 +Rp18007 +(dp18008 +g17 +g17630 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18009 +(lp18010 +g611 +ag0 +(g190 +g2 +Ntp18011 +Rp18012 +(dp18013 +g194 +I01 +sg195 +(lp18014 +g0 +(g197 +g2 +Ntp18015 +Rp18016 +(dp18017 +g201 +g176 +(g177 +(I0 +tp18018 +g179 +tp18019 +Rp18020 +(I1 +(I1 +tp18021 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p18022 +tp18023 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18024 +Rp18025 +(dp18026 +g201 +g176 +(g177 +(I0 +tp18027 +g179 +tp18028 +Rp18029 +(I1 +(I2 +tp18030 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18031 +tp18032 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp18033 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18034 +g179 +tp18035 +Rp18036 +(I1 +(I1 +I1 +I1 +tp18037 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18038 +tp18039 +bsg238 +g176 +(g177 +(I0 +tp18040 +g179 +tp18041 +Rp18042 +(I1 +(I1 +I1 +I1 +tp18043 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18044 +tp18045 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18046 +g179 +tp18047 +Rp18048 +(I1 +(I1 +I1 +I1 +tp18049 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18050 +tp18051 +bsg252 +g513 +sg48 +(lp18052 +g0 +(g52 +g2 +Ntp18053 +Rp18054 +(dp18055 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp18056 +g179 +tp18057 +Rp18058 +(I1 +(I1 +I1 +I1 +tp18059 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18060 +tp18061 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp18062 +g664 +asg113 +I10574 +sg280 +I01 +sbaa(lp18063 +g666 +ag0 +(g190 +g2 +Ntp18064 +Rp18065 +(dp18066 +g194 +I01 +sg195 +(lp18067 +g0 +(g197 +g2 +Ntp18068 +Rp18069 +(dp18070 +g201 +g176 +(g177 +(I0 +tp18071 +g179 +tp18072 +Rp18073 +(I1 +(I1 +tp18074 +g208 +I00 +S"4'\x00\x00\x00\x00\x00\x00" +p18075 +tp18076 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18077 +Rp18078 +(dp18079 +g201 +g176 +(g177 +(I0 +tp18080 +g179 +tp18081 +Rp18082 +(I1 +(I2 +tp18083 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18084 +tp18085 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp18086 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18087 +g179 +tp18088 +Rp18089 +(I1 +(I1 +I1 +I1 +tp18090 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18091 +tp18092 +bsg238 +g176 +(g177 +(I0 +tp18093 +g179 +tp18094 +Rp18095 +(I1 +(I1 +I1 +I1 +tp18096 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18097 +tp18098 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18099 +g179 +tp18100 +Rp18101 +(I1 +(I1 +I1 +I1 +tp18102 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18103 +tp18104 +bsg252 +g713 +sg48 +(lp18105 +g0 +(g52 +g2 +Ntp18106 +Rp18107 +(dp18108 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp18109 +g179 +tp18110 +Rp18111 +(I1 +(I1 +I1 +I1 +tp18112 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18113 +tp18114 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp18115 +g727 +asg113 +I10575 +sg280 +I01 +sbaatp18116 +Rp18117 +sg337 +I00 +sg338 +Nsbaatp18118 +Rp18119 +aa(lp18120 +I10037 +ag7 +((lp18121 +(lp18122 +g12 +ag0 +(g13 +g2 +Ntp18123 +Rp18124 +(dp18125 +g17 +g0 +(g18 +g2 +Ntp18126 +Rp18127 +(dp18128 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p18129 +sg116 +g0 +(g117 +g2 +Ntp18130 +Rp18131 +(dp18132 +g121 +(lp18133 +g0 +(g123 +g2 +Ntp18134 +Rp18135 +(dp18136 +g127 +g0 +(g128 +g2 +Ntp18137 +Rp18138 +(dp18139 +g23 +g132 +sg133 +(dp18140 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xa9?' +p18141 +tp18142 +Rp18143 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p18144 +sg113 +I67 +sg146 +(lp18145 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp18146 +Rp18147 +(dp18148 +g127 +g0 +(g128 +g2 +Ntp18149 +Rp18150 +(dp18151 +g23 +g132 +sg133 +(dp18152 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p18153 +tp18154 +Rp18155 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p18156 +sg113 +I29 +sg146 +(lp18157 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10037 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18158 +(lp18159 +g189 +ag0 +(g190 +g2 +Ntp18160 +Rp18161 +(dp18162 +g194 +I01 +sg195 +(lp18163 +g0 +(g197 +g2 +Ntp18164 +Rp18165 +(dp18166 +g201 +g176 +(g177 +(I0 +tp18167 +g179 +tp18168 +Rp18169 +(I1 +(I1 +tp18170 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18171 +tp18172 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18173 +Rp18174 +(dp18175 +g201 +g176 +(g177 +(I0 +tp18176 +g179 +tp18177 +Rp18178 +(I1 +(I2 +tp18179 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18180 +tp18181 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18182 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18183 +g179 +tp18184 +Rp18185 +(I1 +(I1 +I1 +I1 +tp18186 +g38 +I00 +S'\xab\xa80s\x18\\8@' +p18187 +tp18188 +bsg238 +g176 +(g177 +(I0 +tp18189 +g179 +tp18190 +Rp18191 +(I1 +(I1 +I1 +I1 +tp18192 +g38 +I00 +S'v\x87\xbav\x98\x9cF?' +p18193 +tp18194 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18195 +g179 +tp18196 +Rp18197 +(I1 +(I1 +I1 +I1 +tp18198 +g38 +I00 +S'I\x9d\xca\x93\x95\xa5\xe0?' +p18199 +tp18200 +bsg252 +g260 +sg48 +(lp18201 +g0 +(g52 +g2 +Ntp18202 +Rp18203 +(dp18204 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18205 +g179 +tp18206 +Rp18207 +(I1 +(I1 +I1 +I1 +tp18208 +g38 +I00 +S'/\xed\xd4W\xdahG@' +p18209 +tp18210 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18211 +g279 +asg113 +I10578 +sg280 +I01 +sbaa(lp18212 +g12 +ag0 +(g190 +g2 +Ntp18213 +Rp18214 +(dp18215 +g194 +I01 +sg195 +(lp18216 +g0 +(g197 +g2 +Ntp18217 +Rp18218 +(dp18219 +g201 +g176 +(g177 +(I0 +tp18220 +g179 +tp18221 +Rp18222 +(I1 +(I1 +tp18223 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18224 +tp18225 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18226 +Rp18227 +(dp18228 +g201 +g176 +(g177 +(I0 +tp18229 +g179 +tp18230 +Rp18231 +(I1 +(I2 +tp18232 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18233 +tp18234 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18235 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18236 +g179 +tp18237 +Rp18238 +(I1 +(I1 +I1 +I1 +tp18239 +g38 +I00 +S'\x82\x1b\xfd\\S\xfe\x0e@' +p18240 +tp18241 +bsg238 +g176 +(g177 +(I0 +tp18242 +g179 +tp18243 +Rp18244 +(I1 +(I1 +I1 +I1 +tp18245 +g38 +I00 +S'\xf4r7(w\x133?' +p18246 +tp18247 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18248 +g179 +tp18249 +Rp18250 +(I1 +(I1 +I1 +I1 +tp18251 +g38 +I00 +S'\xb2O\xc1\x0b\xfe\x8d\xca?' +p18252 +tp18253 +bsg252 +g260 +sg48 +(lp18254 +g0 +(g52 +g2 +Ntp18255 +Rp18256 +(dp18257 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18258 +g179 +tp18259 +Rp18260 +(I1 +(I1 +I1 +I1 +tp18261 +g38 +I00 +S'\t\xecC\xa0\xd6\xab2@' +p18262 +tp18263 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18264 +g334 +asg113 +I10579 +sg280 +I01 +sbaatp18265 +Rp18266 +sg337 +I00 +sg338 +Nsbaa(lp18267 +g340 +ag0 +(g341 +g2 +Ntp18268 +Rp18269 +(dp18270 +g17 +g18127 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18271 +(lp18272 +g189 +ag0 +(g190 +g2 +Ntp18273 +Rp18274 +(dp18275 +g194 +I01 +sg195 +(lp18276 +g0 +(g197 +g2 +Ntp18277 +Rp18278 +(dp18279 +g201 +g176 +(g177 +(I0 +tp18280 +g179 +tp18281 +Rp18282 +(I1 +(I1 +tp18283 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18284 +tp18285 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18286 +Rp18287 +(dp18288 +g201 +g176 +(g177 +(I0 +tp18289 +g179 +tp18290 +Rp18291 +(I1 +(I2 +tp18292 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18293 +tp18294 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18295 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18296 +g179 +tp18297 +Rp18298 +(I1 +(I1 +I1 +I1 +tp18299 +g38 +I00 +S'\xab\xa80s\x18\\8@' +p18300 +tp18301 +bsg238 +g176 +(g177 +(I0 +tp18302 +g179 +tp18303 +Rp18304 +(I1 +(I1 +I1 +I1 +tp18305 +g38 +I00 +S'v\x87\xbav\x98\x9cF?' +p18306 +tp18307 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18308 +g179 +tp18309 +Rp18310 +(I1 +(I1 +I1 +I1 +tp18311 +g38 +I00 +S'I\x9d\xca\x93\x95\xa5\xe0?' +p18312 +tp18313 +bsg252 +g260 +sg48 +(lp18314 +g0 +(g52 +g2 +Ntp18315 +Rp18316 +(dp18317 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18318 +g179 +tp18319 +Rp18320 +(I1 +(I1 +I1 +I1 +tp18321 +g38 +I00 +S'/\xed\xd4W\xdahG@' +p18322 +tp18323 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18324 +g279 +asg113 +I10582 +sg280 +I01 +sbaa(lp18325 +g401 +ag0 +(g190 +g2 +Ntp18326 +Rp18327 +(dp18328 +g194 +I01 +sg195 +(lp18329 +g0 +(g197 +g2 +Ntp18330 +Rp18331 +(dp18332 +g201 +g176 +(g177 +(I0 +tp18333 +g179 +tp18334 +Rp18335 +(I1 +(I1 +tp18336 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18337 +tp18338 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18339 +Rp18340 +(dp18341 +g201 +g176 +(g177 +(I0 +tp18342 +g179 +tp18343 +Rp18344 +(I1 +(I2 +tp18345 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18346 +tp18347 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18348 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18349 +g179 +tp18350 +Rp18351 +(I1 +(I1 +I1 +I1 +tp18352 +g38 +I00 +S'\x8a1\xe1\xfdv6\x9e?' +p18353 +tp18354 +bsg238 +g176 +(g177 +(I0 +tp18355 +g179 +tp18356 +Rp18357 +(I1 +(I1 +I1 +I1 +tp18358 +g38 +I00 +S'\xc9\xff\xae\x18\x8a\x9a\n?' +p18359 +tp18360 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18361 +g179 +tp18362 +Rp18363 +(I1 +(I1 +I1 +I1 +tp18364 +g38 +I00 +S'\x88\x05XC\xbc\x88\x92?' +p18365 +tp18366 +bsg252 +g260 +sg48 +(lp18367 +g0 +(g52 +g2 +Ntp18368 +Rp18369 +(dp18370 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18371 +g179 +tp18372 +Rp18373 +(I1 +(I1 +I1 +I1 +tp18374 +g38 +I00 +S'\xc7\xc7\xb3\xbeH\x10\xfa?' +p18375 +tp18376 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18377 +g454 +asg113 +I10583 +sg280 +I01 +sbaatp18378 +Rp18379 +sg337 +I00 +sg338 +Nsbaa(lp18380 +g458 +ag0 +(g459 +g2 +Ntp18381 +Rp18382 +(dp18383 +g17 +g18127 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18384 +(lp18385 +g189 +ag0 +(g190 +g2 +Ntp18386 +Rp18387 +(dp18388 +g194 +I01 +sg195 +(lp18389 +g0 +(g197 +g2 +Ntp18390 +Rp18391 +(dp18392 +g201 +g176 +(g177 +(I0 +tp18393 +g179 +tp18394 +Rp18395 +(I1 +(I1 +tp18396 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18397 +tp18398 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18399 +Rp18400 +(dp18401 +g201 +g176 +(g177 +(I0 +tp18402 +g179 +tp18403 +Rp18404 +(I1 +(I2 +tp18405 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18406 +tp18407 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp18408 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18409 +g179 +tp18410 +Rp18411 +(I1 +(I1 +I1 +I1 +tp18412 +g38 +I00 +S'F\xdc\x95\x96\xefR8@' +p18413 +tp18414 +bsg238 +g176 +(g177 +(I0 +tp18415 +g179 +tp18416 +Rp18417 +(I1 +(I1 +I1 +I1 +tp18418 +g38 +I00 +S'l\x07\n\xcf\xc4\x83W?' +p18419 +tp18420 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18421 +g179 +tp18422 +Rp18423 +(I1 +(I1 +I1 +I1 +tp18424 +g38 +I00 +S"*'\xcb\x98W\xa1\xe0?" +p18425 +tp18426 +bsg252 +g513 +sg48 +(lp18427 +g0 +(g52 +g2 +Ntp18428 +Rp18429 +(dp18430 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp18431 +g179 +tp18432 +Rp18433 +(I1 +(I1 +I1 +I1 +tp18434 +g38 +I00 +S'\x13\xaf\xdd.\xe3bG@' +p18435 +tp18436 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp18437 +g527 +asg113 +I10586 +sg280 +I01 +sbaa(lp18438 +g529 +ag0 +(g190 +g2 +Ntp18439 +Rp18440 +(dp18441 +g194 +I01 +sg195 +(lp18442 +g0 +(g197 +g2 +Ntp18443 +Rp18444 +(dp18445 +g201 +g176 +(g177 +(I0 +tp18446 +g179 +tp18447 +Rp18448 +(I1 +(I1 +tp18449 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18450 +tp18451 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18452 +Rp18453 +(dp18454 +g201 +g176 +(g177 +(I0 +tp18455 +g179 +tp18456 +Rp18457 +(I1 +(I2 +tp18458 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18459 +tp18460 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18461 +Rp18462 +(dp18463 +g201 +g176 +(g177 +(I0 +tp18464 +g179 +tp18465 +Rp18466 +(I1 +(I2 +tp18467 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18468 +tp18469 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp18470 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18471 +g179 +tp18472 +Rp18473 +(I1 +(I1 +I1 +I1 +tp18474 +g38 +I00 +S'\xc9P\x88_5G\x0b@' +p18475 +tp18476 +bsg238 +g176 +(g177 +(I0 +tp18477 +g179 +tp18478 +Rp18479 +(I1 +(I1 +I1 +I1 +tp18480 +g38 +I00 +S"\xdb\xef\xe8'>3A?" +p18481 +tp18482 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18483 +g179 +tp18484 +Rp18485 +(I1 +(I1 +I1 +I1 +tp18486 +g38 +I00 +S'\xc9\x1eR\xaa\x08\xe8\xc8?' +p18487 +tp18488 +bsg252 +g586 +sg48 +(lp18489 +g0 +(g52 +g2 +Ntp18490 +Rp18491 +(dp18492 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp18493 +g179 +tp18494 +Rp18495 +(I1 +(I1 +I1 +I1 +tp18496 +g38 +I00 +S'\xa5\xbd\xc1\x17&\x831@' +p18497 +tp18498 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp18499 +g600 +asg113 +I10587 +sg280 +I01 +sbaatp18500 +Rp18501 +sg337 +I00 +sg338 +Nsbaa(lp18502 +g604 +ag0 +(g605 +g2 +Ntp18503 +Rp18504 +(dp18505 +g17 +g18127 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18506 +(lp18507 +g611 +ag0 +(g190 +g2 +Ntp18508 +Rp18509 +(dp18510 +g194 +I01 +sg195 +(lp18511 +g0 +(g197 +g2 +Ntp18512 +Rp18513 +(dp18514 +g201 +g176 +(g177 +(I0 +tp18515 +g179 +tp18516 +Rp18517 +(I1 +(I1 +tp18518 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18519 +tp18520 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18521 +Rp18522 +(dp18523 +g201 +g176 +(g177 +(I0 +tp18524 +g179 +tp18525 +Rp18526 +(I1 +(I2 +tp18527 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18528 +tp18529 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp18530 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18531 +g179 +tp18532 +Rp18533 +(I1 +(I1 +I1 +I1 +tp18534 +g38 +I00 +S'o\x0b6\xa1\xd1\x07\x9f?' +p18535 +tp18536 +bsg238 +g176 +(g177 +(I0 +tp18537 +g179 +tp18538 +Rp18539 +(I1 +(I1 +I1 +I1 +tp18540 +g38 +I00 +S'^7\x86\xcd\xfbX%?' +p18541 +tp18542 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18543 +g179 +tp18544 +Rp18545 +(I1 +(I1 +I1 +I1 +tp18546 +g38 +I00 +S'\xaf\xa2\xf3(O\xb9\x92?' +p18547 +tp18548 +bsg252 +g513 +sg48 +(lp18549 +g0 +(g52 +g2 +Ntp18550 +Rp18551 +(dp18552 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp18553 +g179 +tp18554 +Rp18555 +(I1 +(I1 +I1 +I1 +tp18556 +g38 +I00 +S'\xc6\x9c\x96Q\x97T\xfa?' +p18557 +tp18558 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp18559 +g664 +asg113 +I10590 +sg280 +I01 +sbaa(lp18560 +g666 +ag0 +(g190 +g2 +Ntp18561 +Rp18562 +(dp18563 +g194 +I01 +sg195 +(lp18564 +g0 +(g197 +g2 +Ntp18565 +Rp18566 +(dp18567 +g201 +g176 +(g177 +(I0 +tp18568 +g179 +tp18569 +Rp18570 +(I1 +(I1 +tp18571 +g208 +I00 +S"5'\x00\x00\x00\x00\x00\x00" +p18572 +tp18573 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18574 +Rp18575 +(dp18576 +g201 +g176 +(g177 +(I0 +tp18577 +g179 +tp18578 +Rp18579 +(I1 +(I2 +tp18580 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18581 +tp18582 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp18583 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18584 +g179 +tp18585 +Rp18586 +(I1 +(I1 +I1 +I1 +tp18587 +g38 +I00 +S'o\x0b6\xa1\xd1\x07\x9f?' +p18588 +tp18589 +bsg238 +g176 +(g177 +(I0 +tp18590 +g179 +tp18591 +Rp18592 +(I1 +(I1 +I1 +I1 +tp18593 +g38 +I00 +S'\xd56\x86\xcd\xfbX%?' +p18594 +tp18595 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18596 +g179 +tp18597 +Rp18598 +(I1 +(I1 +I1 +I1 +tp18599 +g38 +I00 +S'\xb0\xa2\xf3(O\xb9\x92?' +p18600 +tp18601 +bsg252 +g713 +sg48 +(lp18602 +g0 +(g52 +g2 +Ntp18603 +Rp18604 +(dp18605 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp18606 +g179 +tp18607 +Rp18608 +(I1 +(I1 +I1 +I1 +tp18609 +g38 +I00 +S'\xc7\x9c\x96Q\x97T\xfa?' +p18610 +tp18611 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp18612 +g727 +asg113 +I10591 +sg280 +I01 +sbaatp18613 +Rp18614 +sg337 +I00 +sg338 +Nsbaatp18615 +Rp18616 +aa(lp18617 +I10038 +ag7 +((lp18618 +(lp18619 +g12 +ag0 +(g13 +g2 +Ntp18620 +Rp18621 +(dp18622 +g17 +g0 +(g18 +g2 +Ntp18623 +Rp18624 +(dp18625 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p18626 +sg116 +g0 +(g117 +g2 +Ntp18627 +Rp18628 +(dp18629 +g121 +(lp18630 +g0 +(g123 +g2 +Ntp18631 +Rp18632 +(dp18633 +g127 +g0 +(g128 +g2 +Ntp18634 +Rp18635 +(dp18636 +g23 +g132 +sg133 +(dp18637 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xf7?' +p18638 +tp18639 +Rp18640 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p18641 +sg113 +I68 +sg146 +(lp18642 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp18643 +Rp18644 +(dp18645 +g127 +g8279 +sg148 +g162 +sbasbsg163 +Nsg113 +I10038 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18646 +(lp18647 +g189 +ag0 +(g190 +g2 +Ntp18648 +Rp18649 +(dp18650 +g194 +I01 +sg195 +(lp18651 +g0 +(g197 +g2 +Ntp18652 +Rp18653 +(dp18654 +g201 +g176 +(g177 +(I0 +tp18655 +g179 +tp18656 +Rp18657 +(I1 +(I1 +tp18658 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18659 +tp18660 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18661 +Rp18662 +(dp18663 +g201 +g176 +(g177 +(I0 +tp18664 +g179 +tp18665 +Rp18666 +(I1 +(I2 +tp18667 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18668 +tp18669 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18670 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18671 +g179 +tp18672 +Rp18673 +(I1 +(I1 +I1 +I1 +tp18674 +g38 +I00 +S'\xcfN\xfe\xa9\\\x948@' +p18675 +tp18676 +bsg238 +g176 +(g177 +(I0 +tp18677 +g179 +tp18678 +Rp18679 +(I1 +(I1 +I1 +I1 +tp18680 +g38 +I00 +S'O\xc0\xc5\xd4\xc3YA?' +p18681 +tp18682 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18683 +g179 +tp18684 +Rp18685 +(I1 +(I1 +I1 +I1 +tp18686 +g38 +I00 +S'\xda\xc6\xff\xfd\xe7\xb8\xe0?' +p18687 +tp18688 +bsg252 +g260 +sg48 +(lp18689 +g0 +(g52 +g2 +Ntp18690 +Rp18691 +(dp18692 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18693 +g179 +tp18694 +Rp18695 +(I1 +(I1 +I1 +I1 +tp18696 +g38 +I00 +S'\xa2\xaf/=\x06\x84G@' +p18697 +tp18698 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18699 +g279 +asg113 +I10594 +sg280 +I01 +sbaa(lp18700 +g12 +ag0 +(g190 +g2 +Ntp18701 +Rp18702 +(dp18703 +g194 +I01 +sg195 +(lp18704 +g0 +(g197 +g2 +Ntp18705 +Rp18706 +(dp18707 +g201 +g176 +(g177 +(I0 +tp18708 +g179 +tp18709 +Rp18710 +(I1 +(I1 +tp18711 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18712 +tp18713 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18714 +Rp18715 +(dp18716 +g201 +g176 +(g177 +(I0 +tp18717 +g179 +tp18718 +Rp18719 +(I1 +(I2 +tp18720 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18721 +tp18722 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18723 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18724 +g179 +tp18725 +Rp18726 +(I1 +(I1 +I1 +I1 +tp18727 +g38 +I00 +S'\x8d\x8d\xb8\xef\xd0\x9e\x10@' +p18728 +tp18729 +bsg238 +g176 +(g177 +(I0 +tp18730 +g179 +tp18731 +Rp18732 +(I1 +(I1 +I1 +I1 +tp18733 +g38 +I00 +S'l\x85<8\x83\x190?' +p18734 +tp18735 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18736 +g179 +tp18737 +Rp18738 +(I1 +(I1 +I1 +I1 +tp18739 +g38 +I00 +S'?k\x9a\xe3W\x80\xcb?' +p18740 +tp18741 +bsg252 +g260 +sg48 +(lp18742 +g0 +(g52 +g2 +Ntp18743 +Rp18744 +(dp18745 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18746 +g179 +tp18747 +Rp18748 +(I1 +(I1 +I1 +I1 +tp18749 +g38 +I00 +S'h\x93\x08\xcc=V3@' +p18750 +tp18751 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18752 +g334 +asg113 +I10595 +sg280 +I01 +sbaatp18753 +Rp18754 +sg337 +I00 +sg338 +Nsbaa(lp18755 +g340 +ag0 +(g341 +g2 +Ntp18756 +Rp18757 +(dp18758 +g17 +g18624 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18759 +(lp18760 +g189 +ag0 +(g190 +g2 +Ntp18761 +Rp18762 +(dp18763 +g194 +I01 +sg195 +(lp18764 +g0 +(g197 +g2 +Ntp18765 +Rp18766 +(dp18767 +g201 +g176 +(g177 +(I0 +tp18768 +g179 +tp18769 +Rp18770 +(I1 +(I1 +tp18771 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18772 +tp18773 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18774 +Rp18775 +(dp18776 +g201 +g176 +(g177 +(I0 +tp18777 +g179 +tp18778 +Rp18779 +(I1 +(I2 +tp18780 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18781 +tp18782 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18783 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18784 +g179 +tp18785 +Rp18786 +(I1 +(I1 +I1 +I1 +tp18787 +g38 +I00 +S'\xcfN\xfe\xa9\\\x948@' +p18788 +tp18789 +bsg238 +g176 +(g177 +(I0 +tp18790 +g179 +tp18791 +Rp18792 +(I1 +(I1 +I1 +I1 +tp18793 +g38 +I00 +S'O\xc0\xc5\xd4\xc3YA?' +p18794 +tp18795 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18796 +g179 +tp18797 +Rp18798 +(I1 +(I1 +I1 +I1 +tp18799 +g38 +I00 +S'\xda\xc6\xff\xfd\xe7\xb8\xe0?' +p18800 +tp18801 +bsg252 +g260 +sg48 +(lp18802 +g0 +(g52 +g2 +Ntp18803 +Rp18804 +(dp18805 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18806 +g179 +tp18807 +Rp18808 +(I1 +(I1 +I1 +I1 +tp18809 +g38 +I00 +S'\xa2\xaf/=\x06\x84G@' +p18810 +tp18811 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18812 +g279 +asg113 +I10598 +sg280 +I01 +sbaa(lp18813 +g401 +ag0 +(g190 +g2 +Ntp18814 +Rp18815 +(dp18816 +g194 +I01 +sg195 +(lp18817 +g0 +(g197 +g2 +Ntp18818 +Rp18819 +(dp18820 +g201 +g176 +(g177 +(I0 +tp18821 +g179 +tp18822 +Rp18823 +(I1 +(I1 +tp18824 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18825 +tp18826 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18827 +Rp18828 +(dp18829 +g201 +g176 +(g177 +(I0 +tp18830 +g179 +tp18831 +Rp18832 +(I1 +(I2 +tp18833 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18834 +tp18835 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp18836 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18837 +g179 +tp18838 +Rp18839 +(I1 +(I1 +I1 +I1 +tp18840 +g38 +I00 +S'\xc4\xbf\xac\xc5\xbe\\\xb0?' +p18841 +tp18842 +bsg238 +g176 +(g177 +(I0 +tp18843 +g179 +tp18844 +Rp18845 +(I1 +(I1 +I1 +I1 +tp18846 +g38 +I00 +S'\xfd\xf3\x0b\xbd\xfc%\x0e?' +p18847 +tp18848 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18849 +g179 +tp18850 +Rp18851 +(I1 +(I1 +I1 +I1 +tp18852 +g38 +I00 +S'\xb7\xb0\x15\xd9lH\x9b?' +p18853 +tp18854 +bsg252 +g260 +sg48 +(lp18855 +g0 +(g52 +g2 +Ntp18856 +Rp18857 +(dp18858 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp18859 +g179 +tp18860 +Rp18861 +(I1 +(I1 +I1 +I1 +tp18862 +g38 +I00 +S'A@\xa3\x88\xec.\x03@' +p18863 +tp18864 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp18865 +g454 +asg113 +I10599 +sg280 +I01 +sbaatp18866 +Rp18867 +sg337 +I00 +sg338 +Nsbaa(lp18868 +g458 +ag0 +(g459 +g2 +Ntp18869 +Rp18870 +(dp18871 +g17 +g18624 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18872 +(lp18873 +g189 +ag0 +(g190 +g2 +Ntp18874 +Rp18875 +(dp18876 +g194 +I01 +sg195 +(lp18877 +g0 +(g197 +g2 +Ntp18878 +Rp18879 +(dp18880 +g201 +g176 +(g177 +(I0 +tp18881 +g179 +tp18882 +Rp18883 +(I1 +(I1 +tp18884 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18885 +tp18886 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18887 +Rp18888 +(dp18889 +g201 +g176 +(g177 +(I0 +tp18890 +g179 +tp18891 +Rp18892 +(I1 +(I2 +tp18893 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18894 +tp18895 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp18896 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18897 +g179 +tp18898 +Rp18899 +(I1 +(I1 +I1 +I1 +tp18900 +g38 +I00 +S'\x9d\x19H\xfb;\xd38@' +p18901 +tp18902 +bsg238 +g176 +(g177 +(I0 +tp18903 +g179 +tp18904 +Rp18905 +(I1 +(I1 +I1 +I1 +tp18906 +g38 +I00 +S'0\xbb\xc2\xc1\x1c\xbfW?' +p18907 +tp18908 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18909 +g179 +tp18910 +Rp18911 +(I1 +(I1 +I1 +I1 +tp18912 +g38 +I00 +S'\xe2\xec\xb6u\xfa\xcc\xe0?' +p18913 +tp18914 +bsg252 +g513 +sg48 +(lp18915 +g0 +(g52 +g2 +Ntp18916 +Rp18917 +(dp18918 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp18919 +g179 +tp18920 +Rp18921 +(I1 +(I1 +I1 +I1 +tp18922 +g38 +I00 +S'\x1e=\x895@\xa0G@' +p18923 +tp18924 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp18925 +g527 +asg113 +I10602 +sg280 +I01 +sbaa(lp18926 +g529 +ag0 +(g190 +g2 +Ntp18927 +Rp18928 +(dp18929 +g194 +I01 +sg195 +(lp18930 +g0 +(g197 +g2 +Ntp18931 +Rp18932 +(dp18933 +g201 +g176 +(g177 +(I0 +tp18934 +g179 +tp18935 +Rp18936 +(I1 +(I1 +tp18937 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p18938 +tp18939 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18940 +Rp18941 +(dp18942 +g201 +g176 +(g177 +(I0 +tp18943 +g179 +tp18944 +Rp18945 +(I1 +(I2 +tp18946 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18947 +tp18948 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp18949 +Rp18950 +(dp18951 +g201 +g176 +(g177 +(I0 +tp18952 +g179 +tp18953 +Rp18954 +(I1 +(I2 +tp18955 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p18956 +tp18957 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp18958 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp18959 +g179 +tp18960 +Rp18961 +(I1 +(I1 +I1 +I1 +tp18962 +g38 +I00 +S"\xe9\xe0\xd3{\xae'\x0c@" +p18963 +tp18964 +bsg238 +g176 +(g177 +(I0 +tp18965 +g179 +tp18966 +Rp18967 +(I1 +(I1 +I1 +I1 +tp18968 +g38 +I00 +S'p\x84D|\xfc\x87A?' +p18969 +tp18970 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp18971 +g179 +tp18972 +Rp18973 +(I1 +(I1 +I1 +I1 +tp18974 +g38 +I00 +S'l\xc2\xd0\xfd\xafM\xc9?' +p18975 +tp18976 +bsg252 +g586 +sg48 +(lp18977 +g0 +(g52 +g2 +Ntp18978 +Rp18979 +(dp18980 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp18981 +g179 +tp18982 +Rp18983 +(I1 +(I1 +I1 +I1 +tp18984 +g38 +I00 +S'\xb4\xc8v\xbe\x9f\xca1@' +p18985 +tp18986 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp18987 +g600 +asg113 +I10603 +sg280 +I01 +sbaatp18988 +Rp18989 +sg337 +I00 +sg338 +Nsbaa(lp18990 +g604 +ag0 +(g605 +g2 +Ntp18991 +Rp18992 +(dp18993 +g17 +g18624 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp18994 +(lp18995 +g611 +ag0 +(g190 +g2 +Ntp18996 +Rp18997 +(dp18998 +g194 +I01 +sg195 +(lp18999 +g0 +(g197 +g2 +Ntp19000 +Rp19001 +(dp19002 +g201 +g176 +(g177 +(I0 +tp19003 +g179 +tp19004 +Rp19005 +(I1 +(I1 +tp19006 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p19007 +tp19008 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19009 +Rp19010 +(dp19011 +g201 +g176 +(g177 +(I0 +tp19012 +g179 +tp19013 +Rp19014 +(I1 +(I2 +tp19015 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19016 +tp19017 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp19018 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19019 +g179 +tp19020 +Rp19021 +(I1 +(I1 +I1 +I1 +tp19022 +g38 +I00 +S'\xf3a\x8c\x95\x1a!\xb0?' +p19023 +tp19024 +bsg238 +g176 +(g177 +(I0 +tp19025 +g179 +tp19026 +Rp19027 +(I1 +(I1 +I1 +I1 +tp19028 +g38 +I00 +S'\\KI\xedyz-?' +p19029 +tp19030 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19031 +g179 +tp19032 +Rp19033 +(I1 +(I1 +I1 +I1 +tp19034 +g38 +I00 +S'\xd0\xf7!\xa1\x9f\x01\x9b?' +p19035 +tp19036 +bsg252 +g513 +sg48 +(lp19037 +g0 +(g52 +g2 +Ntp19038 +Rp19039 +(dp19040 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp19041 +g179 +tp19042 +Rp19043 +(I1 +(I1 +I1 +I1 +tp19044 +g38 +I00 +S'>\xe2K=$\xfd\x02@' +p19045 +tp19046 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp19047 +g664 +asg113 +I10606 +sg280 +I01 +sbaa(lp19048 +g666 +ag0 +(g190 +g2 +Ntp19049 +Rp19050 +(dp19051 +g194 +I01 +sg195 +(lp19052 +g0 +(g197 +g2 +Ntp19053 +Rp19054 +(dp19055 +g201 +g176 +(g177 +(I0 +tp19056 +g179 +tp19057 +Rp19058 +(I1 +(I1 +tp19059 +g208 +I00 +S"6'\x00\x00\x00\x00\x00\x00" +p19060 +tp19061 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19062 +Rp19063 +(dp19064 +g201 +g176 +(g177 +(I0 +tp19065 +g179 +tp19066 +Rp19067 +(I1 +(I2 +tp19068 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19069 +tp19070 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp19071 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19072 +g179 +tp19073 +Rp19074 +(I1 +(I1 +I1 +I1 +tp19075 +g38 +I00 +S'\xf2a\x8c\x95\x1a!\xb0?' +p19076 +tp19077 +bsg238 +g176 +(g177 +(I0 +tp19078 +g179 +tp19079 +Rp19080 +(I1 +(I1 +I1 +I1 +tp19081 +g38 +I00 +S'\x94JI\xedyz-?' +p19082 +tp19083 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19084 +g179 +tp19085 +Rp19086 +(I1 +(I1 +I1 +I1 +tp19087 +g38 +I00 +S'\xd0\xf7!\xa1\x9f\x01\x9b?' +p19088 +tp19089 +bsg252 +g713 +sg48 +(lp19090 +g0 +(g52 +g2 +Ntp19091 +Rp19092 +(dp19093 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp19094 +g179 +tp19095 +Rp19096 +(I1 +(I1 +I1 +I1 +tp19097 +g38 +I00 +S'>\xe2K=$\xfd\x02@' +p19098 +tp19099 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp19100 +g727 +asg113 +I10607 +sg280 +I01 +sbaatp19101 +Rp19102 +sg337 +I00 +sg338 +Nsbaatp19103 +Rp19104 +aa(lp19105 +I10039 +ag7 +((lp19106 +(lp19107 +g12 +ag0 +(g13 +g2 +Ntp19108 +Rp19109 +(dp19110 +g17 +g0 +(g18 +g2 +Ntp19111 +Rp19112 +(dp19113 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p19114 +sg116 +g0 +(g117 +g2 +Ntp19115 +Rp19116 +(dp19117 +g121 +(lp19118 +g0 +(g123 +g2 +Ntp19119 +Rp19120 +(dp19121 +g127 +g0 +(g128 +g2 +Ntp19122 +Rp19123 +(dp19124 +g23 +g132 +sg133 +(dp19125 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xec?' +p19126 +tp19127 +Rp19128 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p19129 +sg113 +I69 +sg146 +(lp19130 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp19131 +Rp19132 +(dp19133 +g127 +g5336 +sg148 +g149 +sbasbsg163 +Nsg113 +I10039 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19134 +(lp19135 +g189 +ag0 +(g190 +g2 +Ntp19136 +Rp19137 +(dp19138 +g194 +I01 +sg195 +(lp19139 +g0 +(g197 +g2 +Ntp19140 +Rp19141 +(dp19142 +g201 +g176 +(g177 +(I0 +tp19143 +g179 +tp19144 +Rp19145 +(I1 +(I1 +tp19146 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19147 +tp19148 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19149 +Rp19150 +(dp19151 +g201 +g176 +(g177 +(I0 +tp19152 +g179 +tp19153 +Rp19154 +(I1 +(I2 +tp19155 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19156 +tp19157 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19158 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19159 +g179 +tp19160 +Rp19161 +(I1 +(I1 +I1 +I1 +tp19162 +g38 +I00 +S'\x02S!oW}8@' +p19163 +tp19164 +bsg238 +g176 +(g177 +(I0 +tp19165 +g179 +tp19166 +Rp19167 +(I1 +(I1 +I1 +I1 +tp19168 +g38 +I00 +S'E\xee\xfc\x86\x7f\xeeB?' +p19169 +tp19170 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19171 +g179 +tp19172 +Rp19173 +(I1 +(I1 +I1 +I1 +tp19174 +g38 +I00 +S'\x99\x1dr\xbb\x07\xb1\xe0?' +p19175 +tp19176 +bsg252 +g260 +sg48 +(lp19177 +g0 +(g52 +g2 +Ntp19178 +Rp19179 +(dp19180 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19181 +g179 +tp19182 +Rp19183 +(I1 +(I1 +I1 +I1 +tp19184 +g38 +I00 +S'\x9fy\x98\xdf\xf2xG@' +p19185 +tp19186 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19187 +g279 +asg113 +I10610 +sg280 +I01 +sbaa(lp19188 +g12 +ag0 +(g190 +g2 +Ntp19189 +Rp19190 +(dp19191 +g194 +I01 +sg195 +(lp19192 +g0 +(g197 +g2 +Ntp19193 +Rp19194 +(dp19195 +g201 +g176 +(g177 +(I0 +tp19196 +g179 +tp19197 +Rp19198 +(I1 +(I1 +tp19199 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19200 +tp19201 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19202 +Rp19203 +(dp19204 +g201 +g176 +(g177 +(I0 +tp19205 +g179 +tp19206 +Rp19207 +(I1 +(I2 +tp19208 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19209 +tp19210 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19211 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19212 +g179 +tp19213 +Rp19214 +(I1 +(I1 +I1 +I1 +tp19215 +g38 +I00 +S'\x9a\x8ab\x9c\x8f\xd3\x0f@' +p19216 +tp19217 +bsg238 +g176 +(g177 +(I0 +tp19218 +g179 +tp19219 +Rp19220 +(I1 +(I1 +I1 +I1 +tp19221 +g38 +I00 +S'\xab\xac\xb7k\xb3b0?' +p19222 +tp19223 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19224 +g179 +tp19225 +Rp19226 +(I1 +(I1 +I1 +I1 +tp19227 +g38 +I00 +S'_\xf32\x9f\xe7\xe8\xca?' +p19228 +tp19229 +bsg252 +g260 +sg48 +(lp19230 +g0 +(g52 +g2 +Ntp19231 +Rp19232 +(dp19233 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19234 +g179 +tp19235 +Rp19236 +(I1 +(I1 +I1 +I1 +tp19237 +g38 +I00 +S'\x1f\xd3\xef\xdb\xc2\xeb2@' +p19238 +tp19239 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19240 +g334 +asg113 +I10611 +sg280 +I01 +sbaatp19241 +Rp19242 +sg337 +I00 +sg338 +Nsbaa(lp19243 +g340 +ag0 +(g341 +g2 +Ntp19244 +Rp19245 +(dp19246 +g17 +g19112 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19247 +(lp19248 +g189 +ag0 +(g190 +g2 +Ntp19249 +Rp19250 +(dp19251 +g194 +I01 +sg195 +(lp19252 +g0 +(g197 +g2 +Ntp19253 +Rp19254 +(dp19255 +g201 +g176 +(g177 +(I0 +tp19256 +g179 +tp19257 +Rp19258 +(I1 +(I1 +tp19259 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19260 +tp19261 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19262 +Rp19263 +(dp19264 +g201 +g176 +(g177 +(I0 +tp19265 +g179 +tp19266 +Rp19267 +(I1 +(I2 +tp19268 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19269 +tp19270 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19271 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19272 +g179 +tp19273 +Rp19274 +(I1 +(I1 +I1 +I1 +tp19275 +g38 +I00 +S'\x02S!oW}8@' +p19276 +tp19277 +bsg238 +g176 +(g177 +(I0 +tp19278 +g179 +tp19279 +Rp19280 +(I1 +(I1 +I1 +I1 +tp19281 +g38 +I00 +S'E\xee\xfc\x86\x7f\xeeB?' +p19282 +tp19283 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19284 +g179 +tp19285 +Rp19286 +(I1 +(I1 +I1 +I1 +tp19287 +g38 +I00 +S'\x99\x1dr\xbb\x07\xb1\xe0?' +p19288 +tp19289 +bsg252 +g260 +sg48 +(lp19290 +g0 +(g52 +g2 +Ntp19291 +Rp19292 +(dp19293 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19294 +g179 +tp19295 +Rp19296 +(I1 +(I1 +I1 +I1 +tp19297 +g38 +I00 +S'\x9fy\x98\xdf\xf2xG@' +p19298 +tp19299 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19300 +g279 +asg113 +I10614 +sg280 +I01 +sbaa(lp19301 +g401 +ag0 +(g190 +g2 +Ntp19302 +Rp19303 +(dp19304 +g194 +I01 +sg195 +(lp19305 +g0 +(g197 +g2 +Ntp19306 +Rp19307 +(dp19308 +g201 +g176 +(g177 +(I0 +tp19309 +g179 +tp19310 +Rp19311 +(I1 +(I1 +tp19312 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19313 +tp19314 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19315 +Rp19316 +(dp19317 +g201 +g176 +(g177 +(I0 +tp19318 +g179 +tp19319 +Rp19320 +(I1 +(I2 +tp19321 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19322 +tp19323 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19324 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19325 +g179 +tp19326 +Rp19327 +(I1 +(I1 +I1 +I1 +tp19328 +g38 +I00 +S'\xca\xc9^\xa7!\xc4\xa4?' +p19329 +tp19330 +bsg238 +g176 +(g177 +(I0 +tp19331 +g179 +tp19332 +Rp19333 +(I1 +(I1 +I1 +I1 +tp19334 +g38 +I00 +S'wP32:\xb1\x07?' +p19335 +tp19336 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19337 +g179 +tp19338 +Rp19339 +(I1 +(I1 +I1 +I1 +tp19340 +g38 +I00 +S'\xbaf\xa2\xdc\xd4\xbb\x95?' +p19341 +tp19342 +bsg252 +g260 +sg48 +(lp19343 +g0 +(g52 +g2 +Ntp19344 +Rp19345 +(dp19346 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19347 +g179 +tp19348 +Rp19349 +(I1 +(I1 +I1 +I1 +tp19350 +g38 +I00 +S'v`DV#\x90\xfe?' +p19351 +tp19352 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19353 +g454 +asg113 +I10615 +sg280 +I01 +sbaatp19354 +Rp19355 +sg337 +I00 +sg338 +Nsbaa(lp19356 +g458 +ag0 +(g459 +g2 +Ntp19357 +Rp19358 +(dp19359 +g17 +g19112 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19360 +(lp19361 +g189 +ag0 +(g190 +g2 +Ntp19362 +Rp19363 +(dp19364 +g194 +I01 +sg195 +(lp19365 +g0 +(g197 +g2 +Ntp19366 +Rp19367 +(dp19368 +g201 +g176 +(g177 +(I0 +tp19369 +g179 +tp19370 +Rp19371 +(I1 +(I1 +tp19372 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19373 +tp19374 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19375 +Rp19376 +(dp19377 +g201 +g176 +(g177 +(I0 +tp19378 +g179 +tp19379 +Rp19380 +(I1 +(I2 +tp19381 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19382 +tp19383 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp19384 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19385 +g179 +tp19386 +Rp19387 +(I1 +(I1 +I1 +I1 +tp19388 +g38 +I00 +S'\x10\x1d\x15\xae\xb6/8@' +p19389 +tp19390 +bsg238 +g176 +(g177 +(I0 +tp19391 +g179 +tp19392 +Rp19393 +(I1 +(I1 +I1 +I1 +tp19394 +g38 +I00 +S'\x96\x96{v\xb3cW?' +p19395 +tp19396 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19397 +g179 +tp19398 +Rp19399 +(I1 +(I1 +I1 +I1 +tp19400 +g38 +I00 +S'f(!\xa6J\x95\xe0?' +p19401 +tp19402 +bsg252 +g513 +sg48 +(lp19403 +g0 +(g52 +g2 +Ntp19404 +Rp19405 +(dp19406 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp19407 +g179 +tp19408 +Rp19409 +(I1 +(I1 +I1 +I1 +tp19410 +g38 +I00 +S'\xd0\xa0\x9e\xf9\xf0QG@' +p19411 +tp19412 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp19413 +g527 +asg113 +I10618 +sg280 +I01 +sbaa(lp19414 +g529 +ag0 +(g190 +g2 +Ntp19415 +Rp19416 +(dp19417 +g194 +I01 +sg195 +(lp19418 +g0 +(g197 +g2 +Ntp19419 +Rp19420 +(dp19421 +g201 +g176 +(g177 +(I0 +tp19422 +g179 +tp19423 +Rp19424 +(I1 +(I1 +tp19425 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19426 +tp19427 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19428 +Rp19429 +(dp19430 +g201 +g176 +(g177 +(I0 +tp19431 +g179 +tp19432 +Rp19433 +(I1 +(I2 +tp19434 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19435 +tp19436 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19437 +Rp19438 +(dp19439 +g201 +g176 +(g177 +(I0 +tp19440 +g179 +tp19441 +Rp19442 +(I1 +(I2 +tp19443 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19444 +tp19445 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp19446 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19447 +g179 +tp19448 +Rp19449 +(I1 +(I1 +I1 +I1 +tp19450 +g38 +I00 +S'\x12\xa70B\xba@\x0b@' +p19451 +tp19452 +bsg238 +g176 +(g177 +(I0 +tp19453 +g179 +tp19454 +Rp19455 +(I1 +(I1 +I1 +I1 +tp19456 +g38 +I00 +S'T\xfb\xb6\x85\xb0\xd7@?' +p19457 +tp19458 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19459 +g179 +tp19460 +Rp19461 +(I1 +(I1 +I1 +I1 +tp19462 +g38 +I00 +S'\xect\xfaT(\xe5\xc8?' +p19463 +tp19464 +bsg252 +g586 +sg48 +(lp19465 +g0 +(g52 +g2 +Ntp19466 +Rp19467 +(dp19468 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp19469 +g179 +tp19470 +Rp19471 +(I1 +(I1 +I1 +I1 +tp19472 +g38 +I00 +S'6\x1a\xc0[ \x811@' +p19473 +tp19474 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp19475 +g600 +asg113 +I10619 +sg280 +I01 +sbaatp19476 +Rp19477 +sg337 +I00 +sg338 +Nsbaa(lp19478 +g604 +ag0 +(g605 +g2 +Ntp19479 +Rp19480 +(dp19481 +g17 +g19112 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19482 +(lp19483 +g611 +ag0 +(g190 +g2 +Ntp19484 +Rp19485 +(dp19486 +g194 +I01 +sg195 +(lp19487 +g0 +(g197 +g2 +Ntp19488 +Rp19489 +(dp19490 +g201 +g176 +(g177 +(I0 +tp19491 +g179 +tp19492 +Rp19493 +(I1 +(I1 +tp19494 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19495 +tp19496 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19497 +Rp19498 +(dp19499 +g201 +g176 +(g177 +(I0 +tp19500 +g179 +tp19501 +Rp19502 +(I1 +(I2 +tp19503 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19504 +tp19505 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp19506 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19507 +g179 +tp19508 +Rp19509 +(I1 +(I1 +I1 +I1 +tp19510 +g38 +I00 +S'2c\xe1\xc5\xfe\xcd\xa4?' +p19511 +tp19512 +bsg238 +g176 +(g177 +(I0 +tp19513 +g179 +tp19514 +Rp19515 +(I1 +(I1 +I1 +I1 +tp19516 +g38 +I00 +S'kO\x91&\x98\xb6(?' +p19517 +tp19518 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19519 +g179 +tp19520 +Rp19521 +(I1 +(I1 +I1 +I1 +tp19522 +g38 +I00 +S'\xf6X\xc3\x08\x90\xae\x95?' +p19523 +tp19524 +bsg252 +g513 +sg48 +(lp19525 +g0 +(g52 +g2 +Ntp19526 +Rp19527 +(dp19528 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp19529 +g179 +tp19530 +Rp19531 +(I1 +(I1 +I1 +I1 +tp19532 +g38 +I00 +S'\x1a\xb5R\x8cz}\xfe?' +p19533 +tp19534 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp19535 +g664 +asg113 +I10622 +sg280 +I01 +sbaa(lp19536 +g666 +ag0 +(g190 +g2 +Ntp19537 +Rp19538 +(dp19539 +g194 +I01 +sg195 +(lp19540 +g0 +(g197 +g2 +Ntp19541 +Rp19542 +(dp19543 +g201 +g176 +(g177 +(I0 +tp19544 +g179 +tp19545 +Rp19546 +(I1 +(I1 +tp19547 +g208 +I00 +S"7'\x00\x00\x00\x00\x00\x00" +p19548 +tp19549 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19550 +Rp19551 +(dp19552 +g201 +g176 +(g177 +(I0 +tp19553 +g179 +tp19554 +Rp19555 +(I1 +(I2 +tp19556 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19557 +tp19558 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp19559 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19560 +g179 +tp19561 +Rp19562 +(I1 +(I1 +I1 +I1 +tp19563 +g38 +I00 +S'3c\xe1\xc5\xfe\xcd\xa4?' +p19564 +tp19565 +bsg238 +g176 +(g177 +(I0 +tp19566 +g179 +tp19567 +Rp19568 +(I1 +(I1 +I1 +I1 +tp19569 +g38 +I00 +S'0O\x91&\x98\xb6(?' +p19570 +tp19571 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19572 +g179 +tp19573 +Rp19574 +(I1 +(I1 +I1 +I1 +tp19575 +g38 +I00 +S'\xf7X\xc3\x08\x90\xae\x95?' +p19576 +tp19577 +bsg252 +g713 +sg48 +(lp19578 +g0 +(g52 +g2 +Ntp19579 +Rp19580 +(dp19581 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp19582 +g179 +tp19583 +Rp19584 +(I1 +(I1 +I1 +I1 +tp19585 +g38 +I00 +S'\x1b\xb5R\x8cz}\xfe?' +p19586 +tp19587 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp19588 +g727 +asg113 +I10623 +sg280 +I01 +sbaatp19589 +Rp19590 +sg337 +I00 +sg338 +Nsbaatp19591 +Rp19592 +aa(lp19593 +I10040 +ag7 +((lp19594 +(lp19595 +g12 +ag0 +(g13 +g2 +Ntp19596 +Rp19597 +(dp19598 +g17 +g0 +(g18 +g2 +Ntp19599 +Rp19600 +(dp19601 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p19602 +sg116 +g0 +(g117 +g2 +Ntp19603 +Rp19604 +(dp19605 +g121 +(lp19606 +g0 +(g123 +g2 +Ntp19607 +Rp19608 +(dp19609 +g127 +g14695 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp19610 +Rp19611 +(dp19612 +g127 +g2851 +sg148 +g149 +sbasbsg163 +Nsg113 +I10040 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19613 +(lp19614 +g189 +ag0 +(g190 +g2 +Ntp19615 +Rp19616 +(dp19617 +g194 +I01 +sg195 +(lp19618 +g0 +(g197 +g2 +Ntp19619 +Rp19620 +(dp19621 +g201 +g176 +(g177 +(I0 +tp19622 +g179 +tp19623 +Rp19624 +(I1 +(I1 +tp19625 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19626 +tp19627 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19628 +Rp19629 +(dp19630 +g201 +g176 +(g177 +(I0 +tp19631 +g179 +tp19632 +Rp19633 +(I1 +(I2 +tp19634 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19635 +tp19636 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19637 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19638 +g179 +tp19639 +Rp19640 +(I1 +(I1 +I1 +I1 +tp19641 +g38 +I00 +S'{\xedSN\x15\x8b8@' +p19642 +tp19643 +bsg238 +g176 +(g177 +(I0 +tp19644 +g179 +tp19645 +Rp19646 +(I1 +(I1 +I1 +I1 +tp19647 +g38 +I00 +S'\xe8\xf4\xba)\xafTC?' +p19648 +tp19649 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19650 +g179 +tp19651 +Rp19652 +(I1 +(I1 +I1 +I1 +tp19653 +g38 +I00 +S'nF0\x83\xb3\xb5\xe0?' +p19654 +tp19655 +bsg252 +g260 +sg48 +(lp19656 +g0 +(g52 +g2 +Ntp19657 +Rp19658 +(dp19659 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19660 +g179 +tp19661 +Rp19662 +(I1 +(I1 +I1 +I1 +tp19663 +g38 +I00 +S'\x0b\xe3{p\x84\x7fG@' +p19664 +tp19665 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19666 +g279 +asg113 +I10626 +sg280 +I01 +sbaa(lp19667 +g12 +ag0 +(g190 +g2 +Ntp19668 +Rp19669 +(dp19670 +g194 +I01 +sg195 +(lp19671 +g0 +(g197 +g2 +Ntp19672 +Rp19673 +(dp19674 +g201 +g176 +(g177 +(I0 +tp19675 +g179 +tp19676 +Rp19677 +(I1 +(I1 +tp19678 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19679 +tp19680 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19681 +Rp19682 +(dp19683 +g201 +g176 +(g177 +(I0 +tp19684 +g179 +tp19685 +Rp19686 +(I1 +(I2 +tp19687 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19688 +tp19689 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19690 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19691 +g179 +tp19692 +Rp19693 +(I1 +(I1 +I1 +I1 +tp19694 +g38 +I00 +S'\xa0X\x98\xf7\x18\x17\x10@' +p19695 +tp19696 +bsg238 +g176 +(g177 +(I0 +tp19697 +g179 +tp19698 +Rp19699 +(I1 +(I1 +I1 +I1 +tp19700 +g38 +I00 +S'\xab\xe88\x10VU1?' +p19701 +tp19702 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19703 +g179 +tp19704 +Rp19705 +(I1 +(I1 +I1 +I1 +tp19706 +g38 +I00 +S'\x8eL\x04\x91\x11\x0f\xcb?' +p19707 +tp19708 +bsg252 +g260 +sg48 +(lp19709 +g0 +(g52 +g2 +Ntp19710 +Rp19711 +(dp19712 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19713 +g179 +tp19714 +Rp19715 +(I1 +(I1 +I1 +I1 +tp19716 +g38 +I00 +S'\xd4\x05\xf7Y\x98\x063@' +p19717 +tp19718 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19719 +g334 +asg113 +I10627 +sg280 +I01 +sbaatp19720 +Rp19721 +sg337 +I00 +sg338 +Nsbaa(lp19722 +g340 +ag0 +(g341 +g2 +Ntp19723 +Rp19724 +(dp19725 +g17 +g19600 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19726 +(lp19727 +g189 +ag0 +(g190 +g2 +Ntp19728 +Rp19729 +(dp19730 +g194 +I01 +sg195 +(lp19731 +g0 +(g197 +g2 +Ntp19732 +Rp19733 +(dp19734 +g201 +g176 +(g177 +(I0 +tp19735 +g179 +tp19736 +Rp19737 +(I1 +(I1 +tp19738 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19739 +tp19740 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19741 +Rp19742 +(dp19743 +g201 +g176 +(g177 +(I0 +tp19744 +g179 +tp19745 +Rp19746 +(I1 +(I2 +tp19747 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19748 +tp19749 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19750 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19751 +g179 +tp19752 +Rp19753 +(I1 +(I1 +I1 +I1 +tp19754 +g38 +I00 +S'{\xedSN\x15\x8b8@' +p19755 +tp19756 +bsg238 +g176 +(g177 +(I0 +tp19757 +g179 +tp19758 +Rp19759 +(I1 +(I1 +I1 +I1 +tp19760 +g38 +I00 +S'\xe8\xf4\xba)\xafTC?' +p19761 +tp19762 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19763 +g179 +tp19764 +Rp19765 +(I1 +(I1 +I1 +I1 +tp19766 +g38 +I00 +S'nF0\x83\xb3\xb5\xe0?' +p19767 +tp19768 +bsg252 +g260 +sg48 +(lp19769 +g0 +(g52 +g2 +Ntp19770 +Rp19771 +(dp19772 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19773 +g179 +tp19774 +Rp19775 +(I1 +(I1 +I1 +I1 +tp19776 +g38 +I00 +S'\x0b\xe3{p\x84\x7fG@' +p19777 +tp19778 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19779 +g279 +asg113 +I10630 +sg280 +I01 +sbaa(lp19780 +g401 +ag0 +(g190 +g2 +Ntp19781 +Rp19782 +(dp19783 +g194 +I01 +sg195 +(lp19784 +g0 +(g197 +g2 +Ntp19785 +Rp19786 +(dp19787 +g201 +g176 +(g177 +(I0 +tp19788 +g179 +tp19789 +Rp19790 +(I1 +(I1 +tp19791 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19792 +tp19793 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19794 +Rp19795 +(dp19796 +g201 +g176 +(g177 +(I0 +tp19797 +g179 +tp19798 +Rp19799 +(I1 +(I2 +tp19800 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19801 +tp19802 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp19803 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19804 +g179 +tp19805 +Rp19806 +(I1 +(I1 +I1 +I1 +tp19807 +g38 +I00 +S'\xa3\xf7K\xb0\xb4k\xa7?' +p19808 +tp19809 +bsg238 +g176 +(g177 +(I0 +tp19810 +g179 +tp19811 +Rp19812 +(I1 +(I1 +I1 +I1 +tp19813 +g38 +I00 +S'\xb8\xb0\nL\xd0O\r?' +p19814 +tp19815 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19816 +g179 +tp19817 +Rp19818 +(I1 +(I1 +I1 +I1 +tp19819 +g38 +I00 +S'\xb7\xbf=LU\x14\x97?' +p19820 +tp19821 +bsg252 +g260 +sg48 +(lp19822 +g0 +(g52 +g2 +Ntp19823 +Rp19824 +(dp19825 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp19826 +g179 +tp19827 +Rp19828 +(I1 +(I1 +I1 +I1 +tp19829 +g38 +I00 +S'\xcdj\x9b\xf9K:\x00@' +p19830 +tp19831 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp19832 +g454 +asg113 +I10631 +sg280 +I01 +sbaatp19833 +Rp19834 +sg337 +I00 +sg338 +Nsbaa(lp19835 +g458 +ag0 +(g459 +g2 +Ntp19836 +Rp19837 +(dp19838 +g17 +g19600 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19839 +(lp19840 +g189 +ag0 +(g190 +g2 +Ntp19841 +Rp19842 +(dp19843 +g194 +I01 +sg195 +(lp19844 +g0 +(g197 +g2 +Ntp19845 +Rp19846 +(dp19847 +g201 +g176 +(g177 +(I0 +tp19848 +g179 +tp19849 +Rp19850 +(I1 +(I1 +tp19851 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19852 +tp19853 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19854 +Rp19855 +(dp19856 +g201 +g176 +(g177 +(I0 +tp19857 +g179 +tp19858 +Rp19859 +(I1 +(I2 +tp19860 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19861 +tp19862 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp19863 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19864 +g179 +tp19865 +Rp19866 +(I1 +(I1 +I1 +I1 +tp19867 +g38 +I00 +S'e\xcd\xc1\xa8\x8bn8@' +p19868 +tp19869 +bsg238 +g176 +(g177 +(I0 +tp19870 +g179 +tp19871 +Rp19872 +(I1 +(I1 +I1 +I1 +tp19873 +g38 +I00 +S'\xf6U\x81v\xd6~W?' +p19874 +tp19875 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19876 +g179 +tp19877 +Rp19878 +(I1 +(I1 +I1 +I1 +tp19879 +g38 +I00 +S'\xbbv\xa4`\xc7\xaa\xe0?' +p19880 +tp19881 +bsg252 +g513 +sg48 +(lp19882 +g0 +(g52 +g2 +Ntp19883 +Rp19884 +(dp19885 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp19886 +g179 +tp19887 +Rp19888 +(I1 +(I1 +I1 +I1 +tp19889 +g38 +I00 +S'\xf7F\xe7_(pG@' +p19890 +tp19891 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp19892 +g527 +asg113 +I10634 +sg280 +I01 +sbaa(lp19893 +g529 +ag0 +(g190 +g2 +Ntp19894 +Rp19895 +(dp19896 +g194 +I01 +sg195 +(lp19897 +g0 +(g197 +g2 +Ntp19898 +Rp19899 +(dp19900 +g201 +g176 +(g177 +(I0 +tp19901 +g179 +tp19902 +Rp19903 +(I1 +(I1 +tp19904 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19905 +tp19906 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19907 +Rp19908 +(dp19909 +g201 +g176 +(g177 +(I0 +tp19910 +g179 +tp19911 +Rp19912 +(I1 +(I2 +tp19913 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19914 +tp19915 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19916 +Rp19917 +(dp19918 +g201 +g176 +(g177 +(I0 +tp19919 +g179 +tp19920 +Rp19921 +(I1 +(I2 +tp19922 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19923 +tp19924 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp19925 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19926 +g179 +tp19927 +Rp19928 +(I1 +(I1 +I1 +I1 +tp19929 +g38 +I00 +S'O\xa9\xd7o\x1eu\x0b@' +p19930 +tp19931 +bsg238 +g176 +(g177 +(I0 +tp19932 +g179 +tp19933 +Rp19934 +(I1 +(I1 +I1 +I1 +tp19935 +g38 +I00 +S'\xebI\xa9\xce\xdb6A?' +p19936 +tp19937 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19938 +g179 +tp19939 +Rp19940 +(I1 +(I1 +I1 +I1 +tp19941 +g38 +I00 +S'$7\xc3\r\xf8\xfc\xc8?' +p19942 +tp19943 +bsg252 +g586 +sg48 +(lp19944 +g0 +(g52 +g2 +Ntp19945 +Rp19946 +(dp19947 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp19948 +g179 +tp19949 +Rp19950 +(I1 +(I1 +I1 +I1 +tp19951 +g38 +I00 +S'\xc5B\xadi\xde\x911@' +p19952 +tp19953 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp19954 +g600 +asg113 +I10635 +sg280 +I01 +sbaatp19955 +Rp19956 +sg337 +I00 +sg338 +Nsbaa(lp19957 +g604 +ag0 +(g605 +g2 +Ntp19958 +Rp19959 +(dp19960 +g17 +g19600 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp19961 +(lp19962 +g611 +ag0 +(g190 +g2 +Ntp19963 +Rp19964 +(dp19965 +g194 +I01 +sg195 +(lp19966 +g0 +(g197 +g2 +Ntp19967 +Rp19968 +(dp19969 +g201 +g176 +(g177 +(I0 +tp19970 +g179 +tp19971 +Rp19972 +(I1 +(I1 +tp19973 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p19974 +tp19975 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp19976 +Rp19977 +(dp19978 +g201 +g176 +(g177 +(I0 +tp19979 +g179 +tp19980 +Rp19981 +(I1 +(I2 +tp19982 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p19983 +tp19984 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp19985 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp19986 +g179 +tp19987 +Rp19988 +(I1 +(I1 +I1 +I1 +tp19989 +g38 +I00 +S'\x9d7\x8b\x87\\\x1b\xa7?' +p19990 +tp19991 +bsg238 +g176 +(g177 +(I0 +tp19992 +g179 +tp19993 +Rp19994 +(I1 +(I1 +I1 +I1 +tp19995 +g38 +I00 +S'\xe8\x9e\x11\x14\r#)?' +p19996 +tp19997 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp19998 +g179 +tp19999 +Rp20000 +(I1 +(I1 +I1 +I1 +tp20001 +g38 +I00 +S'\xde\xa6\xf6I\x07\xdb\x96?' +p20002 +tp20003 +bsg252 +g513 +sg48 +(lp20004 +g0 +(g52 +g2 +Ntp20005 +Rp20006 +(dp20007 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp20008 +g179 +tp20009 +Rp20010 +(I1 +(I1 +I1 +I1 +tp20011 +g38 +I00 +S'Tm\x01 \x01\x12\x00@' +p20012 +tp20013 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp20014 +g664 +asg113 +I10638 +sg280 +I01 +sbaa(lp20015 +g666 +ag0 +(g190 +g2 +Ntp20016 +Rp20017 +(dp20018 +g194 +I01 +sg195 +(lp20019 +g0 +(g197 +g2 +Ntp20020 +Rp20021 +(dp20022 +g201 +g176 +(g177 +(I0 +tp20023 +g179 +tp20024 +Rp20025 +(I1 +(I1 +tp20026 +g208 +I00 +S"8'\x00\x00\x00\x00\x00\x00" +p20027 +tp20028 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20029 +Rp20030 +(dp20031 +g201 +g176 +(g177 +(I0 +tp20032 +g179 +tp20033 +Rp20034 +(I1 +(I2 +tp20035 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20036 +tp20037 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp20038 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20039 +g179 +tp20040 +Rp20041 +(I1 +(I1 +I1 +I1 +tp20042 +g38 +I00 +S'\x9b7\x8b\x87\\\x1b\xa7?' +p20043 +tp20044 +bsg238 +g176 +(g177 +(I0 +tp20045 +g179 +tp20046 +Rp20047 +(I1 +(I1 +I1 +I1 +tp20048 +g38 +I00 +S'G\xa0\x11\x14\r#)?' +p20049 +tp20050 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20051 +g179 +tp20052 +Rp20053 +(I1 +(I1 +I1 +I1 +tp20054 +g38 +I00 +S'\xdb\xa6\xf6I\x07\xdb\x96?' +p20055 +tp20056 +bsg252 +g713 +sg48 +(lp20057 +g0 +(g52 +g2 +Ntp20058 +Rp20059 +(dp20060 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp20061 +g179 +tp20062 +Rp20063 +(I1 +(I1 +I1 +I1 +tp20064 +g38 +I00 +S'Rm\x01 \x01\x12\x00@' +p20065 +tp20066 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp20067 +g727 +asg113 +I10639 +sg280 +I01 +sbaatp20068 +Rp20069 +sg337 +I00 +sg338 +Nsbaatp20070 +Rp20071 +aa(lp20072 +I10041 +ag7 +((lp20073 +(lp20074 +g12 +ag0 +(g13 +g2 +Ntp20075 +Rp20076 +(dp20077 +g17 +g0 +(g18 +g2 +Ntp20078 +Rp20079 +(dp20080 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p20081 +sg116 +g0 +(g117 +g2 +Ntp20082 +Rp20083 +(dp20084 +g121 +(lp20085 +g0 +(g123 +g2 +Ntp20086 +Rp20087 +(dp20088 +g127 +g0 +(g128 +g2 +Ntp20089 +Rp20090 +(dp20091 +g23 +g132 +sg133 +(dp20092 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\x11@' +p20093 +tp20094 +Rp20095 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p20096 +sg113 +I70 +sg146 +(lp20097 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp20098 +Rp20099 +(dp20100 +g127 +g0 +(g128 +g2 +Ntp20101 +Rp20102 +(dp20103 +g23 +g132 +sg133 +(dp20104 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S')\\\x8f\xc2\xf5\xa8\x11@' +p20105 +tp20106 +Rp20107 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p20108 +sg113 +I71 +sg146 +(lp20109 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10041 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20110 +(lp20111 +g189 +ag0 +(g190 +g2 +Ntp20112 +Rp20113 +(dp20114 +g194 +I01 +sg195 +(lp20115 +g0 +(g197 +g2 +Ntp20116 +Rp20117 +(dp20118 +g201 +g176 +(g177 +(I0 +tp20119 +g179 +tp20120 +Rp20121 +(I1 +(I1 +tp20122 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20123 +tp20124 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20125 +Rp20126 +(dp20127 +g201 +g176 +(g177 +(I0 +tp20128 +g179 +tp20129 +Rp20130 +(I1 +(I2 +tp20131 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20132 +tp20133 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20134 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20135 +g179 +tp20136 +Rp20137 +(I1 +(I1 +I1 +I1 +tp20138 +g38 +I00 +S'\xd2\xcd1\xc4p$I@' +p20139 +tp20140 +bsg238 +g176 +(g177 +(I0 +tp20141 +g179 +tp20142 +Rp20143 +(I1 +(I1 +I1 +I1 +tp20144 +g38 +I00 +S'8\xac\xa7\x8dn\xb9G?' +p20145 +tp20146 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20147 +g179 +tp20148 +Rp20149 +(I1 +(I1 +I1 +I1 +tp20150 +g38 +I00 +S'\xbdE\xbf \x0f\xeb\xe7?' +p20151 +tp20152 +bsg252 +g260 +sg48 +(lp20153 +g0 +(g52 +g2 +Ntp20154 +Rp20155 +(dp20156 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20157 +g179 +tp20158 +Rp20159 +(I1 +(I1 +I1 +I1 +tp20160 +g38 +I00 +S'\t}\x06\xa3F\xd1P@' +p20161 +tp20162 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20163 +g279 +asg113 +I10642 +sg280 +I01 +sbaa(lp20164 +g12 +ag0 +(g190 +g2 +Ntp20165 +Rp20166 +(dp20167 +g194 +I01 +sg195 +(lp20168 +g0 +(g197 +g2 +Ntp20169 +Rp20170 +(dp20171 +g201 +g176 +(g177 +(I0 +tp20172 +g179 +tp20173 +Rp20174 +(I1 +(I1 +tp20175 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20176 +tp20177 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20178 +Rp20179 +(dp20180 +g201 +g176 +(g177 +(I0 +tp20181 +g179 +tp20182 +Rp20183 +(I1 +(I2 +tp20184 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20185 +tp20186 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20187 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20188 +g179 +tp20189 +Rp20190 +(I1 +(I1 +I1 +I1 +tp20191 +g38 +I00 +S'\x91C\x01\xdb\xec\x9cM@' +p20192 +tp20193 +bsg238 +g176 +(g177 +(I0 +tp20194 +g179 +tp20195 +Rp20196 +(I1 +(I1 +I1 +I1 +tp20197 +g38 +I00 +S'h\xdaT\x11z\xc0R?' +p20198 +tp20199 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20200 +g179 +tp20201 +Rp20202 +(I1 +(I1 +I1 +I1 +tp20203 +g38 +I00 +S'\x9eo\xdf\x1f\xde\xf4\xe9?' +p20204 +tp20205 +bsg252 +g260 +sg48 +(lp20206 +g0 +(g52 +g2 +Ntp20207 +Rp20208 +(dp20209 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20210 +g179 +tp20211 +Rp20212 +(I1 +(I1 +I1 +I1 +tp20213 +g38 +I00 +S'{\x1ai.,@R@' +p20214 +tp20215 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20216 +g334 +asg113 +I10643 +sg280 +I01 +sbaatp20217 +Rp20218 +sg337 +I00 +sg338 +Nsbaa(lp20219 +g340 +ag0 +(g341 +g2 +Ntp20220 +Rp20221 +(dp20222 +g17 +g20079 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20223 +(lp20224 +g189 +ag0 +(g190 +g2 +Ntp20225 +Rp20226 +(dp20227 +g194 +I01 +sg195 +(lp20228 +g0 +(g197 +g2 +Ntp20229 +Rp20230 +(dp20231 +g201 +g176 +(g177 +(I0 +tp20232 +g179 +tp20233 +Rp20234 +(I1 +(I1 +tp20235 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20236 +tp20237 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20238 +Rp20239 +(dp20240 +g201 +g176 +(g177 +(I0 +tp20241 +g179 +tp20242 +Rp20243 +(I1 +(I2 +tp20244 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20245 +tp20246 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20247 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20248 +g179 +tp20249 +Rp20250 +(I1 +(I1 +I1 +I1 +tp20251 +g38 +I00 +S'\xd2\xcd1\xc4p$I@' +p20252 +tp20253 +bsg238 +g176 +(g177 +(I0 +tp20254 +g179 +tp20255 +Rp20256 +(I1 +(I1 +I1 +I1 +tp20257 +g38 +I00 +S'8\xac\xa7\x8dn\xb9G?' +p20258 +tp20259 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20260 +g179 +tp20261 +Rp20262 +(I1 +(I1 +I1 +I1 +tp20263 +g38 +I00 +S'\xbdE\xbf \x0f\xeb\xe7?' +p20264 +tp20265 +bsg252 +g260 +sg48 +(lp20266 +g0 +(g52 +g2 +Ntp20267 +Rp20268 +(dp20269 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20270 +g179 +tp20271 +Rp20272 +(I1 +(I1 +I1 +I1 +tp20273 +g38 +I00 +S'\t}\x06\xa3F\xd1P@' +p20274 +tp20275 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20276 +g279 +asg113 +I10646 +sg280 +I01 +sbaa(lp20277 +g401 +ag0 +(g190 +g2 +Ntp20278 +Rp20279 +(dp20280 +g194 +I01 +sg195 +(lp20281 +g0 +(g197 +g2 +Ntp20282 +Rp20283 +(dp20284 +g201 +g176 +(g177 +(I0 +tp20285 +g179 +tp20286 +Rp20287 +(I1 +(I1 +tp20288 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20289 +tp20290 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20291 +Rp20292 +(dp20293 +g201 +g176 +(g177 +(I0 +tp20294 +g179 +tp20295 +Rp20296 +(I1 +(I2 +tp20297 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20298 +tp20299 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20300 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20301 +g179 +tp20302 +Rp20303 +(I1 +(I1 +I1 +I1 +tp20304 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20305 +tp20306 +bsg238 +g176 +(g177 +(I0 +tp20307 +g179 +tp20308 +Rp20309 +(I1 +(I1 +I1 +I1 +tp20310 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20311 +tp20312 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20313 +g179 +tp20314 +Rp20315 +(I1 +(I1 +I1 +I1 +tp20316 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20317 +tp20318 +bsg252 +g260 +sg48 +(lp20319 +g0 +(g52 +g2 +Ntp20320 +Rp20321 +(dp20322 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20323 +g179 +tp20324 +Rp20325 +(I1 +(I1 +I1 +I1 +tp20326 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20327 +tp20328 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20329 +g454 +asg113 +I10647 +sg280 +I01 +sbaatp20330 +Rp20331 +sg337 +I00 +sg338 +Nsbaa(lp20332 +g458 +ag0 +(g459 +g2 +Ntp20333 +Rp20334 +(dp20335 +g17 +g20079 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20336 +(lp20337 +g189 +ag0 +(g190 +g2 +Ntp20338 +Rp20339 +(dp20340 +g194 +I01 +sg195 +(lp20341 +g0 +(g197 +g2 +Ntp20342 +Rp20343 +(dp20344 +g201 +g176 +(g177 +(I0 +tp20345 +g179 +tp20346 +Rp20347 +(I1 +(I1 +tp20348 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20349 +tp20350 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20351 +Rp20352 +(dp20353 +g201 +g176 +(g177 +(I0 +tp20354 +g179 +tp20355 +Rp20356 +(I1 +(I2 +tp20357 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20358 +tp20359 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp20360 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20361 +g179 +tp20362 +Rp20363 +(I1 +(I1 +I1 +I1 +tp20364 +g38 +I00 +S'\xb5\xe2\xda\xcb:+I@' +p20365 +tp20366 +bsg238 +g176 +(g177 +(I0 +tp20367 +g179 +tp20368 +Rp20369 +(I1 +(I1 +I1 +I1 +tp20370 +g38 +I00 +S'\xd1\x16yuy\x85V?' +p20371 +tp20372 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20373 +g179 +tp20374 +Rp20375 +(I1 +(I1 +I1 +I1 +tp20376 +g38 +I00 +S'\r\x9c+K\x9f\xed\xe7?' +p20377 +tp20378 +bsg252 +g513 +sg48 +(lp20379 +g0 +(g52 +g2 +Ntp20380 +Rp20381 +(dp20382 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp20383 +g179 +tp20384 +Rp20385 +(I1 +(I1 +I1 +I1 +tp20386 +g38 +I00 +S'\xb9\xa9\xda\x00\x14\xd3P@' +p20387 +tp20388 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp20389 +g527 +asg113 +I10650 +sg280 +I01 +sbaa(lp20390 +g529 +ag0 +(g190 +g2 +Ntp20391 +Rp20392 +(dp20393 +g194 +I01 +sg195 +(lp20394 +g0 +(g197 +g2 +Ntp20395 +Rp20396 +(dp20397 +g201 +g176 +(g177 +(I0 +tp20398 +g179 +tp20399 +Rp20400 +(I1 +(I1 +tp20401 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20402 +tp20403 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20404 +Rp20405 +(dp20406 +g201 +g176 +(g177 +(I0 +tp20407 +g179 +tp20408 +Rp20409 +(I1 +(I2 +tp20410 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20411 +tp20412 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20413 +Rp20414 +(dp20415 +g201 +g176 +(g177 +(I0 +tp20416 +g179 +tp20417 +Rp20418 +(I1 +(I2 +tp20419 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20420 +tp20421 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp20422 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20423 +g179 +tp20424 +Rp20425 +(I1 +(I1 +I1 +I1 +tp20426 +g38 +I00 +S'\xb4\x10\xec\x11\xcd\xedL@' +p20427 +tp20428 +bsg238 +g176 +(g177 +(I0 +tp20429 +g179 +tp20430 +Rp20431 +(I1 +(I1 +I1 +I1 +tp20432 +g38 +I00 +S'\x07\xc7\x83<\xbf\xa9V?' +p20433 +tp20434 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20435 +g179 +tp20436 +Rp20437 +(I1 +(I1 +I1 +I1 +tp20438 +g38 +I00 +S'aT\xc7ya\xa7\xe9?' +p20439 +tp20440 +bsg252 +g586 +sg48 +(lp20441 +g0 +(g52 +g2 +Ntp20442 +Rp20443 +(dp20444 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp20445 +g179 +tp20446 +Rp20447 +(I1 +(I1 +I1 +I1 +tp20448 +g38 +I00 +S"T'\xa0\x89\xb0\tR@" +p20449 +tp20450 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp20451 +g600 +asg113 +I10651 +sg280 +I01 +sbaatp20452 +Rp20453 +sg337 +I00 +sg338 +Nsbaa(lp20454 +g604 +ag0 +(g605 +g2 +Ntp20455 +Rp20456 +(dp20457 +g17 +g20079 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20458 +(lp20459 +g611 +ag0 +(g190 +g2 +Ntp20460 +Rp20461 +(dp20462 +g194 +I01 +sg195 +(lp20463 +g0 +(g197 +g2 +Ntp20464 +Rp20465 +(dp20466 +g201 +g176 +(g177 +(I0 +tp20467 +g179 +tp20468 +Rp20469 +(I1 +(I1 +tp20470 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20471 +tp20472 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20473 +Rp20474 +(dp20475 +g201 +g176 +(g177 +(I0 +tp20476 +g179 +tp20477 +Rp20478 +(I1 +(I2 +tp20479 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20480 +tp20481 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp20482 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20483 +g179 +tp20484 +Rp20485 +(I1 +(I1 +I1 +I1 +tp20486 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20487 +tp20488 +bsg238 +g176 +(g177 +(I0 +tp20489 +g179 +tp20490 +Rp20491 +(I1 +(I1 +I1 +I1 +tp20492 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20493 +tp20494 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20495 +g179 +tp20496 +Rp20497 +(I1 +(I1 +I1 +I1 +tp20498 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20499 +tp20500 +bsg252 +g513 +sg48 +(lp20501 +g0 +(g52 +g2 +Ntp20502 +Rp20503 +(dp20504 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp20505 +g179 +tp20506 +Rp20507 +(I1 +(I1 +I1 +I1 +tp20508 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20509 +tp20510 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp20511 +g664 +asg113 +I10654 +sg280 +I01 +sbaa(lp20512 +g666 +ag0 +(g190 +g2 +Ntp20513 +Rp20514 +(dp20515 +g194 +I01 +sg195 +(lp20516 +g0 +(g197 +g2 +Ntp20517 +Rp20518 +(dp20519 +g201 +g176 +(g177 +(I0 +tp20520 +g179 +tp20521 +Rp20522 +(I1 +(I1 +tp20523 +g208 +I00 +S"9'\x00\x00\x00\x00\x00\x00" +p20524 +tp20525 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20526 +Rp20527 +(dp20528 +g201 +g176 +(g177 +(I0 +tp20529 +g179 +tp20530 +Rp20531 +(I1 +(I2 +tp20532 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20533 +tp20534 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp20535 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20536 +g179 +tp20537 +Rp20538 +(I1 +(I1 +I1 +I1 +tp20539 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20540 +tp20541 +bsg238 +g176 +(g177 +(I0 +tp20542 +g179 +tp20543 +Rp20544 +(I1 +(I1 +I1 +I1 +tp20545 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20546 +tp20547 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20548 +g179 +tp20549 +Rp20550 +(I1 +(I1 +I1 +I1 +tp20551 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20552 +tp20553 +bsg252 +g713 +sg48 +(lp20554 +g0 +(g52 +g2 +Ntp20555 +Rp20556 +(dp20557 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp20558 +g179 +tp20559 +Rp20560 +(I1 +(I1 +I1 +I1 +tp20561 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p20562 +tp20563 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp20564 +g727 +asg113 +I10655 +sg280 +I01 +sbaatp20565 +Rp20566 +sg337 +I00 +sg338 +Nsbaatp20567 +Rp20568 +aa(lp20569 +I10042 +ag7 +((lp20570 +(lp20571 +g12 +ag0 +(g13 +g2 +Ntp20572 +Rp20573 +(dp20574 +g17 +g0 +(g18 +g2 +Ntp20575 +Rp20576 +(dp20577 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p20578 +sg116 +g0 +(g117 +g2 +Ntp20579 +Rp20580 +(dp20581 +g121 +(lp20582 +g0 +(g123 +g2 +Ntp20583 +Rp20584 +(dp20585 +g127 +g6309 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp20586 +Rp20587 +(dp20588 +g127 +g0 +(g128 +g2 +Ntp20589 +Rp20590 +(dp20591 +g23 +g132 +sg133 +(dp20592 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xdc?' +p20593 +tp20594 +Rp20595 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p20596 +sg113 +I72 +sg146 +(lp20597 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10042 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20598 +(lp20599 +g189 +ag0 +(g190 +g2 +Ntp20600 +Rp20601 +(dp20602 +g194 +I01 +sg195 +(lp20603 +g0 +(g197 +g2 +Ntp20604 +Rp20605 +(dp20606 +g201 +g176 +(g177 +(I0 +tp20607 +g179 +tp20608 +Rp20609 +(I1 +(I1 +tp20610 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20611 +tp20612 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20613 +Rp20614 +(dp20615 +g201 +g176 +(g177 +(I0 +tp20616 +g179 +tp20617 +Rp20618 +(I1 +(I2 +tp20619 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20620 +tp20621 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20622 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20623 +g179 +tp20624 +Rp20625 +(I1 +(I1 +I1 +I1 +tp20626 +g38 +I00 +S'\x7f\x81\x8f?\x94s8@' +p20627 +tp20628 +bsg238 +g176 +(g177 +(I0 +tp20629 +g179 +tp20630 +Rp20631 +(I1 +(I1 +I1 +I1 +tp20632 +g38 +I00 +S'C\xe1\x9b\xf84;D?' +p20633 +tp20634 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20635 +g179 +tp20636 +Rp20637 +(I1 +(I1 +I1 +I1 +tp20638 +g38 +I00 +S'\xa8t\xb2 \xab\xad\xe0?' +p20639 +tp20640 +bsg252 +g260 +sg48 +(lp20641 +g0 +(g52 +g2 +Ntp20642 +Rp20643 +(dp20644 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20645 +g179 +tp20646 +Rp20647 +(I1 +(I1 +I1 +I1 +tp20648 +g38 +I00 +S'\x0c\xf4\xfa\xa58tG@' +p20649 +tp20650 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20651 +g279 +asg113 +I10658 +sg280 +I01 +sbaa(lp20652 +g12 +ag0 +(g190 +g2 +Ntp20653 +Rp20654 +(dp20655 +g194 +I01 +sg195 +(lp20656 +g0 +(g197 +g2 +Ntp20657 +Rp20658 +(dp20659 +g201 +g176 +(g177 +(I0 +tp20660 +g179 +tp20661 +Rp20662 +(I1 +(I1 +tp20663 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20664 +tp20665 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20666 +Rp20667 +(dp20668 +g201 +g176 +(g177 +(I0 +tp20669 +g179 +tp20670 +Rp20671 +(I1 +(I2 +tp20672 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20673 +tp20674 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20675 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20676 +g179 +tp20677 +Rp20678 +(I1 +(I1 +I1 +I1 +tp20679 +g38 +I00 +S'\x07\xdd\x82b\xc6K\x0f@' +p20680 +tp20681 +bsg238 +g176 +(g177 +(I0 +tp20682 +g179 +tp20683 +Rp20684 +(I1 +(I1 +I1 +I1 +tp20685 +g38 +I00 +S'\x0fW\xc6g\xb1\x861?' +p20686 +tp20687 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20688 +g179 +tp20689 +Rp20690 +(I1 +(I1 +I1 +I1 +tp20691 +g38 +I00 +S'U\xeekF0\xaf\xca?' +p20692 +tp20693 +bsg252 +g260 +sg48 +(lp20694 +g0 +(g52 +g2 +Ntp20695 +Rp20696 +(dp20697 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20698 +g179 +tp20699 +Rp20700 +(I1 +(I1 +I1 +I1 +tp20701 +g38 +I00 +S'\x94\xe3\x83\xf1-\xc32@' +p20702 +tp20703 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20704 +g334 +asg113 +I10659 +sg280 +I01 +sbaatp20705 +Rp20706 +sg337 +I00 +sg338 +Nsbaa(lp20707 +g340 +ag0 +(g341 +g2 +Ntp20708 +Rp20709 +(dp20710 +g17 +g20576 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20711 +(lp20712 +g189 +ag0 +(g190 +g2 +Ntp20713 +Rp20714 +(dp20715 +g194 +I01 +sg195 +(lp20716 +g0 +(g197 +g2 +Ntp20717 +Rp20718 +(dp20719 +g201 +g176 +(g177 +(I0 +tp20720 +g179 +tp20721 +Rp20722 +(I1 +(I1 +tp20723 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20724 +tp20725 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20726 +Rp20727 +(dp20728 +g201 +g176 +(g177 +(I0 +tp20729 +g179 +tp20730 +Rp20731 +(I1 +(I2 +tp20732 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20733 +tp20734 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20735 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20736 +g179 +tp20737 +Rp20738 +(I1 +(I1 +I1 +I1 +tp20739 +g38 +I00 +S'\x7f\x81\x8f?\x94s8@' +p20740 +tp20741 +bsg238 +g176 +(g177 +(I0 +tp20742 +g179 +tp20743 +Rp20744 +(I1 +(I1 +I1 +I1 +tp20745 +g38 +I00 +S'C\xe1\x9b\xf84;D?' +p20746 +tp20747 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20748 +g179 +tp20749 +Rp20750 +(I1 +(I1 +I1 +I1 +tp20751 +g38 +I00 +S'\xa8t\xb2 \xab\xad\xe0?' +p20752 +tp20753 +bsg252 +g260 +sg48 +(lp20754 +g0 +(g52 +g2 +Ntp20755 +Rp20756 +(dp20757 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20758 +g179 +tp20759 +Rp20760 +(I1 +(I1 +I1 +I1 +tp20761 +g38 +I00 +S'\x0c\xf4\xfa\xa58tG@' +p20762 +tp20763 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20764 +g279 +asg113 +I10662 +sg280 +I01 +sbaa(lp20765 +g401 +ag0 +(g190 +g2 +Ntp20766 +Rp20767 +(dp20768 +g194 +I01 +sg195 +(lp20769 +g0 +(g197 +g2 +Ntp20770 +Rp20771 +(dp20772 +g201 +g176 +(g177 +(I0 +tp20773 +g179 +tp20774 +Rp20775 +(I1 +(I1 +tp20776 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20777 +tp20778 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20779 +Rp20780 +(dp20781 +g201 +g176 +(g177 +(I0 +tp20782 +g179 +tp20783 +Rp20784 +(I1 +(I2 +tp20785 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20786 +tp20787 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp20788 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20789 +g179 +tp20790 +Rp20791 +(I1 +(I1 +I1 +I1 +tp20792 +g38 +I00 +S'\xce6\x9bl\xa1\x7f\xa0?' +p20793 +tp20794 +bsg238 +g176 +(g177 +(I0 +tp20795 +g179 +tp20796 +Rp20797 +(I1 +(I1 +I1 +I1 +tp20798 +g38 +I00 +S'\xce~;\xeeX\xc7\x07?' +p20799 +tp20800 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20801 +g179 +tp20802 +Rp20803 +(I1 +(I1 +I1 +I1 +tp20804 +g38 +I00 +S'\xd7\xe4\xae`\x04_\x93?' +p20805 +tp20806 +bsg252 +g260 +sg48 +(lp20807 +g0 +(g52 +g2 +Ntp20808 +Rp20809 +(dp20810 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp20811 +g179 +tp20812 +Rp20813 +(I1 +(I1 +I1 +I1 +tp20814 +g38 +I00 +S"\xcf\xf1\xf5'\x9e=\xfb?" +p20815 +tp20816 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp20817 +g454 +asg113 +I10663 +sg280 +I01 +sbaatp20818 +Rp20819 +sg337 +I00 +sg338 +Nsbaa(lp20820 +g458 +ag0 +(g459 +g2 +Ntp20821 +Rp20822 +(dp20823 +g17 +g20576 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20824 +(lp20825 +g189 +ag0 +(g190 +g2 +Ntp20826 +Rp20827 +(dp20828 +g194 +I01 +sg195 +(lp20829 +g0 +(g197 +g2 +Ntp20830 +Rp20831 +(dp20832 +g201 +g176 +(g177 +(I0 +tp20833 +g179 +tp20834 +Rp20835 +(I1 +(I1 +tp20836 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20837 +tp20838 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20839 +Rp20840 +(dp20841 +g201 +g176 +(g177 +(I0 +tp20842 +g179 +tp20843 +Rp20844 +(I1 +(I2 +tp20845 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20846 +tp20847 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp20848 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20849 +g179 +tp20850 +Rp20851 +(I1 +(I1 +I1 +I1 +tp20852 +g38 +I00 +S'\x9f\x01\xb6\xad/\x978@' +p20853 +tp20854 +bsg238 +g176 +(g177 +(I0 +tp20855 +g179 +tp20856 +Rp20857 +(I1 +(I1 +I1 +I1 +tp20858 +g38 +I00 +S'\xe4\xf2\x8e\xcf\x91!W?' +p20859 +tp20860 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20861 +g179 +tp20862 +Rp20863 +(I1 +(I1 +I1 +I1 +tp20864 +g38 +I00 +S'\xb0\xb4+\x12\xac\xb8\xe0?' +p20865 +tp20866 +bsg252 +g513 +sg48 +(lp20867 +g0 +(g52 +g2 +Ntp20868 +Rp20869 +(dp20870 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp20871 +g179 +tp20872 +Rp20873 +(I1 +(I1 +I1 +I1 +tp20874 +g38 +I00 +S'\x18v\x8d\xf9\xb1\x83G@' +p20875 +tp20876 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp20877 +g527 +asg113 +I10666 +sg280 +I01 +sbaa(lp20878 +g529 +ag0 +(g190 +g2 +Ntp20879 +Rp20880 +(dp20881 +g194 +I01 +sg195 +(lp20882 +g0 +(g197 +g2 +Ntp20883 +Rp20884 +(dp20885 +g201 +g176 +(g177 +(I0 +tp20886 +g179 +tp20887 +Rp20888 +(I1 +(I1 +tp20889 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20890 +tp20891 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20892 +Rp20893 +(dp20894 +g201 +g176 +(g177 +(I0 +tp20895 +g179 +tp20896 +Rp20897 +(I1 +(I2 +tp20898 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20899 +tp20900 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20901 +Rp20902 +(dp20903 +g201 +g176 +(g177 +(I0 +tp20904 +g179 +tp20905 +Rp20906 +(I1 +(I2 +tp20907 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20908 +tp20909 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp20910 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20911 +g179 +tp20912 +Rp20913 +(I1 +(I1 +I1 +I1 +tp20914 +g38 +I00 +S'm*\xcd\xde\x00\x80\x0b@' +p20915 +tp20916 +bsg238 +g176 +(g177 +(I0 +tp20917 +g179 +tp20918 +Rp20919 +(I1 +(I1 +I1 +I1 +tp20920 +g38 +I00 +S'\x15\x88l\x94\x829A?' +p20921 +tp20922 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20923 +g179 +tp20924 +Rp20925 +(I1 +(I1 +I1 +I1 +tp20926 +g38 +I00 +S'\x80\x17g\xaa\xeb\x01\xc9?' +p20927 +tp20928 +bsg252 +g586 +sg48 +(lp20929 +g0 +(g52 +g2 +Ntp20930 +Rp20931 +(dp20932 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp20933 +g179 +tp20934 +Rp20935 +(I1 +(I1 +I1 +I1 +tp20936 +g38 +I00 +S'\x86|\xd0\xb3Y\x951@' +p20937 +tp20938 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp20939 +g600 +asg113 +I10667 +sg280 +I01 +sbaatp20940 +Rp20941 +sg337 +I00 +sg338 +Nsbaa(lp20942 +g604 +ag0 +(g605 +g2 +Ntp20943 +Rp20944 +(dp20945 +g17 +g20576 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp20946 +(lp20947 +g611 +ag0 +(g190 +g2 +Ntp20948 +Rp20949 +(dp20950 +g194 +I01 +sg195 +(lp20951 +g0 +(g197 +g2 +Ntp20952 +Rp20953 +(dp20954 +g201 +g176 +(g177 +(I0 +tp20955 +g179 +tp20956 +Rp20957 +(I1 +(I1 +tp20958 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p20959 +tp20960 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp20961 +Rp20962 +(dp20963 +g201 +g176 +(g177 +(I0 +tp20964 +g179 +tp20965 +Rp20966 +(I1 +(I2 +tp20967 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p20968 +tp20969 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp20970 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp20971 +g179 +tp20972 +Rp20973 +(I1 +(I1 +I1 +I1 +tp20974 +g38 +I00 +S'?\xdenK\xd7\xf6\xa0?' +p20975 +tp20976 +bsg238 +g176 +(g177 +(I0 +tp20977 +g179 +tp20978 +Rp20979 +(I1 +(I1 +I1 +I1 +tp20980 +g38 +I00 +S'\x8a\xe8q\xf9I\xf3&?' +p20981 +tp20982 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp20983 +g179 +tp20984 +Rp20985 +(I1 +(I1 +I1 +I1 +tp20986 +g38 +I00 +S'N\xf1\xc1\xeb\x1f\x93\x93?' +p20987 +tp20988 +bsg252 +g513 +sg48 +(lp20989 +g0 +(g52 +g2 +Ntp20990 +Rp20991 +(dp20992 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp20993 +g179 +tp20994 +Rp20995 +(I1 +(I1 +I1 +I1 +tp20996 +g38 +I00 +S'U\xbb\x88\xe3\xe4\x86\xfb?' +p20997 +tp20998 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp20999 +g664 +asg113 +I10670 +sg280 +I01 +sbaa(lp21000 +g666 +ag0 +(g190 +g2 +Ntp21001 +Rp21002 +(dp21003 +g194 +I01 +sg195 +(lp21004 +g0 +(g197 +g2 +Ntp21005 +Rp21006 +(dp21007 +g201 +g176 +(g177 +(I0 +tp21008 +g179 +tp21009 +Rp21010 +(I1 +(I1 +tp21011 +g208 +I00 +S":'\x00\x00\x00\x00\x00\x00" +p21012 +tp21013 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21014 +Rp21015 +(dp21016 +g201 +g176 +(g177 +(I0 +tp21017 +g179 +tp21018 +Rp21019 +(I1 +(I2 +tp21020 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21021 +tp21022 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp21023 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21024 +g179 +tp21025 +Rp21026 +(I1 +(I1 +I1 +I1 +tp21027 +g38 +I00 +S'A\xdenK\xd7\xf6\xa0?' +p21028 +tp21029 +bsg238 +g176 +(g177 +(I0 +tp21030 +g179 +tp21031 +Rp21032 +(I1 +(I1 +I1 +I1 +tp21033 +g38 +I00 +S'K\xe9q\xf9I\xf3&?' +p21034 +tp21035 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21036 +g179 +tp21037 +Rp21038 +(I1 +(I1 +I1 +I1 +tp21039 +g38 +I00 +S'N\xf1\xc1\xeb\x1f\x93\x93?' +p21040 +tp21041 +bsg252 +g713 +sg48 +(lp21042 +g0 +(g52 +g2 +Ntp21043 +Rp21044 +(dp21045 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp21046 +g179 +tp21047 +Rp21048 +(I1 +(I1 +I1 +I1 +tp21049 +g38 +I00 +S'V\xbb\x88\xe3\xe4\x86\xfb?' +p21050 +tp21051 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp21052 +g727 +asg113 +I10671 +sg280 +I01 +sbaatp21053 +Rp21054 +sg337 +I00 +sg338 +Nsbaatp21055 +Rp21056 +aa(lp21057 +I10043 +ag7 +((lp21058 +(lp21059 +g12 +ag0 +(g13 +g2 +Ntp21060 +Rp21061 +(dp21062 +g17 +g0 +(g18 +g2 +Ntp21063 +Rp21064 +(dp21065 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p21066 +sg116 +g0 +(g117 +g2 +Ntp21067 +Rp21068 +(dp21069 +g121 +(lp21070 +g0 +(g123 +g2 +Ntp21071 +Rp21072 +(dp21073 +g127 +g9755 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp21074 +Rp21075 +(dp21076 +g127 +g0 +(g128 +g2 +Ntp21077 +Rp21078 +(dp21079 +g23 +g132 +sg133 +(dp21080 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x14@' +p21081 +tp21082 +Rp21083 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p21084 +sg113 +I25 +sg146 +(lp21085 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10043 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21086 +(lp21087 +g189 +ag0 +(g190 +g2 +Ntp21088 +Rp21089 +(dp21090 +g194 +I01 +sg195 +(lp21091 +g0 +(g197 +g2 +Ntp21092 +Rp21093 +(dp21094 +g201 +g176 +(g177 +(I0 +tp21095 +g179 +tp21096 +Rp21097 +(I1 +(I1 +tp21098 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21099 +tp21100 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21101 +Rp21102 +(dp21103 +g201 +g176 +(g177 +(I0 +tp21104 +g179 +tp21105 +Rp21106 +(I1 +(I2 +tp21107 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21108 +tp21109 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21110 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21111 +g179 +tp21112 +Rp21113 +(I1 +(I1 +I1 +I1 +tp21114 +g38 +I00 +S'\x80S\xea\xef\xecqI@' +p21115 +tp21116 +bsg238 +g176 +(g177 +(I0 +tp21117 +g179 +tp21118 +Rp21119 +(I1 +(I1 +I1 +I1 +tp21120 +g38 +I00 +S'5\xb5\x07\xbb\x82SK?' +p21121 +tp21122 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21123 +g179 +tp21124 +Rp21125 +(I1 +(I1 +I1 +I1 +tp21126 +g38 +I00 +S'zX$\x9e\xb9\x0f\xe8?' +p21127 +tp21128 +bsg252 +g260 +sg48 +(lp21129 +g0 +(g52 +g2 +Ntp21130 +Rp21131 +(dp21132 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21133 +g179 +tp21134 +Rp21135 +(I1 +(I1 +I1 +I1 +tp21136 +g38 +I00 +S'6\x8e1\x83\x0e\xebP@' +p21137 +tp21138 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21139 +g279 +asg113 +I10674 +sg280 +I01 +sbaa(lp21140 +g12 +ag0 +(g190 +g2 +Ntp21141 +Rp21142 +(dp21143 +g194 +I01 +sg195 +(lp21144 +g0 +(g197 +g2 +Ntp21145 +Rp21146 +(dp21147 +g201 +g176 +(g177 +(I0 +tp21148 +g179 +tp21149 +Rp21150 +(I1 +(I1 +tp21151 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21152 +tp21153 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21154 +Rp21155 +(dp21156 +g201 +g176 +(g177 +(I0 +tp21157 +g179 +tp21158 +Rp21159 +(I1 +(I2 +tp21160 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21161 +tp21162 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21163 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21164 +g179 +tp21165 +Rp21166 +(I1 +(I1 +I1 +I1 +tp21167 +g38 +I00 +S'%;\x7f\xb3\xf2\xd6N@' +p21168 +tp21169 +bsg238 +g176 +(g177 +(I0 +tp21170 +g179 +tp21171 +Rp21172 +(I1 +(I1 +I1 +I1 +tp21173 +g38 +I00 +S'\x8c\xe2\xb7\xbbtbV?' +p21174 +tp21175 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21176 +g179 +tp21177 +Rp21178 +(I1 +(I1 +I1 +I1 +tp21179 +g38 +I00 +S'o\xf7\xb4\xd5\xdf|\xea?' +p21180 +tp21181 +bsg252 +g260 +sg48 +(lp21182 +g0 +(g52 +g2 +Ntp21183 +Rp21184 +(dp21185 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21186 +g179 +tp21187 +Rp21188 +(I1 +(I1 +I1 +I1 +tp21189 +g38 +I00 +S'\xfa=Cb\xcd\x9fR@' +p21190 +tp21191 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21192 +g334 +asg113 +I10675 +sg280 +I01 +sbaatp21193 +Rp21194 +sg337 +I00 +sg338 +Nsbaa(lp21195 +g340 +ag0 +(g341 +g2 +Ntp21196 +Rp21197 +(dp21198 +g17 +g21064 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21199 +(lp21200 +g189 +ag0 +(g190 +g2 +Ntp21201 +Rp21202 +(dp21203 +g194 +I01 +sg195 +(lp21204 +g0 +(g197 +g2 +Ntp21205 +Rp21206 +(dp21207 +g201 +g176 +(g177 +(I0 +tp21208 +g179 +tp21209 +Rp21210 +(I1 +(I1 +tp21211 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21212 +tp21213 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21214 +Rp21215 +(dp21216 +g201 +g176 +(g177 +(I0 +tp21217 +g179 +tp21218 +Rp21219 +(I1 +(I2 +tp21220 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21221 +tp21222 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21223 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21224 +g179 +tp21225 +Rp21226 +(I1 +(I1 +I1 +I1 +tp21227 +g38 +I00 +S'\x80S\xea\xef\xecqI@' +p21228 +tp21229 +bsg238 +g176 +(g177 +(I0 +tp21230 +g179 +tp21231 +Rp21232 +(I1 +(I1 +I1 +I1 +tp21233 +g38 +I00 +S'5\xb5\x07\xbb\x82SK?' +p21234 +tp21235 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21236 +g179 +tp21237 +Rp21238 +(I1 +(I1 +I1 +I1 +tp21239 +g38 +I00 +S'zX$\x9e\xb9\x0f\xe8?' +p21240 +tp21241 +bsg252 +g260 +sg48 +(lp21242 +g0 +(g52 +g2 +Ntp21243 +Rp21244 +(dp21245 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21246 +g179 +tp21247 +Rp21248 +(I1 +(I1 +I1 +I1 +tp21249 +g38 +I00 +S'6\x8e1\x83\x0e\xebP@' +p21250 +tp21251 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21252 +g279 +asg113 +I10678 +sg280 +I01 +sbaa(lp21253 +g401 +ag0 +(g190 +g2 +Ntp21254 +Rp21255 +(dp21256 +g194 +I01 +sg195 +(lp21257 +g0 +(g197 +g2 +Ntp21258 +Rp21259 +(dp21260 +g201 +g176 +(g177 +(I0 +tp21261 +g179 +tp21262 +Rp21263 +(I1 +(I1 +tp21264 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21265 +tp21266 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21267 +Rp21268 +(dp21269 +g201 +g176 +(g177 +(I0 +tp21270 +g179 +tp21271 +Rp21272 +(I1 +(I2 +tp21273 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21274 +tp21275 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21276 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21277 +g179 +tp21278 +Rp21279 +(I1 +(I1 +I1 +I1 +tp21280 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21281 +tp21282 +bsg238 +g176 +(g177 +(I0 +tp21283 +g179 +tp21284 +Rp21285 +(I1 +(I1 +I1 +I1 +tp21286 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21287 +tp21288 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21289 +g179 +tp21290 +Rp21291 +(I1 +(I1 +I1 +I1 +tp21292 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21293 +tp21294 +bsg252 +g260 +sg48 +(lp21295 +g0 +(g52 +g2 +Ntp21296 +Rp21297 +(dp21298 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21299 +g179 +tp21300 +Rp21301 +(I1 +(I1 +I1 +I1 +tp21302 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21303 +tp21304 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21305 +g454 +asg113 +I10679 +sg280 +I01 +sbaatp21306 +Rp21307 +sg337 +I00 +sg338 +Nsbaa(lp21308 +g458 +ag0 +(g459 +g2 +Ntp21309 +Rp21310 +(dp21311 +g17 +g21064 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21312 +(lp21313 +g189 +ag0 +(g190 +g2 +Ntp21314 +Rp21315 +(dp21316 +g194 +I01 +sg195 +(lp21317 +g0 +(g197 +g2 +Ntp21318 +Rp21319 +(dp21320 +g201 +g176 +(g177 +(I0 +tp21321 +g179 +tp21322 +Rp21323 +(I1 +(I1 +tp21324 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21325 +tp21326 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21327 +Rp21328 +(dp21329 +g201 +g176 +(g177 +(I0 +tp21330 +g179 +tp21331 +Rp21332 +(I1 +(I2 +tp21333 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21334 +tp21335 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp21336 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21337 +g179 +tp21338 +Rp21339 +(I1 +(I1 +I1 +I1 +tp21340 +g38 +I00 +S'\xc0\x11~\xbe\xf7\x90I@' +p21341 +tp21342 +bsg238 +g176 +(g177 +(I0 +tp21343 +g179 +tp21344 +Rp21345 +(I1 +(I1 +I1 +I1 +tp21346 +g38 +I00 +S'5\x1a\xf17\xfe\xddW?' +p21347 +tp21348 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21349 +g179 +tp21350 +Rp21351 +(I1 +(I1 +I1 +I1 +tp21352 +g38 +I00 +S'\xef\x00\xff@\xb2\x1d\xe8?' +p21353 +tp21354 +bsg252 +g513 +sg48 +(lp21355 +g0 +(g52 +g2 +Ntp21356 +Rp21357 +(dp21358 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp21359 +g179 +tp21360 +Rp21361 +(I1 +(I1 +I1 +I1 +tp21362 +g38 +I00 +S'\xa8L\xb3U\xe1\xf4P@' +p21363 +tp21364 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp21365 +g527 +asg113 +I10682 +sg280 +I01 +sbaa(lp21366 +g529 +ag0 +(g190 +g2 +Ntp21367 +Rp21368 +(dp21369 +g194 +I01 +sg195 +(lp21370 +g0 +(g197 +g2 +Ntp21371 +Rp21372 +(dp21373 +g201 +g176 +(g177 +(I0 +tp21374 +g179 +tp21375 +Rp21376 +(I1 +(I1 +tp21377 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21378 +tp21379 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21380 +Rp21381 +(dp21382 +g201 +g176 +(g177 +(I0 +tp21383 +g179 +tp21384 +Rp21385 +(I1 +(I2 +tp21386 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21387 +tp21388 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21389 +Rp21390 +(dp21391 +g201 +g176 +(g177 +(I0 +tp21392 +g179 +tp21393 +Rp21394 +(I1 +(I2 +tp21395 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21396 +tp21397 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp21398 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21399 +g179 +tp21400 +Rp21401 +(I1 +(I1 +I1 +I1 +tp21402 +g38 +I00 +S'0\xb5\x089-2N@' +p21403 +tp21404 +bsg238 +g176 +(g177 +(I0 +tp21405 +g179 +tp21406 +Rp21407 +(I1 +(I1 +I1 +I1 +tp21408 +g38 +I00 +S'\x0c\xf4\xa8Ck\xf9[?' +p21409 +tp21410 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21411 +g179 +tp21412 +Rp21413 +(I1 +(I1 +I1 +I1 +tp21414 +g38 +I00 +S',\x84s\xd1A5\xea?' +p21415 +tp21416 +bsg252 +g586 +sg48 +(lp21417 +g0 +(g52 +g2 +Ntp21418 +Rp21419 +(dp21420 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp21421 +g179 +tp21422 +Rp21423 +(I1 +(I1 +I1 +I1 +tp21424 +g38 +I00 +S'\xef8EGrmR@' +p21425 +tp21426 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp21427 +g600 +asg113 +I10683 +sg280 +I01 +sbaatp21428 +Rp21429 +sg337 +I00 +sg338 +Nsbaa(lp21430 +g604 +ag0 +(g605 +g2 +Ntp21431 +Rp21432 +(dp21433 +g17 +g21064 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21434 +(lp21435 +g611 +ag0 +(g190 +g2 +Ntp21436 +Rp21437 +(dp21438 +g194 +I01 +sg195 +(lp21439 +g0 +(g197 +g2 +Ntp21440 +Rp21441 +(dp21442 +g201 +g176 +(g177 +(I0 +tp21443 +g179 +tp21444 +Rp21445 +(I1 +(I1 +tp21446 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21447 +tp21448 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21449 +Rp21450 +(dp21451 +g201 +g176 +(g177 +(I0 +tp21452 +g179 +tp21453 +Rp21454 +(I1 +(I2 +tp21455 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21456 +tp21457 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp21458 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21459 +g179 +tp21460 +Rp21461 +(I1 +(I1 +I1 +I1 +tp21462 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21463 +tp21464 +bsg238 +g176 +(g177 +(I0 +tp21465 +g179 +tp21466 +Rp21467 +(I1 +(I1 +I1 +I1 +tp21468 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21469 +tp21470 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21471 +g179 +tp21472 +Rp21473 +(I1 +(I1 +I1 +I1 +tp21474 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21475 +tp21476 +bsg252 +g513 +sg48 +(lp21477 +g0 +(g52 +g2 +Ntp21478 +Rp21479 +(dp21480 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp21481 +g179 +tp21482 +Rp21483 +(I1 +(I1 +I1 +I1 +tp21484 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21485 +tp21486 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp21487 +g664 +asg113 +I10686 +sg280 +I01 +sbaa(lp21488 +g666 +ag0 +(g190 +g2 +Ntp21489 +Rp21490 +(dp21491 +g194 +I01 +sg195 +(lp21492 +g0 +(g197 +g2 +Ntp21493 +Rp21494 +(dp21495 +g201 +g176 +(g177 +(I0 +tp21496 +g179 +tp21497 +Rp21498 +(I1 +(I1 +tp21499 +g208 +I00 +S";'\x00\x00\x00\x00\x00\x00" +p21500 +tp21501 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21502 +Rp21503 +(dp21504 +g201 +g176 +(g177 +(I0 +tp21505 +g179 +tp21506 +Rp21507 +(I1 +(I2 +tp21508 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21509 +tp21510 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp21511 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21512 +g179 +tp21513 +Rp21514 +(I1 +(I1 +I1 +I1 +tp21515 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21516 +tp21517 +bsg238 +g176 +(g177 +(I0 +tp21518 +g179 +tp21519 +Rp21520 +(I1 +(I1 +I1 +I1 +tp21521 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21522 +tp21523 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21524 +g179 +tp21525 +Rp21526 +(I1 +(I1 +I1 +I1 +tp21527 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21528 +tp21529 +bsg252 +g713 +sg48 +(lp21530 +g0 +(g52 +g2 +Ntp21531 +Rp21532 +(dp21533 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp21534 +g179 +tp21535 +Rp21536 +(I1 +(I1 +I1 +I1 +tp21537 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21538 +tp21539 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp21540 +g727 +asg113 +I10687 +sg280 +I01 +sbaatp21541 +Rp21542 +sg337 +I00 +sg338 +Nsbaatp21543 +Rp21544 +aa(lp21545 +I10044 +ag7 +((lp21546 +(lp21547 +g12 +ag0 +(g13 +g2 +Ntp21548 +Rp21549 +(dp21550 +g17 +g0 +(g18 +g2 +Ntp21551 +Rp21552 +(dp21553 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p21554 +sg116 +g0 +(g117 +g2 +Ntp21555 +Rp21556 +(dp21557 +g121 +(lp21558 +g0 +(g123 +g2 +Ntp21559 +Rp21560 +(dp21561 +g127 +g0 +(g128 +g2 +Ntp21562 +Rp21563 +(dp21564 +g23 +g132 +sg133 +(dp21565 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'R\xb8\x1e\x85\xebQ\x00@' +p21566 +tp21567 +Rp21568 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p21569 +sg113 +I73 +sg146 +(lp21570 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp21571 +Rp21572 +(dp21573 +g127 +g11246 +sg148 +g149 +sbasbsg163 +Nsg113 +I10044 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21574 +(lp21575 +g189 +ag0 +(g190 +g2 +Ntp21576 +Rp21577 +(dp21578 +g194 +I01 +sg195 +(lp21579 +g0 +(g197 +g2 +Ntp21580 +Rp21581 +(dp21582 +g201 +g176 +(g177 +(I0 +tp21583 +g179 +tp21584 +Rp21585 +(I1 +(I1 +tp21586 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21587 +tp21588 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21589 +Rp21590 +(dp21591 +g201 +g176 +(g177 +(I0 +tp21592 +g179 +tp21593 +Rp21594 +(I1 +(I2 +tp21595 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21596 +tp21597 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21598 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21599 +g179 +tp21600 +Rp21601 +(I1 +(I1 +I1 +I1 +tp21602 +g38 +I00 +S'\xe5\xe6\xb8Z:\xe4\x0e@' +p21603 +tp21604 +bsg238 +g176 +(g177 +(I0 +tp21605 +g179 +tp21606 +Rp21607 +(I1 +(I1 +I1 +I1 +tp21608 +g38 +I00 +S'6\tU\xb9\xbe"+?' +p21609 +tp21610 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21611 +g179 +tp21612 +Rp21613 +(I1 +(I1 +I1 +I1 +tp21614 +g38 +I00 +S'"G\x89\x8d\x18\x83\xca?' +p21615 +tp21616 +bsg252 +g260 +sg48 +(lp21617 +g0 +(g52 +g2 +Ntp21618 +Rp21619 +(dp21620 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21621 +g179 +tp21622 +Rp21623 +(I1 +(I1 +I1 +I1 +tp21624 +g38 +I00 +S'\x04\x86\x84C-\xa42@' +p21625 +tp21626 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21627 +g279 +asg113 +I10690 +sg280 +I01 +sbaa(lp21628 +g12 +ag0 +(g190 +g2 +Ntp21629 +Rp21630 +(dp21631 +g194 +I01 +sg195 +(lp21632 +g0 +(g197 +g2 +Ntp21633 +Rp21634 +(dp21635 +g201 +g176 +(g177 +(I0 +tp21636 +g179 +tp21637 +Rp21638 +(I1 +(I1 +tp21639 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21640 +tp21641 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21642 +Rp21643 +(dp21644 +g201 +g176 +(g177 +(I0 +tp21645 +g179 +tp21646 +Rp21647 +(I1 +(I2 +tp21648 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21649 +tp21650 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21651 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21652 +g179 +tp21653 +Rp21654 +(I1 +(I1 +I1 +I1 +tp21655 +g38 +I00 +S'\r\x0c\xee\xfd\x1d\xba\xd7?' +p21656 +tp21657 +bsg238 +g176 +(g177 +(I0 +tp21658 +g179 +tp21659 +Rp21660 +(I1 +(I1 +I1 +I1 +tp21661 +g38 +I00 +S'"P\xdblv\x81\x11?' +p21662 +tp21663 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21664 +g179 +tp21665 +Rp21666 +(I1 +(I1 +I1 +I1 +tp21667 +g38 +I00 +S'gC\x90=\x00n\xb0?' +p21668 +tp21669 +bsg252 +g260 +sg48 +(lp21670 +g0 +(g52 +g2 +Ntp21671 +Rp21672 +(dp21673 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21674 +g179 +tp21675 +Rp21676 +(I1 +(I1 +I1 +I1 +tp21677 +g38 +I00 +S'\xc9\xde\x92V\xb0\x1a\x17@' +p21678 +tp21679 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21680 +g334 +asg113 +I10691 +sg280 +I01 +sbaatp21681 +Rp21682 +sg337 +I00 +sg338 +Nsbaa(lp21683 +g340 +ag0 +(g341 +g2 +Ntp21684 +Rp21685 +(dp21686 +g17 +g21552 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21687 +(lp21688 +g189 +ag0 +(g190 +g2 +Ntp21689 +Rp21690 +(dp21691 +g194 +I01 +sg195 +(lp21692 +g0 +(g197 +g2 +Ntp21693 +Rp21694 +(dp21695 +g201 +g176 +(g177 +(I0 +tp21696 +g179 +tp21697 +Rp21698 +(I1 +(I1 +tp21699 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21700 +tp21701 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21702 +Rp21703 +(dp21704 +g201 +g176 +(g177 +(I0 +tp21705 +g179 +tp21706 +Rp21707 +(I1 +(I2 +tp21708 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21709 +tp21710 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21711 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21712 +g179 +tp21713 +Rp21714 +(I1 +(I1 +I1 +I1 +tp21715 +g38 +I00 +S'\xe5\xe6\xb8Z:\xe4\x0e@' +p21716 +tp21717 +bsg238 +g176 +(g177 +(I0 +tp21718 +g179 +tp21719 +Rp21720 +(I1 +(I1 +I1 +I1 +tp21721 +g38 +I00 +S'6\tU\xb9\xbe"+?' +p21722 +tp21723 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21724 +g179 +tp21725 +Rp21726 +(I1 +(I1 +I1 +I1 +tp21727 +g38 +I00 +S'"G\x89\x8d\x18\x83\xca?' +p21728 +tp21729 +bsg252 +g260 +sg48 +(lp21730 +g0 +(g52 +g2 +Ntp21731 +Rp21732 +(dp21733 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21734 +g179 +tp21735 +Rp21736 +(I1 +(I1 +I1 +I1 +tp21737 +g38 +I00 +S'\x04\x86\x84C-\xa42@' +p21738 +tp21739 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21740 +g279 +asg113 +I10694 +sg280 +I01 +sbaa(lp21741 +g401 +ag0 +(g190 +g2 +Ntp21742 +Rp21743 +(dp21744 +g194 +I01 +sg195 +(lp21745 +g0 +(g197 +g2 +Ntp21746 +Rp21747 +(dp21748 +g201 +g176 +(g177 +(I0 +tp21749 +g179 +tp21750 +Rp21751 +(I1 +(I1 +tp21752 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21753 +tp21754 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21755 +Rp21756 +(dp21757 +g201 +g176 +(g177 +(I0 +tp21758 +g179 +tp21759 +Rp21760 +(I1 +(I2 +tp21761 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21762 +tp21763 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp21764 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21765 +g179 +tp21766 +Rp21767 +(I1 +(I1 +I1 +I1 +tp21768 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21769 +tp21770 +bsg238 +g176 +(g177 +(I0 +tp21771 +g179 +tp21772 +Rp21773 +(I1 +(I1 +I1 +I1 +tp21774 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21775 +tp21776 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21777 +g179 +tp21778 +Rp21779 +(I1 +(I1 +I1 +I1 +tp21780 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21781 +tp21782 +bsg252 +g260 +sg48 +(lp21783 +g0 +(g52 +g2 +Ntp21784 +Rp21785 +(dp21786 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp21787 +g179 +tp21788 +Rp21789 +(I1 +(I1 +I1 +I1 +tp21790 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21791 +tp21792 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp21793 +g454 +asg113 +I10695 +sg280 +I01 +sbaatp21794 +Rp21795 +sg337 +I00 +sg338 +Nsbaa(lp21796 +g458 +ag0 +(g459 +g2 +Ntp21797 +Rp21798 +(dp21799 +g17 +g21552 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21800 +(lp21801 +g189 +ag0 +(g190 +g2 +Ntp21802 +Rp21803 +(dp21804 +g194 +I01 +sg195 +(lp21805 +g0 +(g197 +g2 +Ntp21806 +Rp21807 +(dp21808 +g201 +g176 +(g177 +(I0 +tp21809 +g179 +tp21810 +Rp21811 +(I1 +(I1 +tp21812 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21813 +tp21814 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21815 +Rp21816 +(dp21817 +g201 +g176 +(g177 +(I0 +tp21818 +g179 +tp21819 +Rp21820 +(I1 +(I2 +tp21821 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21822 +tp21823 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp21824 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21825 +g179 +tp21826 +Rp21827 +(I1 +(I1 +I1 +I1 +tp21828 +g38 +I00 +S"\x90[m'\xa7\x10\x0f@" +p21829 +tp21830 +bsg238 +g176 +(g177 +(I0 +tp21831 +g179 +tp21832 +Rp21833 +(I1 +(I1 +I1 +I1 +tp21834 +g38 +I00 +S'\xed\x9c\xb3\xa8\x8f\xb4H?' +p21835 +tp21836 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21837 +g179 +tp21838 +Rp21839 +(I1 +(I1 +I1 +I1 +tp21840 +g38 +I00 +S'\x15`\xf9\x93q\x92\xca?' +p21841 +tp21842 +bsg252 +g513 +sg48 +(lp21843 +g0 +(g52 +g2 +Ntp21844 +Rp21845 +(dp21846 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp21847 +g179 +tp21848 +Rp21849 +(I1 +(I1 +I1 +I1 +tp21850 +g38 +I00 +S'\x8fW\x0b\xdc\xf7\xae2@' +p21851 +tp21852 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp21853 +g527 +asg113 +I10698 +sg280 +I01 +sbaa(lp21854 +g529 +ag0 +(g190 +g2 +Ntp21855 +Rp21856 +(dp21857 +g194 +I01 +sg195 +(lp21858 +g0 +(g197 +g2 +Ntp21859 +Rp21860 +(dp21861 +g201 +g176 +(g177 +(I0 +tp21862 +g179 +tp21863 +Rp21864 +(I1 +(I1 +tp21865 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21866 +tp21867 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21868 +Rp21869 +(dp21870 +g201 +g176 +(g177 +(I0 +tp21871 +g179 +tp21872 +Rp21873 +(I1 +(I2 +tp21874 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21875 +tp21876 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21877 +Rp21878 +(dp21879 +g201 +g176 +(g177 +(I0 +tp21880 +g179 +tp21881 +Rp21882 +(I1 +(I2 +tp21883 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21884 +tp21885 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp21886 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21887 +g179 +tp21888 +Rp21889 +(I1 +(I1 +I1 +I1 +tp21890 +g38 +I00 +S'\x83\xfb+\xd8\x04\xa0\xd7?' +p21891 +tp21892 +bsg238 +g176 +(g177 +(I0 +tp21893 +g179 +tp21894 +Rp21895 +(I1 +(I1 +I1 +I1 +tp21896 +g38 +I00 +S'\xa8q\xc4\x17oD-?' +p21897 +tp21898 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21899 +g179 +tp21900 +Rp21901 +(I1 +(I1 +I1 +I1 +tp21902 +g38 +I00 +S'\xf7Zn\xf4\xe2b\xb0?' +p21903 +tp21904 +bsg252 +g586 +sg48 +(lp21905 +g0 +(g52 +g2 +Ntp21906 +Rp21907 +(dp21908 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp21909 +g179 +tp21910 +Rp21911 +(I1 +(I1 +I1 +I1 +tp21912 +g38 +I00 +S"\xeb/\xbb'\x0f\x0b\x17@" +p21913 +tp21914 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp21915 +g600 +asg113 +I10699 +sg280 +I01 +sbaatp21916 +Rp21917 +sg337 +I00 +sg338 +Nsbaa(lp21918 +g604 +ag0 +(g605 +g2 +Ntp21919 +Rp21920 +(dp21921 +g17 +g21552 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp21922 +(lp21923 +g611 +ag0 +(g190 +g2 +Ntp21924 +Rp21925 +(dp21926 +g194 +I01 +sg195 +(lp21927 +g0 +(g197 +g2 +Ntp21928 +Rp21929 +(dp21930 +g201 +g176 +(g177 +(I0 +tp21931 +g179 +tp21932 +Rp21933 +(I1 +(I1 +tp21934 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21935 +tp21936 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21937 +Rp21938 +(dp21939 +g201 +g176 +(g177 +(I0 +tp21940 +g179 +tp21941 +Rp21942 +(I1 +(I2 +tp21943 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21944 +tp21945 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp21946 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp21947 +g179 +tp21948 +Rp21949 +(I1 +(I1 +I1 +I1 +tp21950 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21951 +tp21952 +bsg238 +g176 +(g177 +(I0 +tp21953 +g179 +tp21954 +Rp21955 +(I1 +(I1 +I1 +I1 +tp21956 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21957 +tp21958 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp21959 +g179 +tp21960 +Rp21961 +(I1 +(I1 +I1 +I1 +tp21962 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21963 +tp21964 +bsg252 +g513 +sg48 +(lp21965 +g0 +(g52 +g2 +Ntp21966 +Rp21967 +(dp21968 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp21969 +g179 +tp21970 +Rp21971 +(I1 +(I1 +I1 +I1 +tp21972 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p21973 +tp21974 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp21975 +g664 +asg113 +I10702 +sg280 +I01 +sbaa(lp21976 +g666 +ag0 +(g190 +g2 +Ntp21977 +Rp21978 +(dp21979 +g194 +I01 +sg195 +(lp21980 +g0 +(g197 +g2 +Ntp21981 +Rp21982 +(dp21983 +g201 +g176 +(g177 +(I0 +tp21984 +g179 +tp21985 +Rp21986 +(I1 +(I1 +tp21987 +g208 +I00 +S"<'\x00\x00\x00\x00\x00\x00" +p21988 +tp21989 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp21990 +Rp21991 +(dp21992 +g201 +g176 +(g177 +(I0 +tp21993 +g179 +tp21994 +Rp21995 +(I1 +(I2 +tp21996 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p21997 +tp21998 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp21999 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22000 +g179 +tp22001 +Rp22002 +(I1 +(I1 +I1 +I1 +tp22003 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22004 +tp22005 +bsg238 +g176 +(g177 +(I0 +tp22006 +g179 +tp22007 +Rp22008 +(I1 +(I1 +I1 +I1 +tp22009 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22010 +tp22011 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22012 +g179 +tp22013 +Rp22014 +(I1 +(I1 +I1 +I1 +tp22015 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22016 +tp22017 +bsg252 +g713 +sg48 +(lp22018 +g0 +(g52 +g2 +Ntp22019 +Rp22020 +(dp22021 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp22022 +g179 +tp22023 +Rp22024 +(I1 +(I1 +I1 +I1 +tp22025 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22026 +tp22027 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp22028 +g727 +asg113 +I10703 +sg280 +I01 +sbaatp22029 +Rp22030 +sg337 +I00 +sg338 +Nsbaatp22031 +Rp22032 +aa(lp22033 +I10045 +ag7 +((lp22034 +(lp22035 +g12 +ag0 +(g13 +g2 +Ntp22036 +Rp22037 +(dp22038 +g17 +g0 +(g18 +g2 +Ntp22039 +Rp22040 +(dp22041 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p22042 +sg116 +g0 +(g117 +g2 +Ntp22043 +Rp22044 +(dp22045 +g121 +(lp22046 +g0 +(g123 +g2 +Ntp22047 +Rp22048 +(dp22049 +g127 +g0 +(g128 +g2 +Ntp22050 +Rp22051 +(dp22052 +g23 +g132 +sg133 +(dp22053 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xf8?' +p22054 +tp22055 +Rp22056 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p22057 +sg113 +I74 +sg146 +(lp22058 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp22059 +Rp22060 +(dp22061 +g127 +g18635 +sg148 +g162 +sbasbsg163 +Nsg113 +I10045 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22062 +(lp22063 +g189 +ag0 +(g190 +g2 +Ntp22064 +Rp22065 +(dp22066 +g194 +I01 +sg195 +(lp22067 +g0 +(g197 +g2 +Ntp22068 +Rp22069 +(dp22070 +g201 +g176 +(g177 +(I0 +tp22071 +g179 +tp22072 +Rp22073 +(I1 +(I1 +tp22074 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22075 +tp22076 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22077 +Rp22078 +(dp22079 +g201 +g176 +(g177 +(I0 +tp22080 +g179 +tp22081 +Rp22082 +(I1 +(I2 +tp22083 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22084 +tp22085 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22086 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22087 +g179 +tp22088 +Rp22089 +(I1 +(I1 +I1 +I1 +tp22090 +g38 +I00 +S'\x15\xe3]H\xf8\x978@' +p22091 +tp22092 +bsg238 +g176 +(g177 +(I0 +tp22093 +g179 +tp22094 +Rp22095 +(I1 +(I1 +I1 +I1 +tp22096 +g38 +I00 +S'S(\x9d\xcd&\x9eB?' +p22097 +tp22098 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22099 +g179 +tp22100 +Rp22101 +(I1 +(I1 +I1 +I1 +tp22102 +g38 +I00 +S'\xe1\xed\x06\x95\x1a\xba\xe0?' +p22103 +tp22104 +bsg252 +g260 +sg48 +(lp22105 +g0 +(g52 +g2 +Ntp22106 +Rp22107 +(dp22108 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22109 +g179 +tp22110 +Rp22111 +(I1 +(I1 +I1 +I1 +tp22112 +g38 +I00 +S'\x85\xbe\x91a\xb5\x85G@' +p22113 +tp22114 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22115 +g279 +asg113 +I10706 +sg280 +I01 +sbaa(lp22116 +g12 +ag0 +(g190 +g2 +Ntp22117 +Rp22118 +(dp22119 +g194 +I01 +sg195 +(lp22120 +g0 +(g197 +g2 +Ntp22121 +Rp22122 +(dp22123 +g201 +g176 +(g177 +(I0 +tp22124 +g179 +tp22125 +Rp22126 +(I1 +(I1 +tp22127 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22128 +tp22129 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22130 +Rp22131 +(dp22132 +g201 +g176 +(g177 +(I0 +tp22133 +g179 +tp22134 +Rp22135 +(I1 +(I2 +tp22136 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22137 +tp22138 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22139 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22140 +g179 +tp22141 +Rp22142 +(I1 +(I1 +I1 +I1 +tp22143 +g38 +I00 +S'TV\x9a\xa9r\xbb\x10@' +p22144 +tp22145 +bsg238 +g176 +(g177 +(I0 +tp22146 +g179 +tp22147 +Rp22148 +(I1 +(I1 +I1 +I1 +tp22149 +g38 +I00 +S'\xfe\xb4\x8f\xbf|\xdf0?' +p22150 +tp22151 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22152 +g179 +tp22153 +Rp22154 +(I1 +(I1 +I1 +I1 +tp22155 +g38 +I00 +S'\x1f\xaaYN\xf4\x97\xcb?' +p22156 +tp22157 +bsg252 +g260 +sg48 +(lp22158 +g0 +(g52 +g2 +Ntp22159 +Rp22160 +(dp22161 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22162 +g179 +tp22163 +Rp22164 +(I1 +(I1 +I1 +I1 +tp22165 +g38 +I00 +S'\x9e\x0b\x17\xc7\xd7f3@' +p22166 +tp22167 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22168 +g334 +asg113 +I10707 +sg280 +I01 +sbaatp22169 +Rp22170 +sg337 +I00 +sg338 +Nsbaa(lp22171 +g340 +ag0 +(g341 +g2 +Ntp22172 +Rp22173 +(dp22174 +g17 +g22040 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22175 +(lp22176 +g189 +ag0 +(g190 +g2 +Ntp22177 +Rp22178 +(dp22179 +g194 +I01 +sg195 +(lp22180 +g0 +(g197 +g2 +Ntp22181 +Rp22182 +(dp22183 +g201 +g176 +(g177 +(I0 +tp22184 +g179 +tp22185 +Rp22186 +(I1 +(I1 +tp22187 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22188 +tp22189 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22190 +Rp22191 +(dp22192 +g201 +g176 +(g177 +(I0 +tp22193 +g179 +tp22194 +Rp22195 +(I1 +(I2 +tp22196 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22197 +tp22198 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22199 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22200 +g179 +tp22201 +Rp22202 +(I1 +(I1 +I1 +I1 +tp22203 +g38 +I00 +S'\x15\xe3]H\xf8\x978@' +p22204 +tp22205 +bsg238 +g176 +(g177 +(I0 +tp22206 +g179 +tp22207 +Rp22208 +(I1 +(I1 +I1 +I1 +tp22209 +g38 +I00 +S'S(\x9d\xcd&\x9eB?' +p22210 +tp22211 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22212 +g179 +tp22213 +Rp22214 +(I1 +(I1 +I1 +I1 +tp22215 +g38 +I00 +S'\xe1\xed\x06\x95\x1a\xba\xe0?' +p22216 +tp22217 +bsg252 +g260 +sg48 +(lp22218 +g0 +(g52 +g2 +Ntp22219 +Rp22220 +(dp22221 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22222 +g179 +tp22223 +Rp22224 +(I1 +(I1 +I1 +I1 +tp22225 +g38 +I00 +S'\x85\xbe\x91a\xb5\x85G@' +p22226 +tp22227 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22228 +g279 +asg113 +I10710 +sg280 +I01 +sbaa(lp22229 +g401 +ag0 +(g190 +g2 +Ntp22230 +Rp22231 +(dp22232 +g194 +I01 +sg195 +(lp22233 +g0 +(g197 +g2 +Ntp22234 +Rp22235 +(dp22236 +g201 +g176 +(g177 +(I0 +tp22237 +g179 +tp22238 +Rp22239 +(I1 +(I1 +tp22240 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22241 +tp22242 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22243 +Rp22244 +(dp22245 +g201 +g176 +(g177 +(I0 +tp22246 +g179 +tp22247 +Rp22248 +(I1 +(I2 +tp22249 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22250 +tp22251 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22252 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22253 +g179 +tp22254 +Rp22255 +(I1 +(I1 +I1 +I1 +tp22256 +g38 +I00 +S'G\xc0\xba\xb2\xfcM\xb1?' +p22257 +tp22258 +bsg238 +g176 +(g177 +(I0 +tp22259 +g179 +tp22260 +Rp22261 +(I1 +(I1 +I1 +I1 +tp22262 +g38 +I00 +S'\xcf \xf3\xf0\xe9\xcd\x0f?' +p22263 +tp22264 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22265 +g179 +tp22266 +Rp22267 +(I1 +(I1 +I1 +I1 +tp22268 +g38 +I00 +S'\x98\x16!\x99\xa8\x0e\x9c?' +p22269 +tp22270 +bsg252 +g260 +sg48 +(lp22271 +g0 +(g52 +g2 +Ntp22272 +Rp22273 +(dp22274 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22275 +g179 +tp22276 +Rp22277 +(I1 +(I1 +I1 +I1 +tp22278 +g38 +I00 +S'\xe3C\xab\x8bN\xba\x03@' +p22279 +tp22280 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22281 +g454 +asg113 +I10711 +sg280 +I01 +sbaatp22282 +Rp22283 +sg337 +I00 +sg338 +Nsbaa(lp22284 +g458 +ag0 +(g459 +g2 +Ntp22285 +Rp22286 +(dp22287 +g17 +g22040 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22288 +(lp22289 +g189 +ag0 +(g190 +g2 +Ntp22290 +Rp22291 +(dp22292 +g194 +I01 +sg195 +(lp22293 +g0 +(g197 +g2 +Ntp22294 +Rp22295 +(dp22296 +g201 +g176 +(g177 +(I0 +tp22297 +g179 +tp22298 +Rp22299 +(I1 +(I1 +tp22300 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22301 +tp22302 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22303 +Rp22304 +(dp22305 +g201 +g176 +(g177 +(I0 +tp22306 +g179 +tp22307 +Rp22308 +(I1 +(I2 +tp22309 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22310 +tp22311 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp22312 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22313 +g179 +tp22314 +Rp22315 +(I1 +(I1 +I1 +I1 +tp22316 +g38 +I00 +S'\xed\xd3\xfb\x95wc8@' +p22317 +tp22318 +bsg238 +g176 +(g177 +(I0 +tp22319 +g179 +tp22320 +Rp22321 +(I1 +(I1 +I1 +I1 +tp22322 +g38 +I00 +S' \x8a\xc5\x8d\x04/V?' +p22323 +tp22324 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22325 +g179 +tp22326 +Rp22327 +(I1 +(I1 +I1 +I1 +tp22328 +g38 +I00 +S'\xde\xfdn\xf5&\xa7\xe0?' +p22329 +tp22330 +bsg252 +g513 +sg48 +(lp22331 +g0 +(g52 +g2 +Ntp22332 +Rp22333 +(dp22334 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp22335 +g179 +tp22336 +Rp22337 +(I1 +(I1 +I1 +I1 +tp22338 +g38 +I00 +S'\x00\x15$\xc9\x0ekG@' +p22339 +tp22340 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp22341 +g527 +asg113 +I10714 +sg280 +I01 +sbaa(lp22342 +g529 +ag0 +(g190 +g2 +Ntp22343 +Rp22344 +(dp22345 +g194 +I01 +sg195 +(lp22346 +g0 +(g197 +g2 +Ntp22347 +Rp22348 +(dp22349 +g201 +g176 +(g177 +(I0 +tp22350 +g179 +tp22351 +Rp22352 +(I1 +(I1 +tp22353 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22354 +tp22355 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22356 +Rp22357 +(dp22358 +g201 +g176 +(g177 +(I0 +tp22359 +g179 +tp22360 +Rp22361 +(I1 +(I2 +tp22362 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22363 +tp22364 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22365 +Rp22366 +(dp22367 +g201 +g176 +(g177 +(I0 +tp22368 +g179 +tp22369 +Rp22370 +(I1 +(I2 +tp22371 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22372 +tp22373 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp22374 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22375 +g179 +tp22376 +Rp22377 +(I1 +(I1 +I1 +I1 +tp22378 +g38 +I00 +S'\xdaTq>\xd0\x9d\x0b@' +p22379 +tp22380 +bsg238 +g176 +(g177 +(I0 +tp22381 +g179 +tp22382 +Rp22383 +(I1 +(I1 +I1 +I1 +tp22384 +g38 +I00 +S'0\xe5\xff\x0e\xad\xa0??' +p22385 +tp22386 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22387 +g179 +tp22388 +Rp22389 +(I1 +(I1 +I1 +I1 +tp22390 +g38 +I00 +S'\xebM\xd0\xd7\xca\x0f\xc9?' +p22391 +tp22392 +bsg252 +g586 +sg48 +(lp22393 +g0 +(g52 +g2 +Ntp22394 +Rp22395 +(dp22396 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp22397 +g179 +tp22398 +Rp22399 +(I1 +(I1 +I1 +I1 +tp22400 +g38 +I00 +S'\xc9v\xbe\x9f\x1a\x9f1@' +p22401 +tp22402 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp22403 +g600 +asg113 +I10715 +sg280 +I01 +sbaatp22404 +Rp22405 +sg337 +I00 +sg338 +Nsbaa(lp22406 +g604 +ag0 +(g605 +g2 +Ntp22407 +Rp22408 +(dp22409 +g17 +g22040 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22410 +(lp22411 +g611 +ag0 +(g190 +g2 +Ntp22412 +Rp22413 +(dp22414 +g194 +I01 +sg195 +(lp22415 +g0 +(g197 +g2 +Ntp22416 +Rp22417 +(dp22418 +g201 +g176 +(g177 +(I0 +tp22419 +g179 +tp22420 +Rp22421 +(I1 +(I1 +tp22422 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22423 +tp22424 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22425 +Rp22426 +(dp22427 +g201 +g176 +(g177 +(I0 +tp22428 +g179 +tp22429 +Rp22430 +(I1 +(I2 +tp22431 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22432 +tp22433 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp22434 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22435 +g179 +tp22436 +Rp22437 +(I1 +(I1 +I1 +I1 +tp22438 +g38 +I00 +S'F\xf8f\x0b\xf7\x89\xb1?' +p22439 +tp22440 +bsg238 +g176 +(g177 +(I0 +tp22441 +g179 +tp22442 +Rp22443 +(I1 +(I1 +I1 +I1 +tp22444 +g38 +I00 +S'\x98\xd5\xc7E\xde\x11/?' +p22445 +tp22446 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22447 +g179 +tp22448 +Rp22449 +(I1 +(I1 +I1 +I1 +tp22450 +g38 +I00 +S'\xb6\x84\xda(\xe6(\x9c?' +p22451 +tp22452 +bsg252 +g513 +sg48 +(lp22453 +g0 +(g52 +g2 +Ntp22454 +Rp22455 +(dp22456 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp22457 +g179 +tp22458 +Rp22459 +(I1 +(I1 +I1 +I1 +tp22460 +g38 +I00 +S'P\xa5\xb9\xd4\xc1\xcc\x03@' +p22461 +tp22462 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp22463 +g664 +asg113 +I10718 +sg280 +I01 +sbaa(lp22464 +g666 +ag0 +(g190 +g2 +Ntp22465 +Rp22466 +(dp22467 +g194 +I01 +sg195 +(lp22468 +g0 +(g197 +g2 +Ntp22469 +Rp22470 +(dp22471 +g201 +g176 +(g177 +(I0 +tp22472 +g179 +tp22473 +Rp22474 +(I1 +(I1 +tp22475 +g208 +I00 +S"='\x00\x00\x00\x00\x00\x00" +p22476 +tp22477 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22478 +Rp22479 +(dp22480 +g201 +g176 +(g177 +(I0 +tp22481 +g179 +tp22482 +Rp22483 +(I1 +(I2 +tp22484 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22485 +tp22486 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp22487 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22488 +g179 +tp22489 +Rp22490 +(I1 +(I1 +I1 +I1 +tp22491 +g38 +I00 +S'E\xf8f\x0b\xf7\x89\xb1?' +p22492 +tp22493 +bsg238 +g176 +(g177 +(I0 +tp22494 +g179 +tp22495 +Rp22496 +(I1 +(I1 +I1 +I1 +tp22497 +g38 +I00 +S'\xa2\xd2\xc7E\xde\x11/?' +p22498 +tp22499 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22500 +g179 +tp22501 +Rp22502 +(I1 +(I1 +I1 +I1 +tp22503 +g38 +I00 +S'\xba\x84\xda(\xe6(\x9c?' +p22504 +tp22505 +bsg252 +g713 +sg48 +(lp22506 +g0 +(g52 +g2 +Ntp22507 +Rp22508 +(dp22509 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp22510 +g179 +tp22511 +Rp22512 +(I1 +(I1 +I1 +I1 +tp22513 +g38 +I00 +S'S\xa5\xb9\xd4\xc1\xcc\x03@' +p22514 +tp22515 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp22516 +g727 +asg113 +I10719 +sg280 +I01 +sbaatp22517 +Rp22518 +sg337 +I00 +sg338 +Nsbaatp22519 +Rp22520 +aa(lp22521 +I10046 +ag7 +((lp22522 +(lp22523 +g12 +ag0 +(g13 +g2 +Ntp22524 +Rp22525 +(dp22526 +g17 +g0 +(g18 +g2 +Ntp22527 +Rp22528 +(dp22529 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p22530 +sg116 +g0 +(g117 +g2 +Ntp22531 +Rp22532 +(dp22533 +g121 +(lp22534 +g0 +(g123 +g2 +Ntp22535 +Rp22536 +(dp22537 +g127 +g15195 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp22538 +Rp22539 +(dp22540 +g127 +g16647 +sg148 +g162 +sbasbsg163 +Nsg113 +I10046 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22541 +(lp22542 +g189 +ag0 +(g190 +g2 +Ntp22543 +Rp22544 +(dp22545 +g194 +I01 +sg195 +(lp22546 +g0 +(g197 +g2 +Ntp22547 +Rp22548 +(dp22549 +g201 +g176 +(g177 +(I0 +tp22550 +g179 +tp22551 +Rp22552 +(I1 +(I1 +tp22553 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22554 +tp22555 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22556 +Rp22557 +(dp22558 +g201 +g176 +(g177 +(I0 +tp22559 +g179 +tp22560 +Rp22561 +(I1 +(I2 +tp22562 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22563 +tp22564 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22565 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22566 +g179 +tp22567 +Rp22568 +(I1 +(I1 +I1 +I1 +tp22569 +g38 +I00 +S'I\x06"\x18\x04Q\x0e@' +p22570 +tp22571 +bsg238 +g176 +(g177 +(I0 +tp22572 +g179 +tp22573 +Rp22574 +(I1 +(I1 +I1 +I1 +tp22575 +g38 +I00 +S'\x03t\x7f\x9b\xb5\xbb)?' +p22576 +tp22577 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22578 +g179 +tp22579 +Rp22580 +(I1 +(I1 +I1 +I1 +tp22581 +g38 +I00 +S'K\xc804\xa7C\xca?' +p22582 +tp22583 +bsg252 +g260 +sg48 +(lp22584 +g0 +(g52 +g2 +Ntp22585 +Rp22586 +(dp22587 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22588 +g179 +tp22589 +Rp22590 +(I1 +(I1 +I1 +I1 +tp22591 +g38 +I00 +S'\xd5L\xb2\x90\x91w2@' +p22592 +tp22593 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22594 +g279 +asg113 +I10722 +sg280 +I01 +sbaa(lp22595 +g12 +ag0 +(g190 +g2 +Ntp22596 +Rp22597 +(dp22598 +g194 +I01 +sg195 +(lp22599 +g0 +(g197 +g2 +Ntp22600 +Rp22601 +(dp22602 +g201 +g176 +(g177 +(I0 +tp22603 +g179 +tp22604 +Rp22605 +(I1 +(I1 +tp22606 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22607 +tp22608 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22609 +Rp22610 +(dp22611 +g201 +g176 +(g177 +(I0 +tp22612 +g179 +tp22613 +Rp22614 +(I1 +(I2 +tp22615 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22616 +tp22617 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22618 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22619 +g179 +tp22620 +Rp22621 +(I1 +(I1 +I1 +I1 +tp22622 +g38 +I00 +S'\xf2\xbbR\x96\xc7\x18\xd7?' +p22623 +tp22624 +bsg238 +g176 +(g177 +(I0 +tp22625 +g179 +tp22626 +Rp22627 +(I1 +(I1 +I1 +I1 +tp22628 +g38 +I00 +S'\x82\x98;\x8b\x92\xed\x10?' +p22629 +tp22630 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22631 +g179 +tp22632 +Rp22633 +(I1 +(I1 +I1 +I1 +tp22634 +g38 +I00 +S')\xa8\x8a*\xc65\xb0?' +p22635 +tp22636 +bsg252 +g260 +sg48 +(lp22637 +g0 +(g52 +g2 +Ntp22638 +Rp22639 +(dp22640 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22641 +g179 +tp22642 +Rp22643 +(I1 +(I1 +I1 +I1 +tp22644 +g38 +I00 +S'z\xfc\xd2\xab\x9e\xcb\x16@' +p22645 +tp22646 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22647 +g334 +asg113 +I10723 +sg280 +I01 +sbaatp22648 +Rp22649 +sg337 +I00 +sg338 +Nsbaa(lp22650 +g340 +ag0 +(g341 +g2 +Ntp22651 +Rp22652 +(dp22653 +g17 +g22528 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22654 +(lp22655 +g189 +ag0 +(g190 +g2 +Ntp22656 +Rp22657 +(dp22658 +g194 +I01 +sg195 +(lp22659 +g0 +(g197 +g2 +Ntp22660 +Rp22661 +(dp22662 +g201 +g176 +(g177 +(I0 +tp22663 +g179 +tp22664 +Rp22665 +(I1 +(I1 +tp22666 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22667 +tp22668 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22669 +Rp22670 +(dp22671 +g201 +g176 +(g177 +(I0 +tp22672 +g179 +tp22673 +Rp22674 +(I1 +(I2 +tp22675 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22676 +tp22677 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22678 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22679 +g179 +tp22680 +Rp22681 +(I1 +(I1 +I1 +I1 +tp22682 +g38 +I00 +S'I\x06"\x18\x04Q\x0e@' +p22683 +tp22684 +bsg238 +g176 +(g177 +(I0 +tp22685 +g179 +tp22686 +Rp22687 +(I1 +(I1 +I1 +I1 +tp22688 +g38 +I00 +S'\x03t\x7f\x9b\xb5\xbb)?' +p22689 +tp22690 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22691 +g179 +tp22692 +Rp22693 +(I1 +(I1 +I1 +I1 +tp22694 +g38 +I00 +S'K\xc804\xa7C\xca?' +p22695 +tp22696 +bsg252 +g260 +sg48 +(lp22697 +g0 +(g52 +g2 +Ntp22698 +Rp22699 +(dp22700 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22701 +g179 +tp22702 +Rp22703 +(I1 +(I1 +I1 +I1 +tp22704 +g38 +I00 +S'\xd5L\xb2\x90\x91w2@' +p22705 +tp22706 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22707 +g279 +asg113 +I10726 +sg280 +I01 +sbaa(lp22708 +g401 +ag0 +(g190 +g2 +Ntp22709 +Rp22710 +(dp22711 +g194 +I01 +sg195 +(lp22712 +g0 +(g197 +g2 +Ntp22713 +Rp22714 +(dp22715 +g201 +g176 +(g177 +(I0 +tp22716 +g179 +tp22717 +Rp22718 +(I1 +(I1 +tp22719 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22720 +tp22721 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22722 +Rp22723 +(dp22724 +g201 +g176 +(g177 +(I0 +tp22725 +g179 +tp22726 +Rp22727 +(I1 +(I2 +tp22728 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22729 +tp22730 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp22731 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22732 +g179 +tp22733 +Rp22734 +(I1 +(I1 +I1 +I1 +tp22735 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22736 +tp22737 +bsg238 +g176 +(g177 +(I0 +tp22738 +g179 +tp22739 +Rp22740 +(I1 +(I1 +I1 +I1 +tp22741 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22742 +tp22743 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22744 +g179 +tp22745 +Rp22746 +(I1 +(I1 +I1 +I1 +tp22747 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22748 +tp22749 +bsg252 +g260 +sg48 +(lp22750 +g0 +(g52 +g2 +Ntp22751 +Rp22752 +(dp22753 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp22754 +g179 +tp22755 +Rp22756 +(I1 +(I1 +I1 +I1 +tp22757 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22758 +tp22759 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp22760 +g454 +asg113 +I10727 +sg280 +I01 +sbaatp22761 +Rp22762 +sg337 +I00 +sg338 +Nsbaa(lp22763 +g458 +ag0 +(g459 +g2 +Ntp22764 +Rp22765 +(dp22766 +g17 +g22528 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22767 +(lp22768 +g189 +ag0 +(g190 +g2 +Ntp22769 +Rp22770 +(dp22771 +g194 +I01 +sg195 +(lp22772 +g0 +(g197 +g2 +Ntp22773 +Rp22774 +(dp22775 +g201 +g176 +(g177 +(I0 +tp22776 +g179 +tp22777 +Rp22778 +(I1 +(I1 +tp22779 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22780 +tp22781 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22782 +Rp22783 +(dp22784 +g201 +g176 +(g177 +(I0 +tp22785 +g179 +tp22786 +Rp22787 +(I1 +(I2 +tp22788 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22789 +tp22790 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp22791 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22792 +g179 +tp22793 +Rp22794 +(I1 +(I1 +I1 +I1 +tp22795 +g38 +I00 +S'\x077\x93\x9b\x00\x91\x0e@' +p22796 +tp22797 +bsg238 +g176 +(g177 +(I0 +tp22798 +g179 +tp22799 +Rp22800 +(I1 +(I1 +I1 +I1 +tp22801 +g38 +I00 +S'N\xb8\xdf\xc3U\xabN?' +p22802 +tp22803 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22804 +g179 +tp22805 +Rp22806 +(I1 +(I1 +I1 +I1 +tp22807 +g38 +I00 +S'\xe4\xb3{\xc0bY\xca?' +p22808 +tp22809 +bsg252 +g513 +sg48 +(lp22810 +g0 +(g52 +g2 +Ntp22811 +Rp22812 +(dp22813 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp22814 +g179 +tp22815 +Rp22816 +(I1 +(I1 +I1 +I1 +tp22817 +g38 +I00 +S'|\xfaVo\xd9\x862@' +p22818 +tp22819 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp22820 +g527 +asg113 +I10730 +sg280 +I01 +sbaa(lp22821 +g529 +ag0 +(g190 +g2 +Ntp22822 +Rp22823 +(dp22824 +g194 +I01 +sg195 +(lp22825 +g0 +(g197 +g2 +Ntp22826 +Rp22827 +(dp22828 +g201 +g176 +(g177 +(I0 +tp22829 +g179 +tp22830 +Rp22831 +(I1 +(I1 +tp22832 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22833 +tp22834 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22835 +Rp22836 +(dp22837 +g201 +g176 +(g177 +(I0 +tp22838 +g179 +tp22839 +Rp22840 +(I1 +(I2 +tp22841 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22842 +tp22843 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22844 +Rp22845 +(dp22846 +g201 +g176 +(g177 +(I0 +tp22847 +g179 +tp22848 +Rp22849 +(I1 +(I2 +tp22850 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22851 +tp22852 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp22853 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22854 +g179 +tp22855 +Rp22856 +(I1 +(I1 +I1 +I1 +tp22857 +g38 +I00 +S'\x07\xf9U\x90\xd1\x07\xd7?' +p22858 +tp22859 +bsg238 +g176 +(g177 +(I0 +tp22860 +g179 +tp22861 +Rp22862 +(I1 +(I1 +I1 +I1 +tp22863 +g38 +I00 +S'_l5O\xc6\xb71?' +p22864 +tp22865 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22866 +g179 +tp22867 +Rp22868 +(I1 +(I1 +I1 +I1 +tp22869 +g38 +I00 +S'^y\xf2%\xa3,\xb0?' +p22870 +tp22871 +bsg252 +g586 +sg48 +(lp22872 +g0 +(g52 +g2 +Ntp22873 +Rp22874 +(dp22875 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp22876 +g179 +tp22877 +Rp22878 +(I1 +(I1 +I1 +I1 +tp22879 +g38 +I00 +S'\xac\xfa\\m\xc5\xbe\x16@' +p22880 +tp22881 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp22882 +g600 +asg113 +I10731 +sg280 +I01 +sbaatp22883 +Rp22884 +sg337 +I00 +sg338 +Nsbaa(lp22885 +g604 +ag0 +(g605 +g2 +Ntp22886 +Rp22887 +(dp22888 +g17 +g22528 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp22889 +(lp22890 +g611 +ag0 +(g190 +g2 +Ntp22891 +Rp22892 +(dp22893 +g194 +I01 +sg195 +(lp22894 +g0 +(g197 +g2 +Ntp22895 +Rp22896 +(dp22897 +g201 +g176 +(g177 +(I0 +tp22898 +g179 +tp22899 +Rp22900 +(I1 +(I1 +tp22901 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22902 +tp22903 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22904 +Rp22905 +(dp22906 +g201 +g176 +(g177 +(I0 +tp22907 +g179 +tp22908 +Rp22909 +(I1 +(I2 +tp22910 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22911 +tp22912 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp22913 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22914 +g179 +tp22915 +Rp22916 +(I1 +(I1 +I1 +I1 +tp22917 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22918 +tp22919 +bsg238 +g176 +(g177 +(I0 +tp22920 +g179 +tp22921 +Rp22922 +(I1 +(I1 +I1 +I1 +tp22923 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22924 +tp22925 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22926 +g179 +tp22927 +Rp22928 +(I1 +(I1 +I1 +I1 +tp22929 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22930 +tp22931 +bsg252 +g513 +sg48 +(lp22932 +g0 +(g52 +g2 +Ntp22933 +Rp22934 +(dp22935 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp22936 +g179 +tp22937 +Rp22938 +(I1 +(I1 +I1 +I1 +tp22939 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22940 +tp22941 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp22942 +g664 +asg113 +I10734 +sg280 +I01 +sbaa(lp22943 +g666 +ag0 +(g190 +g2 +Ntp22944 +Rp22945 +(dp22946 +g194 +I01 +sg195 +(lp22947 +g0 +(g197 +g2 +Ntp22948 +Rp22949 +(dp22950 +g201 +g176 +(g177 +(I0 +tp22951 +g179 +tp22952 +Rp22953 +(I1 +(I1 +tp22954 +g208 +I00 +S">'\x00\x00\x00\x00\x00\x00" +p22955 +tp22956 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp22957 +Rp22958 +(dp22959 +g201 +g176 +(g177 +(I0 +tp22960 +g179 +tp22961 +Rp22962 +(I1 +(I2 +tp22963 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p22964 +tp22965 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp22966 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp22967 +g179 +tp22968 +Rp22969 +(I1 +(I1 +I1 +I1 +tp22970 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22971 +tp22972 +bsg238 +g176 +(g177 +(I0 +tp22973 +g179 +tp22974 +Rp22975 +(I1 +(I1 +I1 +I1 +tp22976 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22977 +tp22978 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp22979 +g179 +tp22980 +Rp22981 +(I1 +(I1 +I1 +I1 +tp22982 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22983 +tp22984 +bsg252 +g713 +sg48 +(lp22985 +g0 +(g52 +g2 +Ntp22986 +Rp22987 +(dp22988 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp22989 +g179 +tp22990 +Rp22991 +(I1 +(I1 +I1 +I1 +tp22992 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p22993 +tp22994 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp22995 +g727 +asg113 +I10735 +sg280 +I01 +sbaatp22996 +Rp22997 +sg337 +I00 +sg338 +Nsbaatp22998 +Rp22999 +aa(lp23000 +I10047 +ag7 +((lp23001 +(lp23002 +g12 +ag0 +(g13 +g2 +Ntp23003 +Rp23004 +(dp23005 +g17 +g0 +(g18 +g2 +Ntp23006 +Rp23007 +(dp23008 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p23009 +sg116 +g0 +(g117 +g2 +Ntp23010 +Rp23011 +(dp23012 +g121 +(lp23013 +g0 +(g123 +g2 +Ntp23014 +Rp23015 +(dp23016 +g127 +g0 +(g128 +g2 +Ntp23017 +Rp23018 +(dp23019 +g23 +g132 +sg133 +(dp23020 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xfb?' +p23021 +tp23022 +Rp23023 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p23024 +sg113 +I75 +sg146 +(lp23025 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp23026 +Rp23027 +(dp23028 +g127 +g0 +(g128 +g2 +Ntp23029 +Rp23030 +(dp23031 +g23 +g132 +sg133 +(dp23032 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xfa?' +p23033 +tp23034 +Rp23035 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p23036 +sg113 +I76 +sg146 +(lp23037 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10047 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23038 +(lp23039 +g189 +ag0 +(g190 +g2 +Ntp23040 +Rp23041 +(dp23042 +g194 +I01 +sg195 +(lp23043 +g0 +(g197 +g2 +Ntp23044 +Rp23045 +(dp23046 +g201 +g176 +(g177 +(I0 +tp23047 +g179 +tp23048 +Rp23049 +(I1 +(I1 +tp23050 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23051 +tp23052 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23053 +Rp23054 +(dp23055 +g201 +g176 +(g177 +(I0 +tp23056 +g179 +tp23057 +Rp23058 +(I1 +(I2 +tp23059 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23060 +tp23061 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23062 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23063 +g179 +tp23064 +Rp23065 +(I1 +(I1 +I1 +I1 +tp23066 +g38 +I00 +S'\xbe\xac\xb6\x80&\x8a8@' +p23067 +tp23068 +bsg238 +g176 +(g177 +(I0 +tp23069 +g179 +tp23070 +Rp23071 +(I1 +(I1 +I1 +I1 +tp23072 +g38 +I00 +S'\xe5\x0e\x84D\xef\x11@?' +p23073 +tp23074 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23075 +g179 +tp23076 +Rp23077 +(I1 +(I1 +I1 +I1 +tp23078 +g38 +I00 +S'N\xd13lu\xb5\xe0?' +p23079 +tp23080 +bsg252 +g260 +sg48 +(lp23081 +g0 +(g52 +g2 +Ntp23082 +Rp23083 +(dp23084 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23085 +g179 +tp23086 +Rp23087 +(I1 +(I1 +I1 +I1 +tp23088 +g38 +I00 +S'V\xde( -\x7fG@' +p23089 +tp23090 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23091 +g279 +asg113 +I10738 +sg280 +I01 +sbaa(lp23092 +g12 +ag0 +(g190 +g2 +Ntp23093 +Rp23094 +(dp23095 +g194 +I01 +sg195 +(lp23096 +g0 +(g197 +g2 +Ntp23097 +Rp23098 +(dp23099 +g201 +g176 +(g177 +(I0 +tp23100 +g179 +tp23101 +Rp23102 +(I1 +(I1 +tp23103 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23104 +tp23105 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23106 +Rp23107 +(dp23108 +g201 +g176 +(g177 +(I0 +tp23109 +g179 +tp23110 +Rp23111 +(I1 +(I2 +tp23112 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23113 +tp23114 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23115 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23116 +g179 +tp23117 +Rp23118 +(I1 +(I1 +I1 +I1 +tp23119 +g38 +I00 +S'\x01\x88\x89\xc61@\x11@' +p23120 +tp23121 +bsg238 +g176 +(g177 +(I0 +tp23122 +g179 +tp23123 +Rp23124 +(I1 +(I1 +I1 +I1 +tp23125 +g38 +I00 +S'\xb1\xc2\xe5I8A.?' +p23126 +tp23127 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23128 +g179 +tp23129 +Rp23130 +(I1 +(I1 +I1 +I1 +tp23131 +g38 +I00 +S'\x0e\xb6\xc6q\xad\x04\xcc?' +p23132 +tp23133 +bsg252 +g260 +sg48 +(lp23134 +g0 +(g52 +g2 +Ntp23135 +Rp23136 +(dp23137 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23138 +g179 +tp23139 +Rp23140 +(I1 +(I1 +I1 +I1 +tp23141 +g38 +I00 +S'\x02\xb8\xff\xf3I\xb33@' +p23142 +tp23143 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23144 +g334 +asg113 +I10739 +sg280 +I01 +sbaatp23145 +Rp23146 +sg337 +I00 +sg338 +Nsbaa(lp23147 +g340 +ag0 +(g341 +g2 +Ntp23148 +Rp23149 +(dp23150 +g17 +g23007 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23151 +(lp23152 +g189 +ag0 +(g190 +g2 +Ntp23153 +Rp23154 +(dp23155 +g194 +I01 +sg195 +(lp23156 +g0 +(g197 +g2 +Ntp23157 +Rp23158 +(dp23159 +g201 +g176 +(g177 +(I0 +tp23160 +g179 +tp23161 +Rp23162 +(I1 +(I1 +tp23163 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23164 +tp23165 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23166 +Rp23167 +(dp23168 +g201 +g176 +(g177 +(I0 +tp23169 +g179 +tp23170 +Rp23171 +(I1 +(I2 +tp23172 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23173 +tp23174 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23175 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23176 +g179 +tp23177 +Rp23178 +(I1 +(I1 +I1 +I1 +tp23179 +g38 +I00 +S'\xbe\xac\xb6\x80&\x8a8@' +p23180 +tp23181 +bsg238 +g176 +(g177 +(I0 +tp23182 +g179 +tp23183 +Rp23184 +(I1 +(I1 +I1 +I1 +tp23185 +g38 +I00 +S'\xe5\x0e\x84D\xef\x11@?' +p23186 +tp23187 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23188 +g179 +tp23189 +Rp23190 +(I1 +(I1 +I1 +I1 +tp23191 +g38 +I00 +S'N\xd13lu\xb5\xe0?' +p23192 +tp23193 +bsg252 +g260 +sg48 +(lp23194 +g0 +(g52 +g2 +Ntp23195 +Rp23196 +(dp23197 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23198 +g179 +tp23199 +Rp23200 +(I1 +(I1 +I1 +I1 +tp23201 +g38 +I00 +S'V\xde( -\x7fG@' +p23202 +tp23203 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23204 +g279 +asg113 +I10742 +sg280 +I01 +sbaa(lp23205 +g401 +ag0 +(g190 +g2 +Ntp23206 +Rp23207 +(dp23208 +g194 +I01 +sg195 +(lp23209 +g0 +(g197 +g2 +Ntp23210 +Rp23211 +(dp23212 +g201 +g176 +(g177 +(I0 +tp23213 +g179 +tp23214 +Rp23215 +(I1 +(I1 +tp23216 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23217 +tp23218 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23219 +Rp23220 +(dp23221 +g201 +g176 +(g177 +(I0 +tp23222 +g179 +tp23223 +Rp23224 +(I1 +(I2 +tp23225 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23226 +tp23227 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23228 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23229 +g179 +tp23230 +Rp23231 +(I1 +(I1 +I1 +I1 +tp23232 +g38 +I00 +S'8\xcbP\xd0\x90H\xb6?' +p23233 +tp23234 +bsg238 +g176 +(g177 +(I0 +tp23235 +g179 +tp23236 +Rp23237 +(I1 +(I1 +I1 +I1 +tp23238 +g38 +I00 +S'\xf9\x92,\xb8\xafR\x11?' +p23239 +tp23240 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23241 +g179 +tp23242 +Rp23243 +(I1 +(I1 +I1 +I1 +tp23244 +g38 +I00 +S'0OM\xb8\xd8\xd6\x9f?' +p23245 +tp23246 +bsg252 +g260 +sg48 +(lp23247 +g0 +(g52 +g2 +Ntp23248 +Rp23249 +(dp23250 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23251 +g179 +tp23252 +Rp23253 +(I1 +(I1 +I1 +I1 +tp23254 +g38 +I00 +S'\xae[\x96a\x10c\x06@' +p23255 +tp23256 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23257 +g454 +asg113 +I10743 +sg280 +I01 +sbaatp23258 +Rp23259 +sg337 +I00 +sg338 +Nsbaa(lp23260 +g458 +ag0 +(g459 +g2 +Ntp23261 +Rp23262 +(dp23263 +g17 +g23007 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23264 +(lp23265 +g189 +ag0 +(g190 +g2 +Ntp23266 +Rp23267 +(dp23268 +g194 +I01 +sg195 +(lp23269 +g0 +(g197 +g2 +Ntp23270 +Rp23271 +(dp23272 +g201 +g176 +(g177 +(I0 +tp23273 +g179 +tp23274 +Rp23275 +(I1 +(I1 +tp23276 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23277 +tp23278 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23279 +Rp23280 +(dp23281 +g201 +g176 +(g177 +(I0 +tp23282 +g179 +tp23283 +Rp23284 +(I1 +(I2 +tp23285 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23286 +tp23287 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp23288 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23289 +g179 +tp23290 +Rp23291 +(I1 +(I1 +I1 +I1 +tp23292 +g38 +I00 +S'o\xf6\x12Y\xb3k8@' +p23293 +tp23294 +bsg238 +g176 +(g177 +(I0 +tp23295 +g179 +tp23296 +Rp23297 +(I1 +(I1 +I1 +I1 +tp23298 +g38 +I00 +S'\xd8n\x1ak\x83&T?' +p23299 +tp23300 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23301 +g179 +tp23302 +Rp23303 +(I1 +(I1 +I1 +I1 +tp23304 +g38 +I00 +S'a\r\x05:0\xaa\xe0?' +p23305 +tp23306 +bsg252 +g513 +sg48 +(lp23307 +g0 +(g52 +g2 +Ntp23308 +Rp23309 +(dp23310 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp23311 +g179 +tp23312 +Rp23313 +(I1 +(I1 +I1 +I1 +tp23314 +g38 +I00 +S'\xd1\x1a\x97\xd1SoG@' +p23315 +tp23316 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp23317 +g527 +asg113 +I10746 +sg280 +I01 +sbaa(lp23318 +g529 +ag0 +(g190 +g2 +Ntp23319 +Rp23320 +(dp23321 +g194 +I01 +sg195 +(lp23322 +g0 +(g197 +g2 +Ntp23323 +Rp23324 +(dp23325 +g201 +g176 +(g177 +(I0 +tp23326 +g179 +tp23327 +Rp23328 +(I1 +(I1 +tp23329 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23330 +tp23331 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23332 +Rp23333 +(dp23334 +g201 +g176 +(g177 +(I0 +tp23335 +g179 +tp23336 +Rp23337 +(I1 +(I2 +tp23338 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23339 +tp23340 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23341 +Rp23342 +(dp23343 +g201 +g176 +(g177 +(I0 +tp23344 +g179 +tp23345 +Rp23346 +(I1 +(I2 +tp23347 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23348 +tp23349 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp23350 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23351 +g179 +tp23352 +Rp23353 +(I1 +(I1 +I1 +I1 +tp23354 +g38 +I00 +S'\xf9\x0ce\xd1\t\x13\x0c@' +p23355 +tp23356 +bsg238 +g176 +(g177 +(I0 +tp23357 +g179 +tp23358 +Rp23359 +(I1 +(I1 +I1 +I1 +tp23360 +g38 +I00 +S'/\xf7A\xbd\x83k@?' +p23361 +tp23362 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23363 +g179 +tp23364 +Rp23365 +(I1 +(I1 +I1 +I1 +tp23366 +g38 +I00 +S'0\x0b\xc4v\xa8D\xc9?' +p23367 +tp23368 +bsg252 +g586 +sg48 +(lp23369 +g0 +(g52 +g2 +Ntp23370 +Rp23371 +(dp23372 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp23373 +g179 +tp23374 +Rp23375 +(I1 +(I1 +I1 +I1 +tp23376 +g38 +I00 +S'\xde\xd7\x81sF\xc41@' +p23377 +tp23378 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp23379 +g600 +asg113 +I10747 +sg280 +I01 +sbaatp23380 +Rp23381 +sg337 +I00 +sg338 +Nsbaa(lp23382 +g604 +ag0 +(g605 +g2 +Ntp23383 +Rp23384 +(dp23385 +g17 +g23007 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23386 +(lp23387 +g611 +ag0 +(g190 +g2 +Ntp23388 +Rp23389 +(dp23390 +g194 +I01 +sg195 +(lp23391 +g0 +(g197 +g2 +Ntp23392 +Rp23393 +(dp23394 +g201 +g176 +(g177 +(I0 +tp23395 +g179 +tp23396 +Rp23397 +(I1 +(I1 +tp23398 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23399 +tp23400 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23401 +Rp23402 +(dp23403 +g201 +g176 +(g177 +(I0 +tp23404 +g179 +tp23405 +Rp23406 +(I1 +(I2 +tp23407 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23408 +tp23409 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp23410 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23411 +g179 +tp23412 +Rp23413 +(I1 +(I1 +I1 +I1 +tp23414 +g38 +I00 +S'3\x07\x88I\xc1a\xb6?' +p23415 +tp23416 +bsg238 +g176 +(g177 +(I0 +tp23417 +g179 +tp23418 +Rp23419 +(I1 +(I1 +I1 +I1 +tp23420 +g38 +I00 +S'\xf0\xce0\x9b)\xbf0?' +p23421 +tp23422 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23423 +g179 +tp23424 +Rp23425 +(I1 +(I1 +I1 +I1 +tp23426 +g38 +I00 +S'&\x13\xe4\xe9\xfc\xd1\x9f?' +p23427 +tp23428 +bsg252 +g513 +sg48 +(lp23429 +g0 +(g52 +g2 +Ntp23430 +Rp23431 +(dp23432 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp23433 +g179 +tp23434 +Rp23435 +(I1 +(I1 +I1 +I1 +tp23436 +g38 +I00 +S'w]t\xd4\xa5_\x06@' +p23437 +tp23438 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp23439 +g664 +asg113 +I10750 +sg280 +I01 +sbaa(lp23440 +g666 +ag0 +(g190 +g2 +Ntp23441 +Rp23442 +(dp23443 +g194 +I01 +sg195 +(lp23444 +g0 +(g197 +g2 +Ntp23445 +Rp23446 +(dp23447 +g201 +g176 +(g177 +(I0 +tp23448 +g179 +tp23449 +Rp23450 +(I1 +(I1 +tp23451 +g208 +I00 +S"?'\x00\x00\x00\x00\x00\x00" +p23452 +tp23453 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23454 +Rp23455 +(dp23456 +g201 +g176 +(g177 +(I0 +tp23457 +g179 +tp23458 +Rp23459 +(I1 +(I2 +tp23460 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23461 +tp23462 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp23463 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23464 +g179 +tp23465 +Rp23466 +(I1 +(I1 +I1 +I1 +tp23467 +g38 +I00 +S'7\x07\x88I\xc1a\xb6?' +p23468 +tp23469 +bsg238 +g176 +(g177 +(I0 +tp23470 +g179 +tp23471 +Rp23472 +(I1 +(I1 +I1 +I1 +tp23473 +g38 +I00 +S'8\xcd0\x9b)\xbf0?' +p23474 +tp23475 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23476 +g179 +tp23477 +Rp23478 +(I1 +(I1 +I1 +I1 +tp23479 +g38 +I00 +S'.\x13\xe4\xe9\xfc\xd1\x9f?' +p23480 +tp23481 +bsg252 +g713 +sg48 +(lp23482 +g0 +(g52 +g2 +Ntp23483 +Rp23484 +(dp23485 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp23486 +g179 +tp23487 +Rp23488 +(I1 +(I1 +I1 +I1 +tp23489 +g38 +I00 +S'|]t\xd4\xa5_\x06@' +p23490 +tp23491 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp23492 +g727 +asg113 +I10751 +sg280 +I01 +sbaatp23493 +Rp23494 +sg337 +I00 +sg338 +Nsbaatp23495 +Rp23496 +aa(lp23497 +I10048 +ag7 +((lp23498 +(lp23499 +g12 +ag0 +(g13 +g2 +Ntp23500 +Rp23501 +(dp23502 +g17 +g0 +(g18 +g2 +Ntp23503 +Rp23504 +(dp23505 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p23506 +sg116 +g0 +(g117 +g2 +Ntp23507 +Rp23508 +(dp23509 +g121 +(lp23510 +g0 +(g123 +g2 +Ntp23511 +Rp23512 +(dp23513 +g127 +g1845 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp23514 +Rp23515 +(dp23516 +g127 +g0 +(g128 +g2 +Ntp23517 +Rp23518 +(dp23519 +g23 +g132 +sg133 +(dp23520 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xecQ\xb8\x1e\x85\xeb\x11@' +p23521 +tp23522 +Rp23523 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p23524 +sg113 +I77 +sg146 +(lp23525 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10048 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23526 +(lp23527 +g189 +ag0 +(g190 +g2 +Ntp23528 +Rp23529 +(dp23530 +g194 +I01 +sg195 +(lp23531 +g0 +(g197 +g2 +Ntp23532 +Rp23533 +(dp23534 +g201 +g176 +(g177 +(I0 +tp23535 +g179 +tp23536 +Rp23537 +(I1 +(I1 +tp23538 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23539 +tp23540 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23541 +Rp23542 +(dp23543 +g201 +g176 +(g177 +(I0 +tp23544 +g179 +tp23545 +Rp23546 +(I1 +(I2 +tp23547 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23548 +tp23549 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23550 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23551 +g179 +tp23552 +Rp23553 +(I1 +(I1 +I1 +I1 +tp23554 +g38 +I00 +S'\x04u\xe7\x1e\nAI@' +p23555 +tp23556 +bsg238 +g176 +(g177 +(I0 +tp23557 +g179 +tp23558 +Rp23559 +(I1 +(I1 +I1 +I1 +tp23560 +g38 +I00 +S'\xd29\x8a\xf8\xc6;G?' +p23561 +tp23562 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23563 +g179 +tp23564 +Rp23565 +(I1 +(I1 +I1 +I1 +tp23566 +g38 +I00 +S'N\x92#\xad\xa8\xf8\xe7?' +p23567 +tp23568 +bsg252 +g260 +sg48 +(lp23569 +g0 +(g52 +g2 +Ntp23570 +Rp23571 +(dp23572 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23573 +g179 +tp23574 +Rp23575 +(I1 +(I1 +I1 +I1 +tp23576 +g38 +I00 +S'\xdf\x02\xbd\x99\xd6\xdaP@' +p23577 +tp23578 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23579 +g279 +asg113 +I10754 +sg280 +I01 +sbaa(lp23580 +g12 +ag0 +(g190 +g2 +Ntp23581 +Rp23582 +(dp23583 +g194 +I01 +sg195 +(lp23584 +g0 +(g197 +g2 +Ntp23585 +Rp23586 +(dp23587 +g201 +g176 +(g177 +(I0 +tp23588 +g179 +tp23589 +Rp23590 +(I1 +(I1 +tp23591 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23592 +tp23593 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23594 +Rp23595 +(dp23596 +g201 +g176 +(g177 +(I0 +tp23597 +g179 +tp23598 +Rp23599 +(I1 +(I2 +tp23600 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23601 +tp23602 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23603 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23604 +g179 +tp23605 +Rp23606 +(I1 +(I1 +I1 +I1 +tp23607 +g38 +I00 +S'\xc4\x11\x0b^=\x11N@' +p23608 +tp23609 +bsg238 +g176 +(g177 +(I0 +tp23610 +g179 +tp23611 +Rp23612 +(I1 +(I1 +I1 +I1 +tp23613 +g38 +I00 +S"'\x02\xb3\xf1o=R?" +p23614 +tp23615 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23616 +g179 +tp23617 +Rp23618 +(I1 +(I1 +I1 +I1 +tp23619 +g38 +I00 +S"s\x87i\xb8\xb0'\xea?" +p23620 +tp23621 +bsg252 +g260 +sg48 +(lp23622 +g0 +(g52 +g2 +Ntp23623 +Rp23624 +(dp23625 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23626 +g179 +tp23627 +Rp23628 +(I1 +(I1 +I1 +I1 +tp23629 +g38 +I00 +S'=3\xaaA\xe8cR@' +p23630 +tp23631 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23632 +g334 +asg113 +I10755 +sg280 +I01 +sbaatp23633 +Rp23634 +sg337 +I00 +sg338 +Nsbaa(lp23635 +g340 +ag0 +(g341 +g2 +Ntp23636 +Rp23637 +(dp23638 +g17 +g23504 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23639 +(lp23640 +g189 +ag0 +(g190 +g2 +Ntp23641 +Rp23642 +(dp23643 +g194 +I01 +sg195 +(lp23644 +g0 +(g197 +g2 +Ntp23645 +Rp23646 +(dp23647 +g201 +g176 +(g177 +(I0 +tp23648 +g179 +tp23649 +Rp23650 +(I1 +(I1 +tp23651 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23652 +tp23653 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23654 +Rp23655 +(dp23656 +g201 +g176 +(g177 +(I0 +tp23657 +g179 +tp23658 +Rp23659 +(I1 +(I2 +tp23660 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23661 +tp23662 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23663 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23664 +g179 +tp23665 +Rp23666 +(I1 +(I1 +I1 +I1 +tp23667 +g38 +I00 +S'\x04u\xe7\x1e\nAI@' +p23668 +tp23669 +bsg238 +g176 +(g177 +(I0 +tp23670 +g179 +tp23671 +Rp23672 +(I1 +(I1 +I1 +I1 +tp23673 +g38 +I00 +S'\xd29\x8a\xf8\xc6;G?' +p23674 +tp23675 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23676 +g179 +tp23677 +Rp23678 +(I1 +(I1 +I1 +I1 +tp23679 +g38 +I00 +S'N\x92#\xad\xa8\xf8\xe7?' +p23680 +tp23681 +bsg252 +g260 +sg48 +(lp23682 +g0 +(g52 +g2 +Ntp23683 +Rp23684 +(dp23685 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23686 +g179 +tp23687 +Rp23688 +(I1 +(I1 +I1 +I1 +tp23689 +g38 +I00 +S'\xdf\x02\xbd\x99\xd6\xdaP@' +p23690 +tp23691 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23692 +g279 +asg113 +I10758 +sg280 +I01 +sbaa(lp23693 +g401 +ag0 +(g190 +g2 +Ntp23694 +Rp23695 +(dp23696 +g194 +I01 +sg195 +(lp23697 +g0 +(g197 +g2 +Ntp23698 +Rp23699 +(dp23700 +g201 +g176 +(g177 +(I0 +tp23701 +g179 +tp23702 +Rp23703 +(I1 +(I1 +tp23704 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23705 +tp23706 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23707 +Rp23708 +(dp23709 +g201 +g176 +(g177 +(I0 +tp23710 +g179 +tp23711 +Rp23712 +(I1 +(I2 +tp23713 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23714 +tp23715 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp23716 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23717 +g179 +tp23718 +Rp23719 +(I1 +(I1 +I1 +I1 +tp23720 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23721 +tp23722 +bsg238 +g176 +(g177 +(I0 +tp23723 +g179 +tp23724 +Rp23725 +(I1 +(I1 +I1 +I1 +tp23726 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23727 +tp23728 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23729 +g179 +tp23730 +Rp23731 +(I1 +(I1 +I1 +I1 +tp23732 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23733 +tp23734 +bsg252 +g260 +sg48 +(lp23735 +g0 +(g52 +g2 +Ntp23736 +Rp23737 +(dp23738 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp23739 +g179 +tp23740 +Rp23741 +(I1 +(I1 +I1 +I1 +tp23742 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23743 +tp23744 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp23745 +g454 +asg113 +I10759 +sg280 +I01 +sbaatp23746 +Rp23747 +sg337 +I00 +sg338 +Nsbaa(lp23748 +g458 +ag0 +(g459 +g2 +Ntp23749 +Rp23750 +(dp23751 +g17 +g23504 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23752 +(lp23753 +g189 +ag0 +(g190 +g2 +Ntp23754 +Rp23755 +(dp23756 +g194 +I01 +sg195 +(lp23757 +g0 +(g197 +g2 +Ntp23758 +Rp23759 +(dp23760 +g201 +g176 +(g177 +(I0 +tp23761 +g179 +tp23762 +Rp23763 +(I1 +(I1 +tp23764 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23765 +tp23766 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23767 +Rp23768 +(dp23769 +g201 +g176 +(g177 +(I0 +tp23770 +g179 +tp23771 +Rp23772 +(I1 +(I2 +tp23773 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23774 +tp23775 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp23776 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23777 +g179 +tp23778 +Rp23779 +(I1 +(I1 +I1 +I1 +tp23780 +g38 +I00 +S's\xf7D\\q"I@' +p23781 +tp23782 +bsg238 +g176 +(g177 +(I0 +tp23783 +g179 +tp23784 +Rp23785 +(I1 +(I1 +I1 +I1 +tp23786 +g38 +I00 +S'\x88\xeb\xb9\xdb\xfc\x94Z?' +p23787 +tp23788 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23789 +g179 +tp23790 +Rp23791 +(I1 +(I1 +I1 +I1 +tp23792 +g38 +I00 +S'\xd1\x08\xc2\x8f\x14\xe9\xe7?' +p23793 +tp23794 +bsg252 +g513 +sg48 +(lp23795 +g0 +(g52 +g2 +Ntp23796 +Rp23797 +(dp23798 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp23799 +g179 +tp23800 +Rp23801 +(I1 +(I1 +I1 +I1 +tp23802 +g38 +I00 +S'3n\x14u\xe2\xcfP@' +p23803 +tp23804 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp23805 +g527 +asg113 +I10762 +sg280 +I01 +sbaa(lp23806 +g529 +ag0 +(g190 +g2 +Ntp23807 +Rp23808 +(dp23809 +g194 +I01 +sg195 +(lp23810 +g0 +(g197 +g2 +Ntp23811 +Rp23812 +(dp23813 +g201 +g176 +(g177 +(I0 +tp23814 +g179 +tp23815 +Rp23816 +(I1 +(I1 +tp23817 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23818 +tp23819 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23820 +Rp23821 +(dp23822 +g201 +g176 +(g177 +(I0 +tp23823 +g179 +tp23824 +Rp23825 +(I1 +(I2 +tp23826 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23827 +tp23828 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23829 +Rp23830 +(dp23831 +g201 +g176 +(g177 +(I0 +tp23832 +g179 +tp23833 +Rp23834 +(I1 +(I2 +tp23835 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23836 +tp23837 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp23838 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23839 +g179 +tp23840 +Rp23841 +(I1 +(I1 +I1 +I1 +tp23842 +g38 +I00 +S':\xc0\xdd\xa3HLM@' +p23843 +tp23844 +bsg238 +g176 +(g177 +(I0 +tp23845 +g179 +tp23846 +Rp23847 +(I1 +(I1 +I1 +I1 +tp23848 +g38 +I00 +S'\xa9\x1c\x8b\xfa\x98\x86Z?' +p23849 +tp23850 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23851 +g179 +tp23852 +Rp23853 +(I1 +(I1 +I1 +I1 +tp23854 +g38 +I00 +S'\xd8\xe5\x97\x10\xd5\xd0\xe9?' +p23855 +tp23856 +bsg252 +g586 +sg48 +(lp23857 +g0 +(g52 +g2 +Ntp23858 +Rp23859 +(dp23860 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp23861 +g179 +tp23862 +Rp23863 +(I1 +(I1 +I1 +I1 +tp23864 +g38 +I00 +S'\x9c\xcd\xaa\xcf\xd5&R@' +p23865 +tp23866 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp23867 +g600 +asg113 +I10763 +sg280 +I01 +sbaatp23868 +Rp23869 +sg337 +I00 +sg338 +Nsbaa(lp23870 +g604 +ag0 +(g605 +g2 +Ntp23871 +Rp23872 +(dp23873 +g17 +g23504 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp23874 +(lp23875 +g611 +ag0 +(g190 +g2 +Ntp23876 +Rp23877 +(dp23878 +g194 +I01 +sg195 +(lp23879 +g0 +(g197 +g2 +Ntp23880 +Rp23881 +(dp23882 +g201 +g176 +(g177 +(I0 +tp23883 +g179 +tp23884 +Rp23885 +(I1 +(I1 +tp23886 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23887 +tp23888 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23889 +Rp23890 +(dp23891 +g201 +g176 +(g177 +(I0 +tp23892 +g179 +tp23893 +Rp23894 +(I1 +(I2 +tp23895 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23896 +tp23897 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp23898 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23899 +g179 +tp23900 +Rp23901 +(I1 +(I1 +I1 +I1 +tp23902 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23903 +tp23904 +bsg238 +g176 +(g177 +(I0 +tp23905 +g179 +tp23906 +Rp23907 +(I1 +(I1 +I1 +I1 +tp23908 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23909 +tp23910 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23911 +g179 +tp23912 +Rp23913 +(I1 +(I1 +I1 +I1 +tp23914 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23915 +tp23916 +bsg252 +g513 +sg48 +(lp23917 +g0 +(g52 +g2 +Ntp23918 +Rp23919 +(dp23920 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp23921 +g179 +tp23922 +Rp23923 +(I1 +(I1 +I1 +I1 +tp23924 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23925 +tp23926 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp23927 +g664 +asg113 +I10766 +sg280 +I01 +sbaa(lp23928 +g666 +ag0 +(g190 +g2 +Ntp23929 +Rp23930 +(dp23931 +g194 +I01 +sg195 +(lp23932 +g0 +(g197 +g2 +Ntp23933 +Rp23934 +(dp23935 +g201 +g176 +(g177 +(I0 +tp23936 +g179 +tp23937 +Rp23938 +(I1 +(I1 +tp23939 +g208 +I00 +S"@'\x00\x00\x00\x00\x00\x00" +p23940 +tp23941 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp23942 +Rp23943 +(dp23944 +g201 +g176 +(g177 +(I0 +tp23945 +g179 +tp23946 +Rp23947 +(I1 +(I2 +tp23948 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p23949 +tp23950 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp23951 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp23952 +g179 +tp23953 +Rp23954 +(I1 +(I1 +I1 +I1 +tp23955 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23956 +tp23957 +bsg238 +g176 +(g177 +(I0 +tp23958 +g179 +tp23959 +Rp23960 +(I1 +(I1 +I1 +I1 +tp23961 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23962 +tp23963 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp23964 +g179 +tp23965 +Rp23966 +(I1 +(I1 +I1 +I1 +tp23967 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23968 +tp23969 +bsg252 +g713 +sg48 +(lp23970 +g0 +(g52 +g2 +Ntp23971 +Rp23972 +(dp23973 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp23974 +g179 +tp23975 +Rp23976 +(I1 +(I1 +I1 +I1 +tp23977 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p23978 +tp23979 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp23980 +g727 +asg113 +I10767 +sg280 +I01 +sbaatp23981 +Rp23982 +sg337 +I00 +sg338 +Nsbaatp23983 +Rp23984 +aa(lp23985 +I10049 +ag7 +((lp23986 +(lp23987 +g12 +ag0 +(g13 +g2 +Ntp23988 +Rp23989 +(dp23990 +g17 +g0 +(g18 +g2 +Ntp23991 +Rp23992 +(dp23993 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p23994 +sg116 +g0 +(g117 +g2 +Ntp23995 +Rp23996 +(dp23997 +g121 +(lp23998 +g0 +(g123 +g2 +Ntp23999 +Rp24000 +(dp24001 +g127 +g0 +(g128 +g2 +Ntp24002 +Rp24003 +(dp24004 +g23 +g132 +sg133 +(dp24005 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'ffffff\xe6?' +p24006 +tp24007 +Rp24008 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p24009 +sg113 +I78 +sg146 +(lp24010 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp24011 +Rp24012 +(dp24013 +g127 +g1303 +sg148 +g162 +sbasbsg163 +Nsg113 +I10049 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp24014 +(lp24015 +g189 +ag0 +(g190 +g2 +Ntp24016 +Rp24017 +(dp24018 +g194 +I01 +sg195 +(lp24019 +g0 +(g197 +g2 +Ntp24020 +Rp24021 +(dp24022 +g201 +g176 +(g177 +(I0 +tp24023 +g179 +tp24024 +Rp24025 +(I1 +(I1 +tp24026 +g208 +I00 +S"A'\x00\x00\x00\x00\x00\x00" +p24027 +tp24028 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24029 +Rp24030 +(dp24031 +g201 +g176 +(g177 +(I0 +tp24032 +g179 +tp24033 +Rp24034 +(I1 +(I2 +tp24035 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24036 +tp24037 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp24038 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24039 +g179 +tp24040 +Rp24041 +(I1 +(I1 +I1 +I1 +tp24042 +g38 +I00 +S'\xf3\xa7\x1c\xae\xaa\x838@' +p24043 +tp24044 +bsg238 +g176 +(g177 +(I0 +tp24045 +g179 +tp24046 +Rp24047 +(I1 +(I1 +I1 +I1 +tp24048 +g38 +I00 +S'\xb6\x02\xf3s\x07\xa8D?' +p24049 +tp24050 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24051 +g179 +tp24052 +Rp24053 +(I1 +(I1 +I1 +I1 +tp24054 +g38 +I00 +S'\xf2\xe7\xeb\x19$\xb3\xe0?' +p24055 +tp24056 +bsg252 +g260 +sg48 +(lp24057 +g0 +(g52 +g2 +Ntp24058 +Rp24059 +(dp24060 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp24061 +g179 +tp24062 +Rp24063 +(I1 +(I1 +I1 +I1 +tp24064 +g38 +I00 +S',\xbes\xc4\xea{G@' +p24065 +tp24066 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp24067 +g279 +asg113 +I10770 +sg280 +I01 +sbaa(lp24068 +g12 +ag0 +(g190 +g2 +Ntp24069 +Rp24070 +(dp24071 +g194 +I01 +sg195 +(lp24072 +g0 +(g197 +g2 +Ntp24073 +Rp24074 +(dp24075 +g201 +g176 +(g177 +(I0 +tp24076 +g179 +tp24077 +Rp24078 +(I1 +(I1 +tp24079 +g208 +I00 +S"A'\x00\x00\x00\x00\x00\x00" +p24080 +tp24081 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24082 +Rp24083 +(dp24084 +g201 +g176 +(g177 +(I0 +tp24085 +g179 +tp24086 +Rp24087 +(I1 +(I2 +tp24088 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24089 +tp24090 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp24091 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24092 +g179 +tp24093 +Rp24094 +(I1 +(I1 +I1 +I1 +tp24095 +g38 +I00 +S'\x0c\x11Bc\x07\x8a\x0f@' +p24096 +tp24097 +bsg238 +g176 +(g177 +(I0 +tp24098 +g179 +tp24099 +Rp24100 +(I1 +(I1 +I1 +I1 +tp24101 +g38 +I00 +S'\\\xcd[\xe5\x97\t2?' +p24102 +tp24103 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24104 +g179 +tp24105 +Rp24106 +(I1 +(I1 +I1 +I1 +tp24107 +g38 +I00 +S'\xce\xd0\xc5\xdb\xa6\xc9\xca?' +p24108 +tp24109 +bsg252 +g260 +sg48 +(lp24110 +g0 +(g52 +g2 +Ntp24111 +Rp24112 +(dp24113 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp24114 +g179 +tp24115 +Rp24116 +(I1 +(I1 +I1 +I1 +tp24117 +g38 +I00 +S'\xd1\x16\x87R\xc9\xd52@' +p24118 +tp24119 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp24120 +g334 +asg113 +I10771 +sg280 +I01 +sbaatp24121 +Rp24122 +sg337 +I00 +sg338 +Nsbaa(lp24123 +g340 +ag0 +(g341 +g2 +Ntp24124 +Rp24125 +(dp24126 +g17 +g23992 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp24127 +(lp24128 +g189 +ag0 +(g190 +g2 +Ntp24129 +Rp24130 +(dp24131 +g194 +I01 +sg195 +(lp24132 +g0 +(g197 +g2 +Ntp24133 +Rp24134 +(dp24135 +g201 +g176 +(g177 +(I0 +tp24136 +g179 +tp24137 +Rp24138 +(I1 +(I1 +tp24139 +g208 +I00 +S"A'\x00\x00\x00\x00\x00\x00" +p24140 +tp24141 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24142 +Rp24143 +(dp24144 +g201 +g176 +(g177 +(I0 +tp24145 +g179 +tp24146 +Rp24147 +(I1 +(I2 +tp24148 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24149 +tp24150 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp24151 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24152 +g179 +tp24153 +Rp24154 +(I1 +(I1 +I1 +I1 +tp24155 +g38 +I00 +S'\xf3\xa7\x1c\xae\xaa\x838@' +p24156 +tp24157 +bsg238 +g176 +(g177 +(I0 +tp24158 +g179 +tp24159 +Rp24160 +(I1 +(I1 +I1 +I1 +tp24161 +g38 +I00 +S'\xb6\x02\xf3s\x07\xa8D?' +p24162 +tp24163 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24164 +g179 +tp24165 +Rp24166 +(I1 +(I1 +I1 +I1 +tp24167 +g38 +I00 +S'\xf2\xe7\xeb\x19$\xb3\xe0?' +p24168 +tp24169 +bsg252 +g260 +sg48 +(lp24170 +g0 +(g52 +g2 +Ntp24171 +Rp24172 +(dp24173 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp24174 +g179 +tp24175 +Rp24176 +(I1 +(I1 +I1 +I1 +tp24177 +g38 +I00 +S',\xbes\xc4\xea{G@' +p24178 +tp24179 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp24180 +g279 +asg113 +I10774 +sg280 +I01 +sbaa(lp24181 +g401 +ag0 +(g190 +g2 +Ntp24182 +Rp24183 +(dp24184 +g194 +I01 +sg195 +(lp24185 +g0 +(g197 +g2 +Ntp24186 +Rp24187 +(dp24188 +g201 +g176 +(g177 +(I0 +tp24189 +g179 +tp24190 +Rp24191 +(I1 +(I1 +tp24192 +g208 +I00 +S"A'\x00\x00\x00\x00\x00\x00" +p24193 +tp24194 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24195 +Rp24196 +(dp24197 +g201 +g176 +(g177 +(I0 +tp24198 +g179 +tp24199 +Rp24200 +(I1 +(I2 +tp24201 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24202 +tp24203 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp24204 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24205 +g179 +tp24206 +Rp24207 +(I1 +(I1 +I1 +I1 +tp24208 +g38 +I00 +S'\xc8\xb8\x1d"f\xfd\xa1?' +p24209 +tp24210 +bsg238 +g176 +(g177 +(I0 +tp24211 +g179 +tp24212 +Rp24213 +(I1 +(I1 +I1 +I1 +tp24214 +g38 +I00 +S'}H\xa5\xc3>\xf8\x06?' +p24215 +tp24216 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24217 +g179 +tp24218 +Rp24219 +(I1 +(I1 +I1 +I1 +tp24220 +g38 +I00 +S'\x92PN\xdbz:\x94?' +p24221 +tp24222 +bsg252 +g260 +sg48 +(lp24223 +g0 +(g52 +g2 +Ntp24224 +Rp24225 +(dp24226 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp24227 +g179 +tp24228 +Rp24229 +(I1 +(I1 +I1 +I1 +tp24230 +g38 +I00 +S'N!f\xc4\xb4Z/?' +p24834 +tp24835 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24836 +g179 +tp24837 +Rp24838 +(I1 +(I1 +I1 +I1 +tp24839 +g38 +I00 +S'\xdc5`.m\xe9\xaf?' +p24840 +tp24841 +bsg252 +g586 +sg48 +(lp24842 +g0 +(g52 +g2 +Ntp24843 +Rp24844 +(dp24845 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp24846 +g179 +tp24847 +Rp24848 +(I1 +(I1 +I1 +I1 +tp24849 +g38 +I00 +S'\xdf\xa5\x9b\xc4 p\x16@' +p24850 +tp24851 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp24852 +g600 +asg113 +I10795 +sg280 +I01 +sbaatp24853 +Rp24854 +sg337 +I00 +sg338 +Nsbaa(lp24855 +g604 +ag0 +(g605 +g2 +Ntp24856 +Rp24857 +(dp24858 +g17 +g24480 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp24859 +(lp24860 +g611 +ag0 +(g190 +g2 +Ntp24861 +Rp24862 +(dp24863 +g194 +I01 +sg195 +(lp24864 +g0 +(g197 +g2 +Ntp24865 +Rp24866 +(dp24867 +g201 +g176 +(g177 +(I0 +tp24868 +g179 +tp24869 +Rp24870 +(I1 +(I1 +tp24871 +g208 +I00 +S"B'\x00\x00\x00\x00\x00\x00" +p24872 +tp24873 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24874 +Rp24875 +(dp24876 +g201 +g176 +(g177 +(I0 +tp24877 +g179 +tp24878 +Rp24879 +(I1 +(I2 +tp24880 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24881 +tp24882 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp24883 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24884 +g179 +tp24885 +Rp24886 +(I1 +(I1 +I1 +I1 +tp24887 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24888 +tp24889 +bsg238 +g176 +(g177 +(I0 +tp24890 +g179 +tp24891 +Rp24892 +(I1 +(I1 +I1 +I1 +tp24893 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24894 +tp24895 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24896 +g179 +tp24897 +Rp24898 +(I1 +(I1 +I1 +I1 +tp24899 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24900 +tp24901 +bsg252 +g513 +sg48 +(lp24902 +g0 +(g52 +g2 +Ntp24903 +Rp24904 +(dp24905 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp24906 +g179 +tp24907 +Rp24908 +(I1 +(I1 +I1 +I1 +tp24909 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24910 +tp24911 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp24912 +g664 +asg113 +I10798 +sg280 +I01 +sbaa(lp24913 +g666 +ag0 +(g190 +g2 +Ntp24914 +Rp24915 +(dp24916 +g194 +I01 +sg195 +(lp24917 +g0 +(g197 +g2 +Ntp24918 +Rp24919 +(dp24920 +g201 +g176 +(g177 +(I0 +tp24921 +g179 +tp24922 +Rp24923 +(I1 +(I1 +tp24924 +g208 +I00 +S"B'\x00\x00\x00\x00\x00\x00" +p24925 +tp24926 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp24927 +Rp24928 +(dp24929 +g201 +g176 +(g177 +(I0 +tp24930 +g179 +tp24931 +Rp24932 +(I1 +(I2 +tp24933 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p24934 +tp24935 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp24936 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp24937 +g179 +tp24938 +Rp24939 +(I1 +(I1 +I1 +I1 +tp24940 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24941 +tp24942 +bsg238 +g176 +(g177 +(I0 +tp24943 +g179 +tp24944 +Rp24945 +(I1 +(I1 +I1 +I1 +tp24946 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24947 +tp24948 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp24949 +g179 +tp24950 +Rp24951 +(I1 +(I1 +I1 +I1 +tp24952 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24953 +tp24954 +bsg252 +g713 +sg48 +(lp24955 +g0 +(g52 +g2 +Ntp24956 +Rp24957 +(dp24958 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp24959 +g179 +tp24960 +Rp24961 +(I1 +(I1 +I1 +I1 +tp24962 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p24963 +tp24964 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp24965 +g727 +asg113 +I10799 +sg280 +I01 +sbaatp24966 +Rp24967 +sg337 +I00 +sg338 +Nsbaatp24968 +Rp24969 +aa(lp24970 +I10051 +ag7 +((lp24971 +(lp24972 +g12 +ag0 +(g13 +g2 +Ntp24973 +Rp24974 +(dp24975 +g17 +g0 +(g18 +g2 +Ntp24976 +Rp24977 +(dp24978 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p24979 +sg116 +g0 +(g117 +g2 +Ntp24980 +Rp24981 +(dp24982 +g121 +(lp24983 +g0 +(g123 +g2 +Ntp24984 +Rp24985 +(dp24986 +g127 +g14198 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp24987 +Rp24988 +(dp24989 +g127 +g0 +(g128 +g2 +Ntp24990 +Rp24991 +(dp24992 +g23 +g132 +sg133 +(dp24993 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'=\n\xd7\xa3p=\x04@' +p24994 +tp24995 +Rp24996 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p24997 +sg113 +I81 +sg146 +(lp24998 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10051 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp24999 +(lp25000 +g189 +ag0 +(g190 +g2 +Ntp25001 +Rp25002 +(dp25003 +g194 +I01 +sg195 +(lp25004 +g0 +(g197 +g2 +Ntp25005 +Rp25006 +(dp25007 +g201 +g176 +(g177 +(I0 +tp25008 +g179 +tp25009 +Rp25010 +(I1 +(I1 +tp25011 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25012 +tp25013 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25014 +Rp25015 +(dp25016 +g201 +g176 +(g177 +(I0 +tp25017 +g179 +tp25018 +Rp25019 +(I1 +(I2 +tp25020 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25021 +tp25022 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25023 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25024 +g179 +tp25025 +Rp25026 +(I1 +(I1 +I1 +I1 +tp25027 +g38 +I00 +S'\xac_;\x08\x1b\xf3C@' +p25028 +tp25029 +bsg238 +g176 +(g177 +(I0 +tp25030 +g179 +tp25031 +Rp25032 +(I1 +(I1 +I1 +I1 +tp25033 +g38 +I00 +S'\xef\x9f]\xd3\x88\xb9C?' +p25034 +tp25035 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25036 +g179 +tp25037 +Rp25038 +(I1 +(I1 +I1 +I1 +tp25039 +g38 +I00 +S'\xffUd\xeb@N\xe5?' +p25040 +tp25041 +bsg252 +g260 +sg48 +(lp25042 +g0 +(g52 +g2 +Ntp25043 +Rp25044 +(dp25045 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25046 +g179 +tp25047 +Rp25048 +(I1 +(I1 +I1 +I1 +tp25049 +g38 +I00 +S'\xef\x18\x05K\x0b\xf6M@' +p25050 +tp25051 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25052 +g279 +asg113 +I10802 +sg280 +I01 +sbaa(lp25053 +g12 +ag0 +(g190 +g2 +Ntp25054 +Rp25055 +(dp25056 +g194 +I01 +sg195 +(lp25057 +g0 +(g197 +g2 +Ntp25058 +Rp25059 +(dp25060 +g201 +g176 +(g177 +(I0 +tp25061 +g179 +tp25062 +Rp25063 +(I1 +(I1 +tp25064 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25065 +tp25066 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25067 +Rp25068 +(dp25069 +g201 +g176 +(g177 +(I0 +tp25070 +g179 +tp25071 +Rp25072 +(I1 +(I2 +tp25073 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25074 +tp25075 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25076 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25077 +g179 +tp25078 +Rp25079 +(I1 +(I1 +I1 +I1 +tp25080 +g38 +I00 +S'\x8e_\xf5]f\xfd9@' +p25081 +tp25082 +bsg238 +g176 +(g177 +(I0 +tp25083 +g179 +tp25084 +Rp25085 +(I1 +(I1 +I1 +I1 +tp25086 +g38 +I00 +S'\x00\xa0/\x97E\xa7B?' +p25087 +tp25088 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25089 +g179 +tp25090 +Rp25091 +(I1 +(I1 +I1 +I1 +tp25092 +g38 +I00 +S'\xff\xa8\x02\xde\xfc1\xe1?' +p25093 +tp25094 +bsg252 +g260 +sg48 +(lp25095 +g0 +(g52 +g2 +Ntp25096 +Rp25097 +(dp25098 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25099 +g179 +tp25100 +Rp25101 +(I1 +(I1 +I1 +I1 +tp25102 +g38 +I00 +S'\xa6\xbd3\x98K.H@' +p25103 +tp25104 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25105 +g334 +asg113 +I10803 +sg280 +I01 +sbaatp25106 +Rp25107 +sg337 +I00 +sg338 +Nsbaa(lp25108 +g340 +ag0 +(g341 +g2 +Ntp25109 +Rp25110 +(dp25111 +g17 +g24977 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25112 +(lp25113 +g189 +ag0 +(g190 +g2 +Ntp25114 +Rp25115 +(dp25116 +g194 +I01 +sg195 +(lp25117 +g0 +(g197 +g2 +Ntp25118 +Rp25119 +(dp25120 +g201 +g176 +(g177 +(I0 +tp25121 +g179 +tp25122 +Rp25123 +(I1 +(I1 +tp25124 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25125 +tp25126 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25127 +Rp25128 +(dp25129 +g201 +g176 +(g177 +(I0 +tp25130 +g179 +tp25131 +Rp25132 +(I1 +(I2 +tp25133 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25134 +tp25135 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25136 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25137 +g179 +tp25138 +Rp25139 +(I1 +(I1 +I1 +I1 +tp25140 +g38 +I00 +S'\xac_;\x08\x1b\xf3C@' +p25141 +tp25142 +bsg238 +g176 +(g177 +(I0 +tp25143 +g179 +tp25144 +Rp25145 +(I1 +(I1 +I1 +I1 +tp25146 +g38 +I00 +S'\xef\x9f]\xd3\x88\xb9C?' +p25147 +tp25148 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25149 +g179 +tp25150 +Rp25151 +(I1 +(I1 +I1 +I1 +tp25152 +g38 +I00 +S'\xffUd\xeb@N\xe5?' +p25153 +tp25154 +bsg252 +g260 +sg48 +(lp25155 +g0 +(g52 +g2 +Ntp25156 +Rp25157 +(dp25158 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25159 +g179 +tp25160 +Rp25161 +(I1 +(I1 +I1 +I1 +tp25162 +g38 +I00 +S'\xef\x18\x05K\x0b\xf6M@' +p25163 +tp25164 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25165 +g279 +asg113 +I10806 +sg280 +I01 +sbaa(lp25166 +g401 +ag0 +(g190 +g2 +Ntp25167 +Rp25168 +(dp25169 +g194 +I01 +sg195 +(lp25170 +g0 +(g197 +g2 +Ntp25171 +Rp25172 +(dp25173 +g201 +g176 +(g177 +(I0 +tp25174 +g179 +tp25175 +Rp25176 +(I1 +(I1 +tp25177 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25178 +tp25179 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25180 +Rp25181 +(dp25182 +g201 +g176 +(g177 +(I0 +tp25183 +g179 +tp25184 +Rp25185 +(I1 +(I2 +tp25186 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25187 +tp25188 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25189 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25190 +g179 +tp25191 +Rp25192 +(I1 +(I1 +I1 +I1 +tp25193 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25194 +tp25195 +bsg238 +g176 +(g177 +(I0 +tp25196 +g179 +tp25197 +Rp25198 +(I1 +(I1 +I1 +I1 +tp25199 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25200 +tp25201 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25202 +g179 +tp25203 +Rp25204 +(I1 +(I1 +I1 +I1 +tp25205 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25206 +tp25207 +bsg252 +g260 +sg48 +(lp25208 +g0 +(g52 +g2 +Ntp25209 +Rp25210 +(dp25211 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25212 +g179 +tp25213 +Rp25214 +(I1 +(I1 +I1 +I1 +tp25215 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25216 +tp25217 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25218 +g454 +asg113 +I10807 +sg280 +I01 +sbaatp25219 +Rp25220 +sg337 +I00 +sg338 +Nsbaa(lp25221 +g458 +ag0 +(g459 +g2 +Ntp25222 +Rp25223 +(dp25224 +g17 +g24977 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25225 +(lp25226 +g189 +ag0 +(g190 +g2 +Ntp25227 +Rp25228 +(dp25229 +g194 +I01 +sg195 +(lp25230 +g0 +(g197 +g2 +Ntp25231 +Rp25232 +(dp25233 +g201 +g176 +(g177 +(I0 +tp25234 +g179 +tp25235 +Rp25236 +(I1 +(I1 +tp25237 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25238 +tp25239 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25240 +Rp25241 +(dp25242 +g201 +g176 +(g177 +(I0 +tp25243 +g179 +tp25244 +Rp25245 +(I1 +(I2 +tp25246 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25247 +tp25248 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp25249 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25250 +g179 +tp25251 +Rp25252 +(I1 +(I1 +I1 +I1 +tp25253 +g38 +I00 +S'&{\t\x89H\xe1C@' +p25254 +tp25255 +bsg238 +g176 +(g177 +(I0 +tp25256 +g179 +tp25257 +Rp25258 +(I1 +(I1 +I1 +I1 +tp25259 +g38 +I00 +S'\x15\xae\xaa\x04;\x11Y?' +p25260 +tp25261 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25262 +g179 +tp25263 +Rp25264 +(I1 +(I1 +I1 +I1 +tp25265 +g38 +I00 +S'%`\x1aw\xa4C\xe5?' +p25266 +tp25267 +bsg252 +g513 +sg48 +(lp25268 +g0 +(g52 +g2 +Ntp25269 +Rp25270 +(dp25271 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp25272 +g179 +tp25273 +Rp25274 +(I1 +(I1 +I1 +I1 +tp25275 +g38 +I00 +S'4\x17}G\x1f\xe7M@' +p25276 +tp25277 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp25278 +g527 +asg113 +I10810 +sg280 +I01 +sbaa(lp25279 +g529 +ag0 +(g190 +g2 +Ntp25280 +Rp25281 +(dp25282 +g194 +I01 +sg195 +(lp25283 +g0 +(g197 +g2 +Ntp25284 +Rp25285 +(dp25286 +g201 +g176 +(g177 +(I0 +tp25287 +g179 +tp25288 +Rp25289 +(I1 +(I1 +tp25290 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25291 +tp25292 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25293 +Rp25294 +(dp25295 +g201 +g176 +(g177 +(I0 +tp25296 +g179 +tp25297 +Rp25298 +(I1 +(I2 +tp25299 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25300 +tp25301 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25302 +Rp25303 +(dp25304 +g201 +g176 +(g177 +(I0 +tp25305 +g179 +tp25306 +Rp25307 +(I1 +(I2 +tp25308 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25309 +tp25310 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp25311 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25312 +g179 +tp25313 +Rp25314 +(I1 +(I1 +I1 +I1 +tp25315 +g38 +I00 +S'\x05L\x8e\xd8z\x919@' +p25316 +tp25317 +bsg238 +g176 +(g177 +(I0 +tp25318 +g179 +tp25319 +Rp25320 +(I1 +(I1 +I1 +I1 +tp25321 +g38 +I00 +S'\t\xecy\x0bEmP?' +p25322 +tp25323 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25324 +g179 +tp25325 +Rp25326 +(I1 +(I1 +I1 +I1 +tp25327 +g38 +I00 +S'\x96Y\xe6\xe9\xab\r\xe1?' +p25328 +tp25329 +bsg252 +g586 +sg48 +(lp25330 +g0 +(g52 +g2 +Ntp25331 +Rp25332 +(dp25333 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp25334 +g179 +tp25335 +Rp25336 +(I1 +(I1 +I1 +I1 +tp25337 +g38 +I00 +S'\xfb\xed\xeb\xc09\xfbG@' +p25338 +tp25339 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp25340 +g600 +asg113 +I10811 +sg280 +I01 +sbaatp25341 +Rp25342 +sg337 +I00 +sg338 +Nsbaa(lp25343 +g604 +ag0 +(g605 +g2 +Ntp25344 +Rp25345 +(dp25346 +g17 +g24977 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25347 +(lp25348 +g611 +ag0 +(g190 +g2 +Ntp25349 +Rp25350 +(dp25351 +g194 +I01 +sg195 +(lp25352 +g0 +(g197 +g2 +Ntp25353 +Rp25354 +(dp25355 +g201 +g176 +(g177 +(I0 +tp25356 +g179 +tp25357 +Rp25358 +(I1 +(I1 +tp25359 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25360 +tp25361 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25362 +Rp25363 +(dp25364 +g201 +g176 +(g177 +(I0 +tp25365 +g179 +tp25366 +Rp25367 +(I1 +(I2 +tp25368 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25369 +tp25370 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp25371 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25372 +g179 +tp25373 +Rp25374 +(I1 +(I1 +I1 +I1 +tp25375 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25376 +tp25377 +bsg238 +g176 +(g177 +(I0 +tp25378 +g179 +tp25379 +Rp25380 +(I1 +(I1 +I1 +I1 +tp25381 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25382 +tp25383 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25384 +g179 +tp25385 +Rp25386 +(I1 +(I1 +I1 +I1 +tp25387 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25388 +tp25389 +bsg252 +g513 +sg48 +(lp25390 +g0 +(g52 +g2 +Ntp25391 +Rp25392 +(dp25393 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp25394 +g179 +tp25395 +Rp25396 +(I1 +(I1 +I1 +I1 +tp25397 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25398 +tp25399 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp25400 +g664 +asg113 +I10814 +sg280 +I01 +sbaa(lp25401 +g666 +ag0 +(g190 +g2 +Ntp25402 +Rp25403 +(dp25404 +g194 +I01 +sg195 +(lp25405 +g0 +(g197 +g2 +Ntp25406 +Rp25407 +(dp25408 +g201 +g176 +(g177 +(I0 +tp25409 +g179 +tp25410 +Rp25411 +(I1 +(I1 +tp25412 +g208 +I00 +S"C'\x00\x00\x00\x00\x00\x00" +p25413 +tp25414 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25415 +Rp25416 +(dp25417 +g201 +g176 +(g177 +(I0 +tp25418 +g179 +tp25419 +Rp25420 +(I1 +(I2 +tp25421 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25422 +tp25423 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp25424 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25425 +g179 +tp25426 +Rp25427 +(I1 +(I1 +I1 +I1 +tp25428 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25429 +tp25430 +bsg238 +g176 +(g177 +(I0 +tp25431 +g179 +tp25432 +Rp25433 +(I1 +(I1 +I1 +I1 +tp25434 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25435 +tp25436 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25437 +g179 +tp25438 +Rp25439 +(I1 +(I1 +I1 +I1 +tp25440 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25441 +tp25442 +bsg252 +g713 +sg48 +(lp25443 +g0 +(g52 +g2 +Ntp25444 +Rp25445 +(dp25446 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp25447 +g179 +tp25448 +Rp25449 +(I1 +(I1 +I1 +I1 +tp25450 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25451 +tp25452 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp25453 +g727 +asg113 +I10815 +sg280 +I01 +sbaatp25454 +Rp25455 +sg337 +I00 +sg338 +Nsbaatp25456 +Rp25457 +aa(lp25458 +I10052 +ag7 +((lp25459 +(lp25460 +g12 +ag0 +(g13 +g2 +Ntp25461 +Rp25462 +(dp25463 +g17 +g0 +(g18 +g2 +Ntp25464 +Rp25465 +(dp25466 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p25467 +sg116 +g0 +(g117 +g2 +Ntp25468 +Rp25469 +(dp25470 +g121 +(lp25471 +g0 +(g123 +g2 +Ntp25472 +Rp25473 +(dp25474 +g127 +g0 +(g128 +g2 +Ntp25475 +Rp25476 +(dp25477 +g23 +g132 +sg133 +(dp25478 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S')\\\x8f\xc2\xf5(\x0f@' +p25479 +tp25480 +Rp25481 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p25482 +sg113 +I82 +sg146 +(lp25483 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp25484 +Rp25485 +(dp25486 +g127 +g7303 +sg148 +g149 +sbasbsg163 +Nsg113 +I10052 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25487 +(lp25488 +g189 +ag0 +(g190 +g2 +Ntp25489 +Rp25490 +(dp25491 +g194 +I01 +sg195 +(lp25492 +g0 +(g197 +g2 +Ntp25493 +Rp25494 +(dp25495 +g201 +g176 +(g177 +(I0 +tp25496 +g179 +tp25497 +Rp25498 +(I1 +(I1 +tp25499 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25500 +tp25501 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25502 +Rp25503 +(dp25504 +g201 +g176 +(g177 +(I0 +tp25505 +g179 +tp25506 +Rp25507 +(I1 +(I2 +tp25508 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25509 +tp25510 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25511 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25512 +g179 +tp25513 +Rp25514 +(I1 +(I1 +I1 +I1 +tp25515 +g38 +I00 +S'w\x04\xb8\xe6\xc8\x7fH@' +p25516 +tp25517 +bsg238 +g176 +(g177 +(I0 +tp25518 +g179 +tp25519 +Rp25520 +(I1 +(I1 +I1 +I1 +tp25521 +g38 +I00 +S'\xc8\x8f\x83\x05\xf86E?' +p25522 +tp25523 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25524 +g179 +tp25525 +Rp25526 +(I1 +(I1 +I1 +I1 +tp25527 +g38 +I00 +S'\xe9\x19a\x0cG\x9c\xe7?' +p25528 +tp25529 +bsg252 +g260 +sg48 +(lp25530 +g0 +(g52 +g2 +Ntp25531 +Rp25532 +(dp25533 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25534 +g179 +tp25535 +Rp25536 +(I1 +(I1 +I1 +I1 +tp25537 +g38 +I00 +S'8F\xb4\xf4\xe1\x99P@' +p25538 +tp25539 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25540 +g279 +asg113 +I10818 +sg280 +I01 +sbaa(lp25541 +g12 +ag0 +(g190 +g2 +Ntp25542 +Rp25543 +(dp25544 +g194 +I01 +sg195 +(lp25545 +g0 +(g197 +g2 +Ntp25546 +Rp25547 +(dp25548 +g201 +g176 +(g177 +(I0 +tp25549 +g179 +tp25550 +Rp25551 +(I1 +(I1 +tp25552 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25553 +tp25554 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25555 +Rp25556 +(dp25557 +g201 +g176 +(g177 +(I0 +tp25558 +g179 +tp25559 +Rp25560 +(I1 +(I2 +tp25561 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25562 +tp25563 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25564 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25565 +g179 +tp25566 +Rp25567 +(I1 +(I1 +I1 +I1 +tp25568 +g38 +I00 +S'\x01\xca\x8d\xd1k/K@' +p25569 +tp25570 +bsg238 +g176 +(g177 +(I0 +tp25571 +g179 +tp25572 +Rp25573 +(I1 +(I1 +I1 +I1 +tp25574 +g38 +I00 +S'\xb1\xb1\x8at3lP?' +p25575 +tp25576 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25577 +g179 +tp25578 +Rp25579 +(I1 +(I1 +I1 +I1 +tp25580 +g38 +I00 +S'C(\x106\xc1\xde\xe8?' +p25581 +tp25582 +bsg252 +g260 +sg48 +(lp25583 +g0 +(g52 +g2 +Ntp25584 +Rp25585 +(dp25586 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25587 +g179 +tp25588 +Rp25589 +(I1 +(I1 +I1 +I1 +tp25590 +g38 +I00 +S'O\\\x03\xda\x9f|Q@' +p25591 +tp25592 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25593 +g334 +asg113 +I10819 +sg280 +I01 +sbaatp25594 +Rp25595 +sg337 +I00 +sg338 +Nsbaa(lp25596 +g340 +ag0 +(g341 +g2 +Ntp25597 +Rp25598 +(dp25599 +g17 +g25465 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25600 +(lp25601 +g189 +ag0 +(g190 +g2 +Ntp25602 +Rp25603 +(dp25604 +g194 +I01 +sg195 +(lp25605 +g0 +(g197 +g2 +Ntp25606 +Rp25607 +(dp25608 +g201 +g176 +(g177 +(I0 +tp25609 +g179 +tp25610 +Rp25611 +(I1 +(I1 +tp25612 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25613 +tp25614 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25615 +Rp25616 +(dp25617 +g201 +g176 +(g177 +(I0 +tp25618 +g179 +tp25619 +Rp25620 +(I1 +(I2 +tp25621 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25622 +tp25623 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25624 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25625 +g179 +tp25626 +Rp25627 +(I1 +(I1 +I1 +I1 +tp25628 +g38 +I00 +S'w\x04\xb8\xe6\xc8\x7fH@' +p25629 +tp25630 +bsg238 +g176 +(g177 +(I0 +tp25631 +g179 +tp25632 +Rp25633 +(I1 +(I1 +I1 +I1 +tp25634 +g38 +I00 +S'\xc8\x8f\x83\x05\xf86E?' +p25635 +tp25636 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25637 +g179 +tp25638 +Rp25639 +(I1 +(I1 +I1 +I1 +tp25640 +g38 +I00 +S'\xe9\x19a\x0cG\x9c\xe7?' +p25641 +tp25642 +bsg252 +g260 +sg48 +(lp25643 +g0 +(g52 +g2 +Ntp25644 +Rp25645 +(dp25646 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25647 +g179 +tp25648 +Rp25649 +(I1 +(I1 +I1 +I1 +tp25650 +g38 +I00 +S'8F\xb4\xf4\xe1\x99P@' +p25651 +tp25652 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25653 +g279 +asg113 +I10822 +sg280 +I01 +sbaa(lp25654 +g401 +ag0 +(g190 +g2 +Ntp25655 +Rp25656 +(dp25657 +g194 +I01 +sg195 +(lp25658 +g0 +(g197 +g2 +Ntp25659 +Rp25660 +(dp25661 +g201 +g176 +(g177 +(I0 +tp25662 +g179 +tp25663 +Rp25664 +(I1 +(I1 +tp25665 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25666 +tp25667 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25668 +Rp25669 +(dp25670 +g201 +g176 +(g177 +(I0 +tp25671 +g179 +tp25672 +Rp25673 +(I1 +(I2 +tp25674 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25675 +tp25676 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25677 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25678 +g179 +tp25679 +Rp25680 +(I1 +(I1 +I1 +I1 +tp25681 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25682 +tp25683 +bsg238 +g176 +(g177 +(I0 +tp25684 +g179 +tp25685 +Rp25686 +(I1 +(I1 +I1 +I1 +tp25687 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25688 +tp25689 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25690 +g179 +tp25691 +Rp25692 +(I1 +(I1 +I1 +I1 +tp25693 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25694 +tp25695 +bsg252 +g260 +sg48 +(lp25696 +g0 +(g52 +g2 +Ntp25697 +Rp25698 +(dp25699 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp25700 +g179 +tp25701 +Rp25702 +(I1 +(I1 +I1 +I1 +tp25703 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25704 +tp25705 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp25706 +g454 +asg113 +I10823 +sg280 +I01 +sbaatp25707 +Rp25708 +sg337 +I00 +sg338 +Nsbaa(lp25709 +g458 +ag0 +(g459 +g2 +Ntp25710 +Rp25711 +(dp25712 +g17 +g25465 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25713 +(lp25714 +g189 +ag0 +(g190 +g2 +Ntp25715 +Rp25716 +(dp25717 +g194 +I01 +sg195 +(lp25718 +g0 +(g197 +g2 +Ntp25719 +Rp25720 +(dp25721 +g201 +g176 +(g177 +(I0 +tp25722 +g179 +tp25723 +Rp25724 +(I1 +(I1 +tp25725 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25726 +tp25727 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25728 +Rp25729 +(dp25730 +g201 +g176 +(g177 +(I0 +tp25731 +g179 +tp25732 +Rp25733 +(I1 +(I2 +tp25734 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25735 +tp25736 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp25737 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25738 +g179 +tp25739 +Rp25740 +(I1 +(I1 +I1 +I1 +tp25741 +g38 +I00 +S'\xd2\xfd|\xd8=\x92H@' +p25742 +tp25743 +bsg238 +g176 +(g177 +(I0 +tp25744 +g179 +tp25745 +Rp25746 +(I1 +(I1 +I1 +I1 +tp25747 +g38 +I00 +S'\x84\xd5g\xbe\x19\xa7X?' +p25748 +tp25749 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25750 +g179 +tp25751 +Rp25752 +(I1 +(I1 +I1 +I1 +tp25753 +g38 +I00 +S'\r\x94BGA\xa4\xe7?' +p25754 +tp25755 +bsg252 +g513 +sg48 +(lp25756 +g0 +(g52 +g2 +Ntp25757 +Rp25758 +(dp25759 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp25760 +g179 +tp25761 +Rp25762 +(I1 +(I1 +I1 +I1 +tp25763 +g38 +I00 +S'\x19\xd0\x1a\xe6}\x9fP@' +p25764 +tp25765 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp25766 +g527 +asg113 +I10826 +sg280 +I01 +sbaa(lp25767 +g529 +ag0 +(g190 +g2 +Ntp25768 +Rp25769 +(dp25770 +g194 +I01 +sg195 +(lp25771 +g0 +(g197 +g2 +Ntp25772 +Rp25773 +(dp25774 +g201 +g176 +(g177 +(I0 +tp25775 +g179 +tp25776 +Rp25777 +(I1 +(I1 +tp25778 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25779 +tp25780 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25781 +Rp25782 +(dp25783 +g201 +g176 +(g177 +(I0 +tp25784 +g179 +tp25785 +Rp25786 +(I1 +(I2 +tp25787 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25788 +tp25789 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25790 +Rp25791 +(dp25792 +g201 +g176 +(g177 +(I0 +tp25793 +g179 +tp25794 +Rp25795 +(I1 +(I2 +tp25796 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25797 +tp25798 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp25799 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25800 +g179 +tp25801 +Rp25802 +(I1 +(I1 +I1 +I1 +tp25803 +g38 +I00 +S'\x11D7w\xcb\x9fJ@' +p25804 +tp25805 +bsg238 +g176 +(g177 +(I0 +tp25806 +g179 +tp25807 +Rp25808 +(I1 +(I1 +I1 +I1 +tp25809 +g38 +I00 +S'CSq\xfc\x15\x10V?' +p25810 +tp25811 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25812 +g179 +tp25813 +Rp25814 +(I1 +(I1 +I1 +I1 +tp25815 +g38 +I00 +S's$\x0cRR\x9c\xe8?' +p25816 +tp25817 +bsg252 +g586 +sg48 +(lp25818 +g0 +(g52 +g2 +Ntp25819 +Rp25820 +(dp25821 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp25822 +g179 +tp25823 +Rp25824 +(I1 +(I1 +I1 +I1 +tp25825 +g38 +I00 +S'\xa1\x89\xb0\xe1\xe9MQ@' +p25826 +tp25827 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp25828 +g600 +asg113 +I10827 +sg280 +I01 +sbaatp25829 +Rp25830 +sg337 +I00 +sg338 +Nsbaa(lp25831 +g604 +ag0 +(g605 +g2 +Ntp25832 +Rp25833 +(dp25834 +g17 +g25465 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25835 +(lp25836 +g611 +ag0 +(g190 +g2 +Ntp25837 +Rp25838 +(dp25839 +g194 +I01 +sg195 +(lp25840 +g0 +(g197 +g2 +Ntp25841 +Rp25842 +(dp25843 +g201 +g176 +(g177 +(I0 +tp25844 +g179 +tp25845 +Rp25846 +(I1 +(I1 +tp25847 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25848 +tp25849 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25850 +Rp25851 +(dp25852 +g201 +g176 +(g177 +(I0 +tp25853 +g179 +tp25854 +Rp25855 +(I1 +(I2 +tp25856 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25857 +tp25858 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp25859 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25860 +g179 +tp25861 +Rp25862 +(I1 +(I1 +I1 +I1 +tp25863 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25864 +tp25865 +bsg238 +g176 +(g177 +(I0 +tp25866 +g179 +tp25867 +Rp25868 +(I1 +(I1 +I1 +I1 +tp25869 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25870 +tp25871 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25872 +g179 +tp25873 +Rp25874 +(I1 +(I1 +I1 +I1 +tp25875 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25876 +tp25877 +bsg252 +g513 +sg48 +(lp25878 +g0 +(g52 +g2 +Ntp25879 +Rp25880 +(dp25881 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp25882 +g179 +tp25883 +Rp25884 +(I1 +(I1 +I1 +I1 +tp25885 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25886 +tp25887 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp25888 +g664 +asg113 +I10830 +sg280 +I01 +sbaa(lp25889 +g666 +ag0 +(g190 +g2 +Ntp25890 +Rp25891 +(dp25892 +g194 +I01 +sg195 +(lp25893 +g0 +(g197 +g2 +Ntp25894 +Rp25895 +(dp25896 +g201 +g176 +(g177 +(I0 +tp25897 +g179 +tp25898 +Rp25899 +(I1 +(I1 +tp25900 +g208 +I00 +S"D'\x00\x00\x00\x00\x00\x00" +p25901 +tp25902 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25903 +Rp25904 +(dp25905 +g201 +g176 +(g177 +(I0 +tp25906 +g179 +tp25907 +Rp25908 +(I1 +(I2 +tp25909 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25910 +tp25911 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp25912 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25913 +g179 +tp25914 +Rp25915 +(I1 +(I1 +I1 +I1 +tp25916 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25917 +tp25918 +bsg238 +g176 +(g177 +(I0 +tp25919 +g179 +tp25920 +Rp25921 +(I1 +(I1 +I1 +I1 +tp25922 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25923 +tp25924 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp25925 +g179 +tp25926 +Rp25927 +(I1 +(I1 +I1 +I1 +tp25928 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25929 +tp25930 +bsg252 +g713 +sg48 +(lp25931 +g0 +(g52 +g2 +Ntp25932 +Rp25933 +(dp25934 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp25935 +g179 +tp25936 +Rp25937 +(I1 +(I1 +I1 +I1 +tp25938 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p25939 +tp25940 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp25941 +g727 +asg113 +I10831 +sg280 +I01 +sbaatp25942 +Rp25943 +sg337 +I00 +sg338 +Nsbaatp25944 +Rp25945 +aa(lp25946 +I10053 +ag7 +((lp25947 +(lp25948 +g12 +ag0 +(g13 +g2 +Ntp25949 +Rp25950 +(dp25951 +g17 +g0 +(g18 +g2 +Ntp25952 +Rp25953 +(dp25954 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p25955 +sg116 +g0 +(g117 +g2 +Ntp25956 +Rp25957 +(dp25958 +g121 +(lp25959 +g0 +(g123 +g2 +Ntp25960 +Rp25961 +(dp25962 +g127 +g10240 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp25963 +Rp25964 +(dp25965 +g127 +g4839 +sg148 +g162 +sbasbsg163 +Nsg113 +I10053 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp25966 +(lp25967 +g189 +ag0 +(g190 +g2 +Ntp25968 +Rp25969 +(dp25970 +g194 +I01 +sg195 +(lp25971 +g0 +(g197 +g2 +Ntp25972 +Rp25973 +(dp25974 +g201 +g176 +(g177 +(I0 +tp25975 +g179 +tp25976 +Rp25977 +(I1 +(I1 +tp25978 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p25979 +tp25980 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp25981 +Rp25982 +(dp25983 +g201 +g176 +(g177 +(I0 +tp25984 +g179 +tp25985 +Rp25986 +(I1 +(I2 +tp25987 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p25988 +tp25989 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp25990 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp25991 +g179 +tp25992 +Rp25993 +(I1 +(I1 +I1 +I1 +tp25994 +g38 +I00 +S'\x00\x8b\x8b\xdd\x02\xd5H@' +p25995 +tp25996 +bsg238 +g176 +(g177 +(I0 +tp25997 +g179 +tp25998 +Rp25999 +(I1 +(I1 +I1 +I1 +tp26000 +g38 +I00 +S'\x81\x9f|C\xb3\xdaC?' +p26001 +tp26002 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26003 +g179 +tp26004 +Rp26005 +(I1 +(I1 +I1 +I1 +tp26006 +g38 +I00 +S'\x04\x0ex\x16<\xc5\xe7?' +p26007 +tp26008 +bsg252 +g260 +sg48 +(lp26009 +g0 +(g52 +g2 +Ntp26010 +Rp26011 +(dp26012 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26013 +g179 +tp26014 +Rp26015 +(I1 +(I1 +I1 +I1 +tp26016 +g38 +I00 +S'\xdbi\xcc?\xae\xb6P@' +p26017 +tp26018 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26019 +g279 +asg113 +I10834 +sg280 +I01 +sbaa(lp26020 +g12 +ag0 +(g190 +g2 +Ntp26021 +Rp26022 +(dp26023 +g194 +I01 +sg195 +(lp26024 +g0 +(g197 +g2 +Ntp26025 +Rp26026 +(dp26027 +g201 +g176 +(g177 +(I0 +tp26028 +g179 +tp26029 +Rp26030 +(I1 +(I1 +tp26031 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26032 +tp26033 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26034 +Rp26035 +(dp26036 +g201 +g176 +(g177 +(I0 +tp26037 +g179 +tp26038 +Rp26039 +(I1 +(I2 +tp26040 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26041 +tp26042 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26043 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26044 +g179 +tp26045 +Rp26046 +(I1 +(I1 +I1 +I1 +tp26047 +g38 +I00 +S'\xea\x93y\xe8\x94\x97L@' +p26048 +tp26049 +bsg238 +g176 +(g177 +(I0 +tp26050 +g179 +tp26051 +Rp26052 +(I1 +(I1 +I1 +I1 +tp26053 +g38 +I00 +S'\xd2)\x86\xc7F\xf3N?' +p26054 +tp26055 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26056 +g179 +tp26057 +Rp26058 +(I1 +(I1 +I1 +I1 +tp26059 +g38 +I00 +S'T\xf1e\x1e\x7f\x81\xe9?' +p26060 +tp26061 +bsg252 +g260 +sg48 +(lp26062 +g0 +(g52 +g2 +Ntp26063 +Rp26064 +(dp26065 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26066 +g179 +tp26067 +Rp26068 +(I1 +(I1 +I1 +I1 +tp26069 +g38 +I00 +S'\xaf\xad_a\r\xefQ@' +p26070 +tp26071 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26072 +g334 +asg113 +I10835 +sg280 +I01 +sbaatp26073 +Rp26074 +sg337 +I00 +sg338 +Nsbaa(lp26075 +g340 +ag0 +(g341 +g2 +Ntp26076 +Rp26077 +(dp26078 +g17 +g25953 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26079 +(lp26080 +g189 +ag0 +(g190 +g2 +Ntp26081 +Rp26082 +(dp26083 +g194 +I01 +sg195 +(lp26084 +g0 +(g197 +g2 +Ntp26085 +Rp26086 +(dp26087 +g201 +g176 +(g177 +(I0 +tp26088 +g179 +tp26089 +Rp26090 +(I1 +(I1 +tp26091 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26092 +tp26093 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26094 +Rp26095 +(dp26096 +g201 +g176 +(g177 +(I0 +tp26097 +g179 +tp26098 +Rp26099 +(I1 +(I2 +tp26100 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26101 +tp26102 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26103 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26104 +g179 +tp26105 +Rp26106 +(I1 +(I1 +I1 +I1 +tp26107 +g38 +I00 +S'\x00\x8b\x8b\xdd\x02\xd5H@' +p26108 +tp26109 +bsg238 +g176 +(g177 +(I0 +tp26110 +g179 +tp26111 +Rp26112 +(I1 +(I1 +I1 +I1 +tp26113 +g38 +I00 +S'\x81\x9f|C\xb3\xdaC?' +p26114 +tp26115 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26116 +g179 +tp26117 +Rp26118 +(I1 +(I1 +I1 +I1 +tp26119 +g38 +I00 +S'\x04\x0ex\x16<\xc5\xe7?' +p26120 +tp26121 +bsg252 +g260 +sg48 +(lp26122 +g0 +(g52 +g2 +Ntp26123 +Rp26124 +(dp26125 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26126 +g179 +tp26127 +Rp26128 +(I1 +(I1 +I1 +I1 +tp26129 +g38 +I00 +S'\xdbi\xcc?\xae\xb6P@' +p26130 +tp26131 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26132 +g279 +asg113 +I10838 +sg280 +I01 +sbaa(lp26133 +g401 +ag0 +(g190 +g2 +Ntp26134 +Rp26135 +(dp26136 +g194 +I01 +sg195 +(lp26137 +g0 +(g197 +g2 +Ntp26138 +Rp26139 +(dp26140 +g201 +g176 +(g177 +(I0 +tp26141 +g179 +tp26142 +Rp26143 +(I1 +(I1 +tp26144 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26145 +tp26146 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26147 +Rp26148 +(dp26149 +g201 +g176 +(g177 +(I0 +tp26150 +g179 +tp26151 +Rp26152 +(I1 +(I2 +tp26153 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26154 +tp26155 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26156 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26157 +g179 +tp26158 +Rp26159 +(I1 +(I1 +I1 +I1 +tp26160 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26161 +tp26162 +bsg238 +g176 +(g177 +(I0 +tp26163 +g179 +tp26164 +Rp26165 +(I1 +(I1 +I1 +I1 +tp26166 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26167 +tp26168 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26169 +g179 +tp26170 +Rp26171 +(I1 +(I1 +I1 +I1 +tp26172 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26173 +tp26174 +bsg252 +g260 +sg48 +(lp26175 +g0 +(g52 +g2 +Ntp26176 +Rp26177 +(dp26178 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26179 +g179 +tp26180 +Rp26181 +(I1 +(I1 +I1 +I1 +tp26182 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26183 +tp26184 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26185 +g454 +asg113 +I10839 +sg280 +I01 +sbaatp26186 +Rp26187 +sg337 +I00 +sg338 +Nsbaa(lp26188 +g458 +ag0 +(g459 +g2 +Ntp26189 +Rp26190 +(dp26191 +g17 +g25953 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26192 +(lp26193 +g189 +ag0 +(g190 +g2 +Ntp26194 +Rp26195 +(dp26196 +g194 +I01 +sg195 +(lp26197 +g0 +(g197 +g2 +Ntp26198 +Rp26199 +(dp26200 +g201 +g176 +(g177 +(I0 +tp26201 +g179 +tp26202 +Rp26203 +(I1 +(I1 +tp26204 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26205 +tp26206 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26207 +Rp26208 +(dp26209 +g201 +g176 +(g177 +(I0 +tp26210 +g179 +tp26211 +Rp26212 +(I1 +(I2 +tp26213 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26214 +tp26215 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp26216 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26217 +g179 +tp26218 +Rp26219 +(I1 +(I1 +I1 +I1 +tp26220 +g38 +I00 +S'/\xeb\xe92\x02\xebH@' +p26221 +tp26222 +bsg238 +g176 +(g177 +(I0 +tp26223 +g179 +tp26224 +Rp26225 +(I1 +(I1 +I1 +I1 +tp26226 +g38 +I00 +S'.\xdc\x85J\xd1uV?' +p26227 +tp26228 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26229 +g179 +tp26230 +Rp26231 +(I1 +(I1 +I1 +I1 +tp26232 +g38 +I00 +S'0\xa78\x8d\x03\xcf\xe7?' +p26233 +tp26234 +bsg252 +g513 +sg48 +(lp26235 +g0 +(g52 +g2 +Ntp26236 +Rp26237 +(dp26238 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp26239 +g179 +tp26240 +Rp26241 +(I1 +(I1 +I1 +I1 +tp26242 +g38 +I00 +S'\x8e\xd5K\x7f\x8e\xbdP@' +p26243 +tp26244 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp26245 +g527 +asg113 +I10842 +sg280 +I01 +sbaa(lp26246 +g529 +ag0 +(g190 +g2 +Ntp26247 +Rp26248 +(dp26249 +g194 +I01 +sg195 +(lp26250 +g0 +(g197 +g2 +Ntp26251 +Rp26252 +(dp26253 +g201 +g176 +(g177 +(I0 +tp26254 +g179 +tp26255 +Rp26256 +(I1 +(I1 +tp26257 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26258 +tp26259 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26260 +Rp26261 +(dp26262 +g201 +g176 +(g177 +(I0 +tp26263 +g179 +tp26264 +Rp26265 +(I1 +(I2 +tp26266 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26267 +tp26268 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26269 +Rp26270 +(dp26271 +g201 +g176 +(g177 +(I0 +tp26272 +g179 +tp26273 +Rp26274 +(I1 +(I2 +tp26275 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26276 +tp26277 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp26278 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26279 +g179 +tp26280 +Rp26281 +(I1 +(I1 +I1 +I1 +tp26282 +g38 +I00 +S'^\x16<\x1a\xc1\x0bL@' +p26283 +tp26284 +bsg238 +g176 +(g177 +(I0 +tp26285 +g179 +tp26286 +Rp26287 +(I1 +(I1 +I1 +I1 +tp26288 +g38 +I00 +S'\x02\xf4i\x92!*W?' +p26289 +tp26290 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26291 +g179 +tp26292 +Rp26293 +(I1 +(I1 +I1 +I1 +tp26294 +g38 +I00 +S'\xb7a\xc5GOB\xe9?' +p26295 +tp26296 +bsg252 +g586 +sg48 +(lp26297 +g0 +(g52 +g2 +Ntp26298 +Rp26299 +(dp26300 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp26301 +g179 +tp26302 +Rp26303 +(I1 +(I1 +I1 +I1 +tp26304 +g38 +I00 +S'\xb5\xc8v\xbe\x9f\xc2Q@' +p26305 +tp26306 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp26307 +g600 +asg113 +I10843 +sg280 +I01 +sbaatp26308 +Rp26309 +sg337 +I00 +sg338 +Nsbaa(lp26310 +g604 +ag0 +(g605 +g2 +Ntp26311 +Rp26312 +(dp26313 +g17 +g25953 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26314 +(lp26315 +g611 +ag0 +(g190 +g2 +Ntp26316 +Rp26317 +(dp26318 +g194 +I01 +sg195 +(lp26319 +g0 +(g197 +g2 +Ntp26320 +Rp26321 +(dp26322 +g201 +g176 +(g177 +(I0 +tp26323 +g179 +tp26324 +Rp26325 +(I1 +(I1 +tp26326 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26327 +tp26328 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26329 +Rp26330 +(dp26331 +g201 +g176 +(g177 +(I0 +tp26332 +g179 +tp26333 +Rp26334 +(I1 +(I2 +tp26335 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26336 +tp26337 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp26338 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26339 +g179 +tp26340 +Rp26341 +(I1 +(I1 +I1 +I1 +tp26342 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26343 +tp26344 +bsg238 +g176 +(g177 +(I0 +tp26345 +g179 +tp26346 +Rp26347 +(I1 +(I1 +I1 +I1 +tp26348 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26349 +tp26350 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26351 +g179 +tp26352 +Rp26353 +(I1 +(I1 +I1 +I1 +tp26354 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26355 +tp26356 +bsg252 +g513 +sg48 +(lp26357 +g0 +(g52 +g2 +Ntp26358 +Rp26359 +(dp26360 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp26361 +g179 +tp26362 +Rp26363 +(I1 +(I1 +I1 +I1 +tp26364 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26365 +tp26366 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp26367 +g664 +asg113 +I10846 +sg280 +I01 +sbaa(lp26368 +g666 +ag0 +(g190 +g2 +Ntp26369 +Rp26370 +(dp26371 +g194 +I01 +sg195 +(lp26372 +g0 +(g197 +g2 +Ntp26373 +Rp26374 +(dp26375 +g201 +g176 +(g177 +(I0 +tp26376 +g179 +tp26377 +Rp26378 +(I1 +(I1 +tp26379 +g208 +I00 +S"E'\x00\x00\x00\x00\x00\x00" +p26380 +tp26381 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26382 +Rp26383 +(dp26384 +g201 +g176 +(g177 +(I0 +tp26385 +g179 +tp26386 +Rp26387 +(I1 +(I2 +tp26388 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26389 +tp26390 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp26391 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26392 +g179 +tp26393 +Rp26394 +(I1 +(I1 +I1 +I1 +tp26395 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26396 +tp26397 +bsg238 +g176 +(g177 +(I0 +tp26398 +g179 +tp26399 +Rp26400 +(I1 +(I1 +I1 +I1 +tp26401 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26402 +tp26403 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26404 +g179 +tp26405 +Rp26406 +(I1 +(I1 +I1 +I1 +tp26407 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26408 +tp26409 +bsg252 +g713 +sg48 +(lp26410 +g0 +(g52 +g2 +Ntp26411 +Rp26412 +(dp26413 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp26414 +g179 +tp26415 +Rp26416 +(I1 +(I1 +I1 +I1 +tp26417 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26418 +tp26419 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp26420 +g727 +asg113 +I10847 +sg280 +I01 +sbaatp26421 +Rp26422 +sg337 +I00 +sg338 +Nsbaatp26423 +Rp26424 +aa(lp26425 +I10054 +ag7 +((lp26426 +(lp26427 +g12 +ag0 +(g13 +g2 +Ntp26428 +Rp26429 +(dp26430 +g17 +g0 +(g18 +g2 +Ntp26431 +Rp26432 +(dp26433 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p26434 +sg116 +g0 +(g117 +g2 +Ntp26435 +Rp26436 +(dp26437 +g121 +(lp26438 +g0 +(g123 +g2 +Ntp26439 +Rp26440 +(dp26441 +g127 +g0 +(g128 +g2 +Ntp26442 +Rp26443 +(dp26444 +g23 +g132 +sg133 +(dp26445 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xf6(\\\x8f\xc2\xf5\x00@' +p26446 +tp26447 +Rp26448 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p26449 +sg113 +I83 +sg146 +(lp26450 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp26451 +Rp26452 +(dp26453 +g127 +g16659 +sg148 +g149 +sbasbsg163 +Nsg113 +I10054 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26454 +(lp26455 +g189 +ag0 +(g190 +g2 +Ntp26456 +Rp26457 +(dp26458 +g194 +I01 +sg195 +(lp26459 +g0 +(g197 +g2 +Ntp26460 +Rp26461 +(dp26462 +g201 +g176 +(g177 +(I0 +tp26463 +g179 +tp26464 +Rp26465 +(I1 +(I1 +tp26466 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26467 +tp26468 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26469 +Rp26470 +(dp26471 +g201 +g176 +(g177 +(I0 +tp26472 +g179 +tp26473 +Rp26474 +(I1 +(I2 +tp26475 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26476 +tp26477 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26478 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26479 +g179 +tp26480 +Rp26481 +(I1 +(I1 +I1 +I1 +tp26482 +g38 +I00 +S'g\\\x17c.q\x0e@' +p26483 +tp26484 +bsg238 +g176 +(g177 +(I0 +tp26485 +g179 +tp26486 +Rp26487 +(I1 +(I1 +I1 +I1 +tp26488 +g38 +I00 +S'\xd8\x1ew\xcd\x81\x82+?' +p26489 +tp26490 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26491 +g179 +tp26492 +Rp26493 +(I1 +(I1 +I1 +I1 +tp26494 +g38 +I00 +S'\xdfu)\xa5\x88Q\xca?' +p26495 +tp26496 +bsg252 +g260 +sg48 +(lp26497 +g0 +(g52 +g2 +Ntp26498 +Rp26499 +(dp26500 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26501 +g179 +tp26502 +Rp26503 +(I1 +(I1 +I1 +I1 +tp26504 +g38 +I00 +S'\xe1&!\x14T\x812@' +p26505 +tp26506 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26507 +g279 +asg113 +I10850 +sg280 +I01 +sbaa(lp26508 +g12 +ag0 +(g190 +g2 +Ntp26509 +Rp26510 +(dp26511 +g194 +I01 +sg195 +(lp26512 +g0 +(g197 +g2 +Ntp26513 +Rp26514 +(dp26515 +g201 +g176 +(g177 +(I0 +tp26516 +g179 +tp26517 +Rp26518 +(I1 +(I1 +tp26519 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26520 +tp26521 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26522 +Rp26523 +(dp26524 +g201 +g176 +(g177 +(I0 +tp26525 +g179 +tp26526 +Rp26527 +(I1 +(I2 +tp26528 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26529 +tp26530 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26531 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26532 +g179 +tp26533 +Rp26534 +(I1 +(I1 +I1 +I1 +tp26535 +g38 +I00 +S'\x96\x0f\x90F\x123\xd7?' +p26536 +tp26537 +bsg238 +g176 +(g177 +(I0 +tp26538 +g179 +tp26539 +Rp26540 +(I1 +(I1 +I1 +I1 +tp26541 +g38 +I00 +S'\xdfz\\\xad\x9c\xfd\x11?' +p26542 +tp26543 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26544 +g179 +tp26545 +Rp26546 +(I1 +(I1 +I1 +I1 +tp26547 +g38 +I00 +S'\xb0a\xecP\xf7>\xb0?' +p26548 +tp26549 +bsg252 +g260 +sg48 +(lp26550 +g0 +(g52 +g2 +Ntp26551 +Rp26552 +(dp26553 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26554 +g179 +tp26555 +Rp26556 +(I1 +(I1 +I1 +I1 +tp26557 +g38 +I00 +S'`i\xcc\xc9\x8b\xd8\x16@' +p26558 +tp26559 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26560 +g334 +asg113 +I10851 +sg280 +I01 +sbaatp26561 +Rp26562 +sg337 +I00 +sg338 +Nsbaa(lp26563 +g340 +ag0 +(g341 +g2 +Ntp26564 +Rp26565 +(dp26566 +g17 +g26432 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26567 +(lp26568 +g189 +ag0 +(g190 +g2 +Ntp26569 +Rp26570 +(dp26571 +g194 +I01 +sg195 +(lp26572 +g0 +(g197 +g2 +Ntp26573 +Rp26574 +(dp26575 +g201 +g176 +(g177 +(I0 +tp26576 +g179 +tp26577 +Rp26578 +(I1 +(I1 +tp26579 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26580 +tp26581 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26582 +Rp26583 +(dp26584 +g201 +g176 +(g177 +(I0 +tp26585 +g179 +tp26586 +Rp26587 +(I1 +(I2 +tp26588 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26589 +tp26590 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26591 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26592 +g179 +tp26593 +Rp26594 +(I1 +(I1 +I1 +I1 +tp26595 +g38 +I00 +S'g\\\x17c.q\x0e@' +p26596 +tp26597 +bsg238 +g176 +(g177 +(I0 +tp26598 +g179 +tp26599 +Rp26600 +(I1 +(I1 +I1 +I1 +tp26601 +g38 +I00 +S'\xd8\x1ew\xcd\x81\x82+?' +p26602 +tp26603 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26604 +g179 +tp26605 +Rp26606 +(I1 +(I1 +I1 +I1 +tp26607 +g38 +I00 +S'\xdfu)\xa5\x88Q\xca?' +p26608 +tp26609 +bsg252 +g260 +sg48 +(lp26610 +g0 +(g52 +g2 +Ntp26611 +Rp26612 +(dp26613 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26614 +g179 +tp26615 +Rp26616 +(I1 +(I1 +I1 +I1 +tp26617 +g38 +I00 +S'\xe1&!\x14T\x812@' +p26618 +tp26619 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26620 +g279 +asg113 +I10854 +sg280 +I01 +sbaa(lp26621 +g401 +ag0 +(g190 +g2 +Ntp26622 +Rp26623 +(dp26624 +g194 +I01 +sg195 +(lp26625 +g0 +(g197 +g2 +Ntp26626 +Rp26627 +(dp26628 +g201 +g176 +(g177 +(I0 +tp26629 +g179 +tp26630 +Rp26631 +(I1 +(I1 +tp26632 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26633 +tp26634 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26635 +Rp26636 +(dp26637 +g201 +g176 +(g177 +(I0 +tp26638 +g179 +tp26639 +Rp26640 +(I1 +(I2 +tp26641 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26642 +tp26643 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26644 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26645 +g179 +tp26646 +Rp26647 +(I1 +(I1 +I1 +I1 +tp26648 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26649 +tp26650 +bsg238 +g176 +(g177 +(I0 +tp26651 +g179 +tp26652 +Rp26653 +(I1 +(I1 +I1 +I1 +tp26654 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26655 +tp26656 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26657 +g179 +tp26658 +Rp26659 +(I1 +(I1 +I1 +I1 +tp26660 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26661 +tp26662 +bsg252 +g260 +sg48 +(lp26663 +g0 +(g52 +g2 +Ntp26664 +Rp26665 +(dp26666 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26667 +g179 +tp26668 +Rp26669 +(I1 +(I1 +I1 +I1 +tp26670 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26671 +tp26672 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp26673 +g454 +asg113 +I10855 +sg280 +I01 +sbaatp26674 +Rp26675 +sg337 +I00 +sg338 +Nsbaa(lp26676 +g458 +ag0 +(g459 +g2 +Ntp26677 +Rp26678 +(dp26679 +g17 +g26432 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26680 +(lp26681 +g189 +ag0 +(g190 +g2 +Ntp26682 +Rp26683 +(dp26684 +g194 +I01 +sg195 +(lp26685 +g0 +(g197 +g2 +Ntp26686 +Rp26687 +(dp26688 +g201 +g176 +(g177 +(I0 +tp26689 +g179 +tp26690 +Rp26691 +(I1 +(I1 +tp26692 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26693 +tp26694 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26695 +Rp26696 +(dp26697 +g201 +g176 +(g177 +(I0 +tp26698 +g179 +tp26699 +Rp26700 +(I1 +(I2 +tp26701 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26702 +tp26703 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp26704 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26705 +g179 +tp26706 +Rp26707 +(I1 +(I1 +I1 +I1 +tp26708 +g38 +I00 +S'z\xe0!:p\xce\x0e@' +p26709 +tp26710 +bsg238 +g176 +(g177 +(I0 +tp26711 +g179 +tp26712 +Rp26713 +(I1 +(I1 +I1 +I1 +tp26714 +g38 +I00 +S'\x1f\xcbXH\xc7\xa2P?' +p26715 +tp26716 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26717 +g179 +tp26718 +Rp26719 +(I1 +(I1 +I1 +I1 +tp26720 +g38 +I00 +S'\xe8\x9d\xb3\xce\xc4r\xca?' +p26721 +tp26722 +bsg252 +g513 +sg48 +(lp26723 +g0 +(g52 +g2 +Ntp26724 +Rp26725 +(dp26726 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp26727 +g179 +tp26728 +Rp26729 +(I1 +(I1 +I1 +I1 +tp26730 +g38 +I00 +S'\x07KVa\xb2\x982@' +p26731 +tp26732 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp26733 +g527 +asg113 +I10858 +sg280 +I01 +sbaa(lp26734 +g529 +ag0 +(g190 +g2 +Ntp26735 +Rp26736 +(dp26737 +g194 +I01 +sg195 +(lp26738 +g0 +(g197 +g2 +Ntp26739 +Rp26740 +(dp26741 +g201 +g176 +(g177 +(I0 +tp26742 +g179 +tp26743 +Rp26744 +(I1 +(I1 +tp26745 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26746 +tp26747 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26748 +Rp26749 +(dp26750 +g201 +g176 +(g177 +(I0 +tp26751 +g179 +tp26752 +Rp26753 +(I1 +(I2 +tp26754 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26755 +tp26756 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26757 +Rp26758 +(dp26759 +g201 +g176 +(g177 +(I0 +tp26760 +g179 +tp26761 +Rp26762 +(I1 +(I2 +tp26763 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26764 +tp26765 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp26766 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26767 +g179 +tp26768 +Rp26769 +(I1 +(I1 +I1 +I1 +tp26770 +g38 +I00 +S'W$\xd3_\xb7!\xd7?' +p26771 +tp26772 +bsg238 +g176 +(g177 +(I0 +tp26773 +g179 +tp26774 +Rp26775 +(I1 +(I1 +I1 +I1 +tp26776 +g38 +I00 +S'\xde\xa9^+\xf5\xd22?' +p26777 +tp26778 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26779 +g179 +tp26780 +Rp26781 +(I1 +(I1 +I1 +I1 +tp26782 +g38 +I00 +S'\x00B\x11xM5\xb0?' +p26783 +tp26784 +bsg252 +g586 +sg48 +(lp26785 +g0 +(g52 +g2 +Ntp26786 +Rp26787 +(dp26788 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp26789 +g179 +tp26790 +Rp26791 +(I1 +(I1 +I1 +I1 +tp26792 +g38 +I00 +S'\xd0D\xd8\xf0\xf4\xca\x16@' +p26793 +tp26794 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp26795 +g600 +asg113 +I10859 +sg280 +I01 +sbaatp26796 +Rp26797 +sg337 +I00 +sg338 +Nsbaa(lp26798 +g604 +ag0 +(g605 +g2 +Ntp26799 +Rp26800 +(dp26801 +g17 +g26432 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26802 +(lp26803 +g611 +ag0 +(g190 +g2 +Ntp26804 +Rp26805 +(dp26806 +g194 +I01 +sg195 +(lp26807 +g0 +(g197 +g2 +Ntp26808 +Rp26809 +(dp26810 +g201 +g176 +(g177 +(I0 +tp26811 +g179 +tp26812 +Rp26813 +(I1 +(I1 +tp26814 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26815 +tp26816 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26817 +Rp26818 +(dp26819 +g201 +g176 +(g177 +(I0 +tp26820 +g179 +tp26821 +Rp26822 +(I1 +(I2 +tp26823 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26824 +tp26825 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp26826 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26827 +g179 +tp26828 +Rp26829 +(I1 +(I1 +I1 +I1 +tp26830 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26831 +tp26832 +bsg238 +g176 +(g177 +(I0 +tp26833 +g179 +tp26834 +Rp26835 +(I1 +(I1 +I1 +I1 +tp26836 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26837 +tp26838 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26839 +g179 +tp26840 +Rp26841 +(I1 +(I1 +I1 +I1 +tp26842 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26843 +tp26844 +bsg252 +g513 +sg48 +(lp26845 +g0 +(g52 +g2 +Ntp26846 +Rp26847 +(dp26848 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp26849 +g179 +tp26850 +Rp26851 +(I1 +(I1 +I1 +I1 +tp26852 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26853 +tp26854 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp26855 +g664 +asg113 +I10862 +sg280 +I01 +sbaa(lp26856 +g666 +ag0 +(g190 +g2 +Ntp26857 +Rp26858 +(dp26859 +g194 +I01 +sg195 +(lp26860 +g0 +(g197 +g2 +Ntp26861 +Rp26862 +(dp26863 +g201 +g176 +(g177 +(I0 +tp26864 +g179 +tp26865 +Rp26866 +(I1 +(I1 +tp26867 +g208 +I00 +S"F'\x00\x00\x00\x00\x00\x00" +p26868 +tp26869 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26870 +Rp26871 +(dp26872 +g201 +g176 +(g177 +(I0 +tp26873 +g179 +tp26874 +Rp26875 +(I1 +(I2 +tp26876 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26877 +tp26878 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp26879 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26880 +g179 +tp26881 +Rp26882 +(I1 +(I1 +I1 +I1 +tp26883 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26884 +tp26885 +bsg238 +g176 +(g177 +(I0 +tp26886 +g179 +tp26887 +Rp26888 +(I1 +(I1 +I1 +I1 +tp26889 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26890 +tp26891 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26892 +g179 +tp26893 +Rp26894 +(I1 +(I1 +I1 +I1 +tp26895 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26896 +tp26897 +bsg252 +g713 +sg48 +(lp26898 +g0 +(g52 +g2 +Ntp26899 +Rp26900 +(dp26901 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp26902 +g179 +tp26903 +Rp26904 +(I1 +(I1 +I1 +I1 +tp26905 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p26906 +tp26907 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp26908 +g727 +asg113 +I10863 +sg280 +I01 +sbaatp26909 +Rp26910 +sg337 +I00 +sg338 +Nsbaatp26911 +Rp26912 +aa(lp26913 +I10055 +ag7 +((lp26914 +(lp26915 +g12 +ag0 +(g13 +g2 +Ntp26916 +Rp26917 +(dp26918 +g17 +g0 +(g18 +g2 +Ntp26919 +Rp26920 +(dp26921 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p26922 +sg116 +g0 +(g117 +g2 +Ntp26923 +Rp26924 +(dp26925 +g121 +(lp26926 +g0 +(g123 +g2 +Ntp26927 +Rp26928 +(dp26929 +g127 +g0 +(g128 +g2 +Ntp26930 +Rp26931 +(dp26932 +g23 +g132 +sg133 +(dp26933 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xf9?' +p26934 +tp26935 +Rp26936 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p26937 +sg113 +I84 +sg146 +(lp26938 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp26939 +Rp26940 +(dp26941 +g127 +g0 +(g128 +g2 +Ntp26942 +Rp26943 +(dp26944 +g23 +g132 +sg133 +(dp26945 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xf8?' +p26946 +tp26947 +Rp26948 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p26949 +sg113 +I85 +sg146 +(lp26950 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10055 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp26951 +(lp26952 +g189 +ag0 +(g190 +g2 +Ntp26953 +Rp26954 +(dp26955 +g194 +I01 +sg195 +(lp26956 +g0 +(g197 +g2 +Ntp26957 +Rp26958 +(dp26959 +g201 +g176 +(g177 +(I0 +tp26960 +g179 +tp26961 +Rp26962 +(I1 +(I1 +tp26963 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p26964 +tp26965 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp26966 +Rp26967 +(dp26968 +g201 +g176 +(g177 +(I0 +tp26969 +g179 +tp26970 +Rp26971 +(I1 +(I2 +tp26972 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p26973 +tp26974 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp26975 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp26976 +g179 +tp26977 +Rp26978 +(I1 +(I1 +I1 +I1 +tp26979 +g38 +I00 +S'"\xfb\xe0\xd2|\x918@' +p26980 +tp26981 +bsg238 +g176 +(g177 +(I0 +tp26982 +g179 +tp26983 +Rp26984 +(I1 +(I1 +I1 +I1 +tp26985 +g38 +I00 +S'Y\x95\x1ax\xa7\xc6@?' +p26986 +tp26987 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp26988 +g179 +tp26989 +Rp26990 +(I1 +(I1 +I1 +I1 +tp26991 +g38 +I00 +S'\xe9\xc7\x07\xe5\xf0\xb7\xe0?' +p26992 +tp26993 +bsg252 +g260 +sg48 +(lp26994 +g0 +(g52 +g2 +Ntp26995 +Rp26996 +(dp26997 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp26998 +g179 +tp26999 +Rp27000 +(I1 +(I1 +I1 +I1 +tp27001 +g38 +I00 +S'\x1f\xf1\x12\xc2\xaa\x82G@' +p27002 +tp27003 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27004 +g279 +asg113 +I10866 +sg280 +I01 +sbaa(lp27005 +g12 +ag0 +(g190 +g2 +Ntp27006 +Rp27007 +(dp27008 +g194 +I01 +sg195 +(lp27009 +g0 +(g197 +g2 +Ntp27010 +Rp27011 +(dp27012 +g201 +g176 +(g177 +(I0 +tp27013 +g179 +tp27014 +Rp27015 +(I1 +(I1 +tp27016 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27017 +tp27018 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27019 +Rp27020 +(dp27021 +g201 +g176 +(g177 +(I0 +tp27022 +g179 +tp27023 +Rp27024 +(I1 +(I2 +tp27025 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27026 +tp27027 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27028 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27029 +g179 +tp27030 +Rp27031 +(I1 +(I1 +I1 +I1 +tp27032 +g38 +I00 +S'\xb9b\xbdt8\xf2\x10@' +p27033 +tp27034 +bsg238 +g176 +(g177 +(I0 +tp27035 +g179 +tp27036 +Rp27037 +(I1 +(I1 +I1 +I1 +tp27038 +g38 +I00 +S"\t\xacG\xb3'\xe0-?" +p27039 +tp27040 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27041 +g179 +tp27042 +Rp27043 +(I1 +(I1 +I1 +I1 +tp27044 +g38 +I00 +S'\xf5\xe4;\x91\x13\xc5\xcb?' +p27045 +tp27046 +bsg252 +g260 +sg48 +(lp27047 +g0 +(g52 +g2 +Ntp27048 +Rp27049 +(dp27050 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27051 +g179 +tp27052 +Rp27053 +(I1 +(I1 +I1 +I1 +tp27054 +g38 +I00 +S'\xfc\x1c\x1e\xc2\x91\x863@' +p27055 +tp27056 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27057 +g334 +asg113 +I10867 +sg280 +I01 +sbaatp27058 +Rp27059 +sg337 +I00 +sg338 +Nsbaa(lp27060 +g340 +ag0 +(g341 +g2 +Ntp27061 +Rp27062 +(dp27063 +g17 +g26920 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27064 +(lp27065 +g189 +ag0 +(g190 +g2 +Ntp27066 +Rp27067 +(dp27068 +g194 +I01 +sg195 +(lp27069 +g0 +(g197 +g2 +Ntp27070 +Rp27071 +(dp27072 +g201 +g176 +(g177 +(I0 +tp27073 +g179 +tp27074 +Rp27075 +(I1 +(I1 +tp27076 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27077 +tp27078 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27079 +Rp27080 +(dp27081 +g201 +g176 +(g177 +(I0 +tp27082 +g179 +tp27083 +Rp27084 +(I1 +(I2 +tp27085 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27086 +tp27087 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27088 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27089 +g179 +tp27090 +Rp27091 +(I1 +(I1 +I1 +I1 +tp27092 +g38 +I00 +S'"\xfb\xe0\xd2|\x918@' +p27093 +tp27094 +bsg238 +g176 +(g177 +(I0 +tp27095 +g179 +tp27096 +Rp27097 +(I1 +(I1 +I1 +I1 +tp27098 +g38 +I00 +S'Y\x95\x1ax\xa7\xc6@?' +p27099 +tp27100 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27101 +g179 +tp27102 +Rp27103 +(I1 +(I1 +I1 +I1 +tp27104 +g38 +I00 +S'\xe9\xc7\x07\xe5\xf0\xb7\xe0?' +p27105 +tp27106 +bsg252 +g260 +sg48 +(lp27107 +g0 +(g52 +g2 +Ntp27108 +Rp27109 +(dp27110 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27111 +g179 +tp27112 +Rp27113 +(I1 +(I1 +I1 +I1 +tp27114 +g38 +I00 +S'\x1f\xf1\x12\xc2\xaa\x82G@' +p27115 +tp27116 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27117 +g279 +asg113 +I10870 +sg280 +I01 +sbaa(lp27118 +g401 +ag0 +(g190 +g2 +Ntp27119 +Rp27120 +(dp27121 +g194 +I01 +sg195 +(lp27122 +g0 +(g197 +g2 +Ntp27123 +Rp27124 +(dp27125 +g201 +g176 +(g177 +(I0 +tp27126 +g179 +tp27127 +Rp27128 +(I1 +(I1 +tp27129 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27130 +tp27131 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27132 +Rp27133 +(dp27134 +g201 +g176 +(g177 +(I0 +tp27135 +g179 +tp27136 +Rp27137 +(I1 +(I2 +tp27138 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27139 +tp27140 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27141 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27142 +g179 +tp27143 +Rp27144 +(I1 +(I1 +I1 +I1 +tp27145 +g38 +I00 +S'\xd5V\x02p\x04x\xb3?' +p27146 +tp27147 +bsg238 +g176 +(g177 +(I0 +tp27148 +g179 +tp27149 +Rp27150 +(I1 +(I1 +I1 +I1 +tp27151 +g38 +I00 +S'Z\x14\xee4"\x19\x10?' +p27152 +tp27153 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27154 +g179 +tp27155 +Rp27156 +(I1 +(I1 +I1 +I1 +tp27157 +g38 +I00 +S'0\x84\x8a0\xb9\xc2\x9d?' +p27158 +tp27159 +bsg252 +g260 +sg48 +(lp27160 +g0 +(g52 +g2 +Ntp27161 +Rp27162 +(dp27163 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27164 +g179 +tp27165 +Rp27166 +(I1 +(I1 +I1 +I1 +tp27167 +g38 +I00 +S'\xf2d!6\xea\xec\x04@' +p27168 +tp27169 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27170 +g454 +asg113 +I10871 +sg280 +I01 +sbaatp27171 +Rp27172 +sg337 +I00 +sg338 +Nsbaa(lp27173 +g458 +ag0 +(g459 +g2 +Ntp27174 +Rp27175 +(dp27176 +g17 +g26920 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27177 +(lp27178 +g189 +ag0 +(g190 +g2 +Ntp27179 +Rp27180 +(dp27181 +g194 +I01 +sg195 +(lp27182 +g0 +(g197 +g2 +Ntp27183 +Rp27184 +(dp27185 +g201 +g176 +(g177 +(I0 +tp27186 +g179 +tp27187 +Rp27188 +(I1 +(I1 +tp27189 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27190 +tp27191 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27192 +Rp27193 +(dp27194 +g201 +g176 +(g177 +(I0 +tp27195 +g179 +tp27196 +Rp27197 +(I1 +(I2 +tp27198 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27199 +tp27200 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp27201 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27202 +g179 +tp27203 +Rp27204 +(I1 +(I1 +I1 +I1 +tp27205 +g38 +I00 +S'\x90\xd7v\xa0\x91\x7f8@' +p27206 +tp27207 +bsg238 +g176 +(g177 +(I0 +tp27208 +g179 +tp27209 +Rp27210 +(I1 +(I1 +I1 +I1 +tp27211 +g38 +I00 +S')s\xb6\xb7\xd8>U?' +p27212 +tp27213 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27214 +g179 +tp27215 +Rp27216 +(I1 +(I1 +I1 +I1 +tp27217 +g38 +I00 +S'\xa0Q\x1b\xf2\xd8\xb0\xe0?' +p27218 +tp27219 +bsg252 +g513 +sg48 +(lp27220 +g0 +(g52 +g2 +Ntp27221 +Rp27222 +(dp27223 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp27224 +g179 +tp27225 +Rp27226 +(I1 +(I1 +I1 +I1 +tp27227 +g38 +I00 +S'\xc9jv\x14\xb1xG@' +p27228 +tp27229 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp27230 +g527 +asg113 +I10874 +sg280 +I01 +sbaa(lp27231 +g529 +ag0 +(g190 +g2 +Ntp27232 +Rp27233 +(dp27234 +g194 +I01 +sg195 +(lp27235 +g0 +(g197 +g2 +Ntp27236 +Rp27237 +(dp27238 +g201 +g176 +(g177 +(I0 +tp27239 +g179 +tp27240 +Rp27241 +(I1 +(I1 +tp27242 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27243 +tp27244 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27245 +Rp27246 +(dp27247 +g201 +g176 +(g177 +(I0 +tp27248 +g179 +tp27249 +Rp27250 +(I1 +(I2 +tp27251 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27252 +tp27253 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27254 +Rp27255 +(dp27256 +g201 +g176 +(g177 +(I0 +tp27257 +g179 +tp27258 +Rp27259 +(I1 +(I2 +tp27260 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27261 +tp27262 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp27263 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27264 +g179 +tp27265 +Rp27266 +(I1 +(I1 +I1 +I1 +tp27267 +g38 +I00 +S'\xb6\xdfE%\x96\xe8\x0b@' +p27268 +tp27269 +bsg238 +g176 +(g177 +(I0 +tp27270 +g179 +tp27271 +Rp27272 +(I1 +(I1 +I1 +I1 +tp27273 +g38 +I00 +S'k]\x1c\x96\x06\xec>?' +p27274 +tp27275 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27276 +g179 +tp27277 +Rp27278 +(I1 +(I1 +I1 +I1 +tp27279 +g38 +I00 +S'5\x93o\xb6\xb91\xc9?' +p27280 +tp27281 +bsg252 +g586 +sg48 +(lp27282 +g0 +(g52 +g2 +Ntp27283 +Rp27284 +(dp27285 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp27286 +g179 +tp27287 +Rp27288 +(I1 +(I1 +I1 +I1 +tp27289 +g38 +I00 +S'\x81sF\x94\xf6\xb61@' +p27290 +tp27291 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp27292 +g600 +asg113 +I10875 +sg280 +I01 +sbaatp27293 +Rp27294 +sg337 +I00 +sg338 +Nsbaa(lp27295 +g604 +ag0 +(g605 +g2 +Ntp27296 +Rp27297 +(dp27298 +g17 +g26920 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27299 +(lp27300 +g611 +ag0 +(g190 +g2 +Ntp27301 +Rp27302 +(dp27303 +g194 +I01 +sg195 +(lp27304 +g0 +(g197 +g2 +Ntp27305 +Rp27306 +(dp27307 +g201 +g176 +(g177 +(I0 +tp27308 +g179 +tp27309 +Rp27310 +(I1 +(I1 +tp27311 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27312 +tp27313 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27314 +Rp27315 +(dp27316 +g201 +g176 +(g177 +(I0 +tp27317 +g179 +tp27318 +Rp27319 +(I1 +(I2 +tp27320 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27321 +tp27322 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp27323 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27324 +g179 +tp27325 +Rp27326 +(I1 +(I1 +I1 +I1 +tp27327 +g38 +I00 +S'\xa1\x9a~k|D\xb3?' +p27328 +tp27329 +bsg238 +g176 +(g177 +(I0 +tp27330 +g179 +tp27331 +Rp27332 +(I1 +(I1 +I1 +I1 +tp27333 +g38 +I00 +S'\xa5t\xa2\xf93Y,?' +p27334 +tp27335 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27336 +g179 +tp27337 +Rp27338 +(I1 +(I1 +I1 +I1 +tp27339 +g38 +I00 +S'y\xe9g\xe3\xd8\x89\x9d?' +p27340 +tp27341 +bsg252 +g513 +sg48 +(lp27342 +g0 +(g52 +g2 +Ntp27343 +Rp27344 +(dp27345 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp27346 +g179 +tp27347 +Rp27348 +(I1 +(I1 +I1 +I1 +tp27349 +g38 +I00 +S')\x10\xe5\x7f\xec\xc4\x04@' +p27350 +tp27351 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp27352 +g664 +asg113 +I10878 +sg280 +I01 +sbaa(lp27353 +g666 +ag0 +(g190 +g2 +Ntp27354 +Rp27355 +(dp27356 +g194 +I01 +sg195 +(lp27357 +g0 +(g197 +g2 +Ntp27358 +Rp27359 +(dp27360 +g201 +g176 +(g177 +(I0 +tp27361 +g179 +tp27362 +Rp27363 +(I1 +(I1 +tp27364 +g208 +I00 +S"G'\x00\x00\x00\x00\x00\x00" +p27365 +tp27366 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27367 +Rp27368 +(dp27369 +g201 +g176 +(g177 +(I0 +tp27370 +g179 +tp27371 +Rp27372 +(I1 +(I2 +tp27373 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27374 +tp27375 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp27376 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27377 +g179 +tp27378 +Rp27379 +(I1 +(I1 +I1 +I1 +tp27380 +g38 +I00 +S'\x9f\x9a~k|D\xb3?' +p27381 +tp27382 +bsg238 +g176 +(g177 +(I0 +tp27383 +g179 +tp27384 +Rp27385 +(I1 +(I1 +I1 +I1 +tp27386 +g38 +I00 +S'eq\xa2\xf93Y,?' +p27387 +tp27388 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27389 +g179 +tp27390 +Rp27391 +(I1 +(I1 +I1 +I1 +tp27392 +g38 +I00 +S'|\xe9g\xe3\xd8\x89\x9d?' +p27393 +tp27394 +bsg252 +g713 +sg48 +(lp27395 +g0 +(g52 +g2 +Ntp27396 +Rp27397 +(dp27398 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp27399 +g179 +tp27400 +Rp27401 +(I1 +(I1 +I1 +I1 +tp27402 +g38 +I00 +S'+\x10\xe5\x7f\xec\xc4\x04@' +p27403 +tp27404 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp27405 +g727 +asg113 +I10879 +sg280 +I01 +sbaatp27406 +Rp27407 +sg337 +I00 +sg338 +Nsbaatp27408 +Rp27409 +aa(lp27410 +I10056 +ag7 +((lp27411 +(lp27412 +g12 +ag0 +(g13 +g2 +Ntp27413 +Rp27414 +(dp27415 +g17 +g0 +(g18 +g2 +Ntp27416 +Rp27417 +(dp27418 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p27419 +sg116 +g0 +(g117 +g2 +Ntp27420 +Rp27421 +(dp27422 +g121 +(lp27423 +g0 +(g123 +g2 +Ntp27424 +Rp27425 +(dp27426 +g127 +g1857 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp27427 +Rp27428 +(dp27429 +g127 +g4330 +sg148 +g149 +sbasbsg163 +Nsg113 +I10056 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27430 +(lp27431 +g189 +ag0 +(g190 +g2 +Ntp27432 +Rp27433 +(dp27434 +g194 +I01 +sg195 +(lp27435 +g0 +(g197 +g2 +Ntp27436 +Rp27437 +(dp27438 +g201 +g176 +(g177 +(I0 +tp27439 +g179 +tp27440 +Rp27441 +(I1 +(I1 +tp27442 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27443 +tp27444 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27445 +Rp27446 +(dp27447 +g201 +g176 +(g177 +(I0 +tp27448 +g179 +tp27449 +Rp27450 +(I1 +(I2 +tp27451 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27452 +tp27453 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27454 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27455 +g179 +tp27456 +Rp27457 +(I1 +(I1 +I1 +I1 +tp27458 +g38 +I00 +S'\xcf\x17\xac\xdc\x18^I@' +p27459 +tp27460 +bsg238 +g176 +(g177 +(I0 +tp27461 +g179 +tp27462 +Rp27463 +(I1 +(I1 +I1 +I1 +tp27464 +g38 +I00 +S'b\xd7n@L\x0bJ?' +p27465 +tp27466 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27467 +g179 +tp27468 +Rp27469 +(I1 +(I1 +I1 +I1 +tp27470 +g38 +I00 +S'\xcb\xca\xc8j_\x06\xe8?' +p27471 +tp27472 +bsg252 +g260 +sg48 +(lp27473 +g0 +(g52 +g2 +Ntp27474 +Rp27475 +(dp27476 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27477 +g179 +tp27478 +Rp27479 +(I1 +(I1 +I1 +I1 +tp27480 +g38 +I00 +S'\x97.\x15\x17{\xe4P@' +p27481 +tp27482 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27483 +g279 +asg113 +I10882 +sg280 +I01 +sbaa(lp27484 +g12 +ag0 +(g190 +g2 +Ntp27485 +Rp27486 +(dp27487 +g194 +I01 +sg195 +(lp27488 +g0 +(g197 +g2 +Ntp27489 +Rp27490 +(dp27491 +g201 +g176 +(g177 +(I0 +tp27492 +g179 +tp27493 +Rp27494 +(I1 +(I1 +tp27495 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27496 +tp27497 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27498 +Rp27499 +(dp27500 +g201 +g176 +(g177 +(I0 +tp27501 +g179 +tp27502 +Rp27503 +(I1 +(I2 +tp27504 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27505 +tp27506 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27507 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27508 +g179 +tp27509 +Rp27510 +(I1 +(I1 +I1 +I1 +tp27511 +g38 +I00 +S'\x85~E\x80\x1b{N@' +p27512 +tp27513 +bsg238 +g176 +(g177 +(I0 +tp27514 +g179 +tp27515 +Rp27516 +(I1 +(I1 +I1 +I1 +tp27517 +g38 +I00 +S'P\x11\t\xeb\xeenT?' +p27518 +tp27519 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27520 +g179 +tp27521 +Rp27522 +(I1 +(I1 +I1 +I1 +tp27523 +g38 +I00 +S'\x84\xeafdrU\xea?' +p27524 +tp27525 +bsg252 +g260 +sg48 +(lp27526 +g0 +(g52 +g2 +Ntp27527 +Rp27528 +(dp27529 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27530 +g179 +tp27531 +Rp27532 +(I1 +(I1 +I1 +I1 +tp27533 +g38 +I00 +S'\xe5\\\x98n\x14\x84R@' +p27534 +tp27535 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27536 +g334 +asg113 +I10883 +sg280 +I01 +sbaatp27537 +Rp27538 +sg337 +I00 +sg338 +Nsbaa(lp27539 +g340 +ag0 +(g341 +g2 +Ntp27540 +Rp27541 +(dp27542 +g17 +g27417 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27543 +(lp27544 +g189 +ag0 +(g190 +g2 +Ntp27545 +Rp27546 +(dp27547 +g194 +I01 +sg195 +(lp27548 +g0 +(g197 +g2 +Ntp27549 +Rp27550 +(dp27551 +g201 +g176 +(g177 +(I0 +tp27552 +g179 +tp27553 +Rp27554 +(I1 +(I1 +tp27555 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27556 +tp27557 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27558 +Rp27559 +(dp27560 +g201 +g176 +(g177 +(I0 +tp27561 +g179 +tp27562 +Rp27563 +(I1 +(I2 +tp27564 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27565 +tp27566 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27567 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27568 +g179 +tp27569 +Rp27570 +(I1 +(I1 +I1 +I1 +tp27571 +g38 +I00 +S'\xcf\x17\xac\xdc\x18^I@' +p27572 +tp27573 +bsg238 +g176 +(g177 +(I0 +tp27574 +g179 +tp27575 +Rp27576 +(I1 +(I1 +I1 +I1 +tp27577 +g38 +I00 +S'b\xd7n@L\x0bJ?' +p27578 +tp27579 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27580 +g179 +tp27581 +Rp27582 +(I1 +(I1 +I1 +I1 +tp27583 +g38 +I00 +S'\xcb\xca\xc8j_\x06\xe8?' +p27584 +tp27585 +bsg252 +g260 +sg48 +(lp27586 +g0 +(g52 +g2 +Ntp27587 +Rp27588 +(dp27589 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27590 +g179 +tp27591 +Rp27592 +(I1 +(I1 +I1 +I1 +tp27593 +g38 +I00 +S'\x97.\x15\x17{\xe4P@' +p27594 +tp27595 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27596 +g279 +asg113 +I10886 +sg280 +I01 +sbaa(lp27597 +g401 +ag0 +(g190 +g2 +Ntp27598 +Rp27599 +(dp27600 +g194 +I01 +sg195 +(lp27601 +g0 +(g197 +g2 +Ntp27602 +Rp27603 +(dp27604 +g201 +g176 +(g177 +(I0 +tp27605 +g179 +tp27606 +Rp27607 +(I1 +(I1 +tp27608 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27609 +tp27610 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27611 +Rp27612 +(dp27613 +g201 +g176 +(g177 +(I0 +tp27614 +g179 +tp27615 +Rp27616 +(I1 +(I2 +tp27617 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27618 +tp27619 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27620 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27621 +g179 +tp27622 +Rp27623 +(I1 +(I1 +I1 +I1 +tp27624 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27625 +tp27626 +bsg238 +g176 +(g177 +(I0 +tp27627 +g179 +tp27628 +Rp27629 +(I1 +(I1 +I1 +I1 +tp27630 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27631 +tp27632 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27633 +g179 +tp27634 +Rp27635 +(I1 +(I1 +I1 +I1 +tp27636 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27637 +tp27638 +bsg252 +g260 +sg48 +(lp27639 +g0 +(g52 +g2 +Ntp27640 +Rp27641 +(dp27642 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27643 +g179 +tp27644 +Rp27645 +(I1 +(I1 +I1 +I1 +tp27646 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27647 +tp27648 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27649 +g454 +asg113 +I10887 +sg280 +I01 +sbaatp27650 +Rp27651 +sg337 +I00 +sg338 +Nsbaa(lp27652 +g458 +ag0 +(g459 +g2 +Ntp27653 +Rp27654 +(dp27655 +g17 +g27417 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27656 +(lp27657 +g189 +ag0 +(g190 +g2 +Ntp27658 +Rp27659 +(dp27660 +g194 +I01 +sg195 +(lp27661 +g0 +(g197 +g2 +Ntp27662 +Rp27663 +(dp27664 +g201 +g176 +(g177 +(I0 +tp27665 +g179 +tp27666 +Rp27667 +(I1 +(I1 +tp27668 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27669 +tp27670 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27671 +Rp27672 +(dp27673 +g201 +g176 +(g177 +(I0 +tp27674 +g179 +tp27675 +Rp27676 +(I1 +(I2 +tp27677 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27678 +tp27679 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp27680 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27681 +g179 +tp27682 +Rp27683 +(I1 +(I1 +I1 +I1 +tp27684 +g38 +I00 +S'\x11\xd0\x89\xa7\xc3ZI@' +p27685 +tp27686 +bsg238 +g176 +(g177 +(I0 +tp27687 +g179 +tp27688 +Rp27689 +(I1 +(I1 +I1 +I1 +tp27690 +g38 +I00 +S'\xde\xbb\xd0`\xc3~W?' +p27691 +tp27692 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27693 +g179 +tp27694 +Rp27695 +(I1 +(I1 +I1 +I1 +tp27696 +g38 +I00 +S'\xb2\xed\xea%\x1a\x04\xe8?' +p27697 +tp27698 +bsg252 +g513 +sg48 +(lp27699 +g0 +(g52 +g2 +Ntp27700 +Rp27701 +(dp27702 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp27703 +g179 +tp27704 +Rp27705 +(I1 +(I1 +I1 +I1 +tp27706 +g38 +I00 +S'!/\xa9b\xe2\xe2P@' +p27707 +tp27708 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp27709 +g527 +asg113 +I10890 +sg280 +I01 +sbaa(lp27710 +g529 +ag0 +(g190 +g2 +Ntp27711 +Rp27712 +(dp27713 +g194 +I01 +sg195 +(lp27714 +g0 +(g197 +g2 +Ntp27715 +Rp27716 +(dp27717 +g201 +g176 +(g177 +(I0 +tp27718 +g179 +tp27719 +Rp27720 +(I1 +(I1 +tp27721 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27722 +tp27723 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27724 +Rp27725 +(dp27726 +g201 +g176 +(g177 +(I0 +tp27727 +g179 +tp27728 +Rp27729 +(I1 +(I2 +tp27730 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27731 +tp27732 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27733 +Rp27734 +(dp27735 +g201 +g176 +(g177 +(I0 +tp27736 +g179 +tp27737 +Rp27738 +(I1 +(I2 +tp27739 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27740 +tp27741 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp27742 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27743 +g179 +tp27744 +Rp27745 +(I1 +(I1 +I1 +I1 +tp27746 +g38 +I00 +S'$\x9a(\xbe\xb1\xd0M@' +p27747 +tp27748 +bsg238 +g176 +(g177 +(I0 +tp27749 +g179 +tp27750 +Rp27751 +(I1 +(I1 +I1 +I1 +tp27752 +g38 +I00 +S'2\x13\x82\x8f\xc5\xacV?' +p27753 +tp27754 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27755 +g179 +tp27756 +Rp27757 +(I1 +(I1 +I1 +I1 +tp27758 +g38 +I00 +S'\xff\x19\xb8\x16@\x0b\xea?' +p27759 +tp27760 +bsg252 +g586 +sg48 +(lp27761 +g0 +(g52 +g2 +Ntp27762 +Rp27763 +(dp27764 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp27765 +g179 +tp27766 +Rp27767 +(I1 +(I1 +I1 +I1 +tp27768 +g38 +I00 +S'Gr\xf9\x0f\xe9OR@' +p27769 +tp27770 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp27771 +g600 +asg113 +I10891 +sg280 +I01 +sbaatp27772 +Rp27773 +sg337 +I00 +sg338 +Nsbaa(lp27774 +g604 +ag0 +(g605 +g2 +Ntp27775 +Rp27776 +(dp27777 +g17 +g27417 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27778 +(lp27779 +g611 +ag0 +(g190 +g2 +Ntp27780 +Rp27781 +(dp27782 +g194 +I01 +sg195 +(lp27783 +g0 +(g197 +g2 +Ntp27784 +Rp27785 +(dp27786 +g201 +g176 +(g177 +(I0 +tp27787 +g179 +tp27788 +Rp27789 +(I1 +(I1 +tp27790 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27791 +tp27792 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27793 +Rp27794 +(dp27795 +g201 +g176 +(g177 +(I0 +tp27796 +g179 +tp27797 +Rp27798 +(I1 +(I2 +tp27799 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27800 +tp27801 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp27802 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27803 +g179 +tp27804 +Rp27805 +(I1 +(I1 +I1 +I1 +tp27806 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27807 +tp27808 +bsg238 +g176 +(g177 +(I0 +tp27809 +g179 +tp27810 +Rp27811 +(I1 +(I1 +I1 +I1 +tp27812 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27813 +tp27814 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27815 +g179 +tp27816 +Rp27817 +(I1 +(I1 +I1 +I1 +tp27818 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27819 +tp27820 +bsg252 +g513 +sg48 +(lp27821 +g0 +(g52 +g2 +Ntp27822 +Rp27823 +(dp27824 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp27825 +g179 +tp27826 +Rp27827 +(I1 +(I1 +I1 +I1 +tp27828 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27829 +tp27830 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp27831 +g664 +asg113 +I10894 +sg280 +I01 +sbaa(lp27832 +g666 +ag0 +(g190 +g2 +Ntp27833 +Rp27834 +(dp27835 +g194 +I01 +sg195 +(lp27836 +g0 +(g197 +g2 +Ntp27837 +Rp27838 +(dp27839 +g201 +g176 +(g177 +(I0 +tp27840 +g179 +tp27841 +Rp27842 +(I1 +(I1 +tp27843 +g208 +I00 +S"H'\x00\x00\x00\x00\x00\x00" +p27844 +tp27845 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27846 +Rp27847 +(dp27848 +g201 +g176 +(g177 +(I0 +tp27849 +g179 +tp27850 +Rp27851 +(I1 +(I2 +tp27852 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27853 +tp27854 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp27855 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27856 +g179 +tp27857 +Rp27858 +(I1 +(I1 +I1 +I1 +tp27859 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27860 +tp27861 +bsg238 +g176 +(g177 +(I0 +tp27862 +g179 +tp27863 +Rp27864 +(I1 +(I1 +I1 +I1 +tp27865 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27866 +tp27867 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27868 +g179 +tp27869 +Rp27870 +(I1 +(I1 +I1 +I1 +tp27871 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27872 +tp27873 +bsg252 +g713 +sg48 +(lp27874 +g0 +(g52 +g2 +Ntp27875 +Rp27876 +(dp27877 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp27878 +g179 +tp27879 +Rp27880 +(I1 +(I1 +I1 +I1 +tp27881 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p27882 +tp27883 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp27884 +g727 +asg113 +I10895 +sg280 +I01 +sbaatp27885 +Rp27886 +sg337 +I00 +sg338 +Nsbaatp27887 +Rp27888 +aa(lp27889 +I10057 +ag7 +((lp27890 +(lp27891 +g12 +ag0 +(g13 +g2 +Ntp27892 +Rp27893 +(dp27894 +g17 +g0 +(g18 +g2 +Ntp27895 +Rp27896 +(dp27897 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p27898 +sg116 +g0 +(g117 +g2 +Ntp27899 +Rp27900 +(dp27901 +g121 +(lp27902 +g0 +(g123 +g2 +Ntp27903 +Rp27904 +(dp27905 +g127 +g19123 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp27906 +Rp27907 +(dp27908 +g127 +g0 +(g128 +g2 +Ntp27909 +Rp27910 +(dp27911 +g23 +g132 +sg133 +(dp27912 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'333333\xeb?' +p27913 +tp27914 +Rp27915 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p27916 +sg113 +I86 +sg146 +(lp27917 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10057 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp27918 +(lp27919 +g189 +ag0 +(g190 +g2 +Ntp27920 +Rp27921 +(dp27922 +g194 +I01 +sg195 +(lp27923 +g0 +(g197 +g2 +Ntp27924 +Rp27925 +(dp27926 +g201 +g176 +(g177 +(I0 +tp27927 +g179 +tp27928 +Rp27929 +(I1 +(I1 +tp27930 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p27931 +tp27932 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27933 +Rp27934 +(dp27935 +g201 +g176 +(g177 +(I0 +tp27936 +g179 +tp27937 +Rp27938 +(I1 +(I2 +tp27939 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27940 +tp27941 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27942 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27943 +g179 +tp27944 +Rp27945 +(I1 +(I1 +I1 +I1 +tp27946 +g38 +I00 +S"j\xb8v'Zs8@" +p27947 +tp27948 +bsg238 +g176 +(g177 +(I0 +tp27949 +g179 +tp27950 +Rp27951 +(I1 +(I1 +I1 +I1 +tp27952 +g38 +I00 +S'\xd8\xb3\xcd67xA?' +p27953 +tp27954 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp27955 +g179 +tp27956 +Rp27957 +(I1 +(I1 +I1 +I1 +tp27958 +g38 +I00 +S'k}\xb6\xac\xa8\xad\xe0?' +p27959 +tp27960 +bsg252 +g260 +sg48 +(lp27961 +g0 +(g52 +g2 +Ntp27962 +Rp27963 +(dp27964 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp27965 +g179 +tp27966 +Rp27967 +(I1 +(I1 +I1 +I1 +tp27968 +g38 +I00 +S'^\xa0\xe025tG@' +p27969 +tp27970 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp27971 +g279 +asg113 +I10898 +sg280 +I01 +sbaa(lp27972 +g12 +ag0 +(g190 +g2 +Ntp27973 +Rp27974 +(dp27975 +g194 +I01 +sg195 +(lp27976 +g0 +(g197 +g2 +Ntp27977 +Rp27978 +(dp27979 +g201 +g176 +(g177 +(I0 +tp27980 +g179 +tp27981 +Rp27982 +(I1 +(I1 +tp27983 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p27984 +tp27985 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp27986 +Rp27987 +(dp27988 +g201 +g176 +(g177 +(I0 +tp27989 +g179 +tp27990 +Rp27991 +(I1 +(I2 +tp27992 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p27993 +tp27994 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp27995 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp27996 +g179 +tp27997 +Rp27998 +(I1 +(I1 +I1 +I1 +tp27999 +g38 +I00 +S'#\xb6\x9f\x8fr\xaf\x0f@' +p28000 +tp28001 +bsg238 +g176 +(g177 +(I0 +tp28002 +g179 +tp28003 +Rp28004 +(I1 +(I1 +I1 +I1 +tp28005 +g38 +I00 +S'\xb2`\xb4\xa3\xa9\xbf.?' +p28006 +tp28007 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28008 +g179 +tp28009 +Rp28010 +(I1 +(I1 +I1 +I1 +tp28011 +g38 +I00 +S'\xd2el\xab\xab\xd9\xca?' +p28012 +tp28013 +bsg252 +g260 +sg48 +(lp28014 +g0 +(g52 +g2 +Ntp28015 +Rp28016 +(dp28017 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28018 +g179 +tp28019 +Rp28020 +(I1 +(I1 +I1 +I1 +tp28021 +g38 +I00 +S'\x987\x88\xb4\x0c\xe12@' +p28022 +tp28023 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28024 +g334 +asg113 +I10899 +sg280 +I01 +sbaatp28025 +Rp28026 +sg337 +I00 +sg338 +Nsbaa(lp28027 +g340 +ag0 +(g341 +g2 +Ntp28028 +Rp28029 +(dp28030 +g17 +g27896 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28031 +(lp28032 +g189 +ag0 +(g190 +g2 +Ntp28033 +Rp28034 +(dp28035 +g194 +I01 +sg195 +(lp28036 +g0 +(g197 +g2 +Ntp28037 +Rp28038 +(dp28039 +g201 +g176 +(g177 +(I0 +tp28040 +g179 +tp28041 +Rp28042 +(I1 +(I1 +tp28043 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28044 +tp28045 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28046 +Rp28047 +(dp28048 +g201 +g176 +(g177 +(I0 +tp28049 +g179 +tp28050 +Rp28051 +(I1 +(I2 +tp28052 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28053 +tp28054 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28055 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28056 +g179 +tp28057 +Rp28058 +(I1 +(I1 +I1 +I1 +tp28059 +g38 +I00 +S"j\xb8v'Zs8@" +p28060 +tp28061 +bsg238 +g176 +(g177 +(I0 +tp28062 +g179 +tp28063 +Rp28064 +(I1 +(I1 +I1 +I1 +tp28065 +g38 +I00 +S'\xd8\xb3\xcd67xA?' +p28066 +tp28067 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28068 +g179 +tp28069 +Rp28070 +(I1 +(I1 +I1 +I1 +tp28071 +g38 +I00 +S'k}\xb6\xac\xa8\xad\xe0?' +p28072 +tp28073 +bsg252 +g260 +sg48 +(lp28074 +g0 +(g52 +g2 +Ntp28075 +Rp28076 +(dp28077 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28078 +g179 +tp28079 +Rp28080 +(I1 +(I1 +I1 +I1 +tp28081 +g38 +I00 +S'^\xa0\xe025tG@' +p28082 +tp28083 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28084 +g279 +asg113 +I10902 +sg280 +I01 +sbaa(lp28085 +g401 +ag0 +(g190 +g2 +Ntp28086 +Rp28087 +(dp28088 +g194 +I01 +sg195 +(lp28089 +g0 +(g197 +g2 +Ntp28090 +Rp28091 +(dp28092 +g201 +g176 +(g177 +(I0 +tp28093 +g179 +tp28094 +Rp28095 +(I1 +(I1 +tp28096 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28097 +tp28098 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28099 +Rp28100 +(dp28101 +g201 +g176 +(g177 +(I0 +tp28102 +g179 +tp28103 +Rp28104 +(I1 +(I2 +tp28105 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28106 +tp28107 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28108 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28109 +g179 +tp28110 +Rp28111 +(I1 +(I1 +I1 +I1 +tp28112 +g38 +I00 +S'\x19\x1a\xab\xcbc\x0e\xa4?' +p28113 +tp28114 +bsg238 +g176 +(g177 +(I0 +tp28115 +g179 +tp28116 +Rp28117 +(I1 +(I1 +I1 +I1 +tp28118 +g38 +I00 +S'\x90k]\x85\xbf\xc0\t?' +p28119 +tp28120 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28121 +g179 +tp28122 +Rp28123 +(I1 +(I1 +I1 +I1 +tp28124 +g38 +I00 +S'\x98F\xa3;\xa7[\x95?' +p28125 +tp28126 +bsg252 +g260 +sg48 +(lp28127 +g0 +(g52 +g2 +Ntp28128 +Rp28129 +(dp28130 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28131 +g179 +tp28132 +Rp28133 +(I1 +(I1 +I1 +I1 +tp28134 +g38 +I00 +S'F\x9b\xdd+\xe3\x08\xfe?' +p28135 +tp28136 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28137 +g454 +asg113 +I10903 +sg280 +I01 +sbaatp28138 +Rp28139 +sg337 +I00 +sg338 +Nsbaa(lp28140 +g458 +ag0 +(g459 +g2 +Ntp28141 +Rp28142 +(dp28143 +g17 +g27896 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28144 +(lp28145 +g189 +ag0 +(g190 +g2 +Ntp28146 +Rp28147 +(dp28148 +g194 +I01 +sg195 +(lp28149 +g0 +(g197 +g2 +Ntp28150 +Rp28151 +(dp28152 +g201 +g176 +(g177 +(I0 +tp28153 +g179 +tp28154 +Rp28155 +(I1 +(I1 +tp28156 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28157 +tp28158 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28159 +Rp28160 +(dp28161 +g201 +g176 +(g177 +(I0 +tp28162 +g179 +tp28163 +Rp28164 +(I1 +(I2 +tp28165 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28166 +tp28167 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp28168 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28169 +g179 +tp28170 +Rp28171 +(I1 +(I1 +I1 +I1 +tp28172 +g38 +I00 +S'\x1c\xae\xb4\x08\xaa|8@' +p28173 +tp28174 +bsg238 +g176 +(g177 +(I0 +tp28175 +g179 +tp28176 +Rp28177 +(I1 +(I1 +I1 +I1 +tp28178 +g38 +I00 +S'C/F\x88\\\xcaW?' +p28179 +tp28180 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28181 +g179 +tp28182 +Rp28183 +(I1 +(I1 +I1 +I1 +tp28184 +g38 +I00 +S'\xf5Q\n\x0e\x8f\xaf\xe0?' +p28185 +tp28186 +bsg252 +g513 +sg48 +(lp28187 +g0 +(g52 +g2 +Ntp28188 +Rp28189 +(dp28190 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp28191 +g179 +tp28192 +Rp28193 +(I1 +(I1 +I1 +I1 +tp28194 +g38 +I00 +S'A\x83\xbe+\xe1vG@' +p28195 +tp28196 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp28197 +g527 +asg113 +I10906 +sg280 +I01 +sbaa(lp28198 +g529 +ag0 +(g190 +g2 +Ntp28199 +Rp28200 +(dp28201 +g194 +I01 +sg195 +(lp28202 +g0 +(g197 +g2 +Ntp28203 +Rp28204 +(dp28205 +g201 +g176 +(g177 +(I0 +tp28206 +g179 +tp28207 +Rp28208 +(I1 +(I1 +tp28209 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28210 +tp28211 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28212 +Rp28213 +(dp28214 +g201 +g176 +(g177 +(I0 +tp28215 +g179 +tp28216 +Rp28217 +(I1 +(I2 +tp28218 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28219 +tp28220 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28221 +Rp28222 +(dp28223 +g201 +g176 +(g177 +(I0 +tp28224 +g179 +tp28225 +Rp28226 +(I1 +(I2 +tp28227 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28228 +tp28229 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp28230 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28231 +g179 +tp28232 +Rp28233 +(I1 +(I1 +I1 +I1 +tp28234 +g38 +I00 +S'n\x9a\xfb\xd4Fo\x0b@' +p28235 +tp28236 +bsg238 +g176 +(g177 +(I0 +tp28237 +g179 +tp28238 +Rp28239 +(I1 +(I1 +I1 +I1 +tp28240 +g38 +I00 +S'0\x8b\x8c\xcb\xbd\x13C?' +p28241 +tp28242 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28243 +g179 +tp28244 +Rp28245 +(I1 +(I1 +I1 +I1 +tp28246 +g38 +I00 +S'\xdb\xff\xc4y\xd6\xf9\xc8?' +p28247 +tp28248 +bsg252 +g586 +sg48 +(lp28249 +g0 +(g52 +g2 +Ntp28250 +Rp28251 +(dp28252 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp28253 +g179 +tp28254 +Rp28255 +(I1 +(I1 +I1 +I1 +tp28256 +g38 +I00 +S'\xe6\x83\x9e\xcd\xaa\x8f1@' +p28257 +tp28258 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp28259 +g600 +asg113 +I10907 +sg280 +I01 +sbaatp28260 +Rp28261 +sg337 +I00 +sg338 +Nsbaa(lp28262 +g604 +ag0 +(g605 +g2 +Ntp28263 +Rp28264 +(dp28265 +g17 +g27896 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28266 +(lp28267 +g611 +ag0 +(g190 +g2 +Ntp28268 +Rp28269 +(dp28270 +g194 +I01 +sg195 +(lp28271 +g0 +(g197 +g2 +Ntp28272 +Rp28273 +(dp28274 +g201 +g176 +(g177 +(I0 +tp28275 +g179 +tp28276 +Rp28277 +(I1 +(I1 +tp28278 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28279 +tp28280 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28281 +Rp28282 +(dp28283 +g201 +g176 +(g177 +(I0 +tp28284 +g179 +tp28285 +Rp28286 +(I1 +(I2 +tp28287 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28288 +tp28289 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp28290 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28291 +g179 +tp28292 +Rp28293 +(I1 +(I1 +I1 +I1 +tp28294 +g38 +I00 +S'f\xcb\xa5{\x1c\xdb\xa3?' +p28295 +tp28296 +bsg238 +g176 +(g177 +(I0 +tp28297 +g179 +tp28298 +Rp28299 +(I1 +(I1 +I1 +I1 +tp28300 +g38 +I00 +S"C\xf1d\xc6L\x98'?" +p28301 +tp28302 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28303 +g179 +tp28304 +Rp28305 +(I1 +(I1 +I1 +I1 +tp28306 +g38 +I00 +S'$T>\xe6a/\x95?' +p28307 +tp28308 +bsg252 +g513 +sg48 +(lp28309 +g0 +(g52 +g2 +Ntp28310 +Rp28311 +(dp28312 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp28313 +g179 +tp28314 +Rp28315 +(I1 +(I1 +I1 +I1 +tp28316 +g38 +I00 +S'S\xa6\xc7\xab\xa1\xca\xfd?' +p28317 +tp28318 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp28319 +g664 +asg113 +I10910 +sg280 +I01 +sbaa(lp28320 +g666 +ag0 +(g190 +g2 +Ntp28321 +Rp28322 +(dp28323 +g194 +I01 +sg195 +(lp28324 +g0 +(g197 +g2 +Ntp28325 +Rp28326 +(dp28327 +g201 +g176 +(g177 +(I0 +tp28328 +g179 +tp28329 +Rp28330 +(I1 +(I1 +tp28331 +g208 +I00 +S"I'\x00\x00\x00\x00\x00\x00" +p28332 +tp28333 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28334 +Rp28335 +(dp28336 +g201 +g176 +(g177 +(I0 +tp28337 +g179 +tp28338 +Rp28339 +(I1 +(I2 +tp28340 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28341 +tp28342 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp28343 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28344 +g179 +tp28345 +Rp28346 +(I1 +(I1 +I1 +I1 +tp28347 +g38 +I00 +S'j\xcb\xa5{\x1c\xdb\xa3?' +p28348 +tp28349 +bsg238 +g176 +(g177 +(I0 +tp28350 +g179 +tp28351 +Rp28352 +(I1 +(I1 +I1 +I1 +tp28353 +g38 +I00 +S"\xfe\xf1d\xc6L\x98'?" +p28354 +tp28355 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28356 +g179 +tp28357 +Rp28358 +(I1 +(I1 +I1 +I1 +tp28359 +g38 +I00 +S'%T>\xe6a/\x95?' +p28360 +tp28361 +bsg252 +g713 +sg48 +(lp28362 +g0 +(g52 +g2 +Ntp28363 +Rp28364 +(dp28365 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp28366 +g179 +tp28367 +Rp28368 +(I1 +(I1 +I1 +I1 +tp28369 +g38 +I00 +S'T\xa6\xc7\xab\xa1\xca\xfd?' +p28370 +tp28371 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp28372 +g727 +asg113 +I10911 +sg280 +I01 +sbaatp28373 +Rp28374 +sg337 +I00 +sg338 +Nsbaatp28375 +Rp28376 +aa(lp28377 +I10058 +ag7 +((lp28378 +(lp28379 +g12 +ag0 +(g13 +g2 +Ntp28380 +Rp28381 +(dp28382 +g17 +g0 +(g18 +g2 +Ntp28383 +Rp28384 +(dp28385 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p28386 +sg116 +g0 +(g117 +g2 +Ntp28387 +Rp28388 +(dp28389 +g121 +(lp28390 +g0 +(g123 +g2 +Ntp28391 +Rp28392 +(dp28393 +g127 +g24991 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp28394 +Rp28395 +(dp28396 +g127 +g17653 +sg148 +g162 +sbasbsg163 +Nsg113 +I10058 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28397 +(lp28398 +g189 +ag0 +(g190 +g2 +Ntp28399 +Rp28400 +(dp28401 +g194 +I01 +sg195 +(lp28402 +g0 +(g197 +g2 +Ntp28403 +Rp28404 +(dp28405 +g201 +g176 +(g177 +(I0 +tp28406 +g179 +tp28407 +Rp28408 +(I1 +(I1 +tp28409 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28410 +tp28411 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28412 +Rp28413 +(dp28414 +g201 +g176 +(g177 +(I0 +tp28415 +g179 +tp28416 +Rp28417 +(I1 +(I2 +tp28418 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28419 +tp28420 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28421 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28422 +g179 +tp28423 +Rp28424 +(I1 +(I1 +I1 +I1 +tp28425 +g38 +I00 +S']\xd4\xfc\xec\xb4\xa5C@' +p28426 +tp28427 +bsg238 +g176 +(g177 +(I0 +tp28428 +g179 +tp28429 +Rp28430 +(I1 +(I1 +I1 +I1 +tp28431 +g38 +I00 +S'\xb6\xcd\xe3\xc7\xcf\x9dD?' +p28432 +tp28433 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28434 +g179 +tp28435 +Rp28436 +(I1 +(I1 +I1 +I1 +tp28437 +g38 +I00 +S'\xe2\xb22\x8c\xbe$\xe5?' +p28438 +tp28439 +bsg252 +g260 +sg48 +(lp28440 +g0 +(g52 +g2 +Ntp28441 +Rp28442 +(dp28443 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28444 +g179 +tp28445 +Rp28446 +(I1 +(I1 +I1 +I1 +tp28447 +g38 +I00 +S"\x8eK'\xf5\xab\xbbM@" +p28448 +tp28449 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28450 +g279 +asg113 +I10914 +sg280 +I01 +sbaa(lp28451 +g12 +ag0 +(g190 +g2 +Ntp28452 +Rp28453 +(dp28454 +g194 +I01 +sg195 +(lp28455 +g0 +(g197 +g2 +Ntp28456 +Rp28457 +(dp28458 +g201 +g176 +(g177 +(I0 +tp28459 +g179 +tp28460 +Rp28461 +(I1 +(I1 +tp28462 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28463 +tp28464 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28465 +Rp28466 +(dp28467 +g201 +g176 +(g177 +(I0 +tp28468 +g179 +tp28469 +Rp28470 +(I1 +(I2 +tp28471 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28472 +tp28473 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28474 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28475 +g179 +tp28476 +Rp28477 +(I1 +(I1 +I1 +I1 +tp28478 +g38 +I00 +S'\xa2\xa6\x07\xa5\xc538@' +p28479 +tp28480 +bsg238 +g176 +(g177 +(I0 +tp28481 +g179 +tp28482 +Rp28483 +(I1 +(I1 +I1 +I1 +tp28484 +g38 +I00 +S'\xf2\x1b$\xdc2\x19C?' +p28485 +tp28486 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28487 +g179 +tp28488 +Rp28489 +(I1 +(I1 +I1 +I1 +tp28490 +g38 +I00 +S'\x0b+\x98\xb2\xe0\x97\xe0?' +p28491 +tp28492 +bsg252 +g260 +sg48 +(lp28493 +g0 +(g52 +g2 +Ntp28494 +Rp28495 +(dp28496 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28497 +g179 +tp28498 +Rp28499 +(I1 +(I1 +I1 +I1 +tp28500 +g38 +I00 +S'\x88\xfc%\xfb\x93UG@' +p28501 +tp28502 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28503 +g334 +asg113 +I10915 +sg280 +I01 +sbaatp28504 +Rp28505 +sg337 +I00 +sg338 +Nsbaa(lp28506 +g340 +ag0 +(g341 +g2 +Ntp28507 +Rp28508 +(dp28509 +g17 +g28384 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28510 +(lp28511 +g189 +ag0 +(g190 +g2 +Ntp28512 +Rp28513 +(dp28514 +g194 +I01 +sg195 +(lp28515 +g0 +(g197 +g2 +Ntp28516 +Rp28517 +(dp28518 +g201 +g176 +(g177 +(I0 +tp28519 +g179 +tp28520 +Rp28521 +(I1 +(I1 +tp28522 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28523 +tp28524 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28525 +Rp28526 +(dp28527 +g201 +g176 +(g177 +(I0 +tp28528 +g179 +tp28529 +Rp28530 +(I1 +(I2 +tp28531 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28532 +tp28533 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28534 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28535 +g179 +tp28536 +Rp28537 +(I1 +(I1 +I1 +I1 +tp28538 +g38 +I00 +S']\xd4\xfc\xec\xb4\xa5C@' +p28539 +tp28540 +bsg238 +g176 +(g177 +(I0 +tp28541 +g179 +tp28542 +Rp28543 +(I1 +(I1 +I1 +I1 +tp28544 +g38 +I00 +S'\xb6\xcd\xe3\xc7\xcf\x9dD?' +p28545 +tp28546 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28547 +g179 +tp28548 +Rp28549 +(I1 +(I1 +I1 +I1 +tp28550 +g38 +I00 +S'\xe2\xb22\x8c\xbe$\xe5?' +p28551 +tp28552 +bsg252 +g260 +sg48 +(lp28553 +g0 +(g52 +g2 +Ntp28554 +Rp28555 +(dp28556 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28557 +g179 +tp28558 +Rp28559 +(I1 +(I1 +I1 +I1 +tp28560 +g38 +I00 +S"\x8eK'\xf5\xab\xbbM@" +p28561 +tp28562 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28563 +g279 +asg113 +I10918 +sg280 +I01 +sbaa(lp28564 +g401 +ag0 +(g190 +g2 +Ntp28565 +Rp28566 +(dp28567 +g194 +I01 +sg195 +(lp28568 +g0 +(g197 +g2 +Ntp28569 +Rp28570 +(dp28571 +g201 +g176 +(g177 +(I0 +tp28572 +g179 +tp28573 +Rp28574 +(I1 +(I1 +tp28575 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28576 +tp28577 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28578 +Rp28579 +(dp28580 +g201 +g176 +(g177 +(I0 +tp28581 +g179 +tp28582 +Rp28583 +(I1 +(I2 +tp28584 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28585 +tp28586 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28587 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28588 +g179 +tp28589 +Rp28590 +(I1 +(I1 +I1 +I1 +tp28591 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28592 +tp28593 +bsg238 +g176 +(g177 +(I0 +tp28594 +g179 +tp28595 +Rp28596 +(I1 +(I1 +I1 +I1 +tp28597 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28598 +tp28599 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28600 +g179 +tp28601 +Rp28602 +(I1 +(I1 +I1 +I1 +tp28603 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28604 +tp28605 +bsg252 +g260 +sg48 +(lp28606 +g0 +(g52 +g2 +Ntp28607 +Rp28608 +(dp28609 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28610 +g179 +tp28611 +Rp28612 +(I1 +(I1 +I1 +I1 +tp28613 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28614 +tp28615 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28616 +g454 +asg113 +I10919 +sg280 +I01 +sbaatp28617 +Rp28618 +sg337 +I00 +sg338 +Nsbaa(lp28619 +g458 +ag0 +(g459 +g2 +Ntp28620 +Rp28621 +(dp28622 +g17 +g28384 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28623 +(lp28624 +g189 +ag0 +(g190 +g2 +Ntp28625 +Rp28626 +(dp28627 +g194 +I01 +sg195 +(lp28628 +g0 +(g197 +g2 +Ntp28629 +Rp28630 +(dp28631 +g201 +g176 +(g177 +(I0 +tp28632 +g179 +tp28633 +Rp28634 +(I1 +(I1 +tp28635 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28636 +tp28637 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28638 +Rp28639 +(dp28640 +g201 +g176 +(g177 +(I0 +tp28641 +g179 +tp28642 +Rp28643 +(I1 +(I2 +tp28644 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28645 +tp28646 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp28647 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28648 +g179 +tp28649 +Rp28650 +(I1 +(I1 +I1 +I1 +tp28651 +g38 +I00 +S'\xce\xa4\xdcK\x89\xbdC@' +p28652 +tp28653 +bsg238 +g176 +(g177 +(I0 +tp28654 +g179 +tp28655 +Rp28656 +(I1 +(I1 +I1 +I1 +tp28657 +g38 +I00 +S'!\xfa\xfd`\x88\xdaX?' +p28658 +tp28659 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28660 +g179 +tp28661 +Rp28662 +(I1 +(I1 +I1 +I1 +tp28663 +g38 +I00 +S'\x80\x17\x1a\xe9\x800\xe5?' +p28664 +tp28665 +bsg252 +g513 +sg48 +(lp28666 +g0 +(g52 +g2 +Ntp28667 +Rp28668 +(dp28669 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp28670 +g179 +tp28671 +Rp28672 +(I1 +(I1 +I1 +I1 +tp28673 +g38 +I00 +S'\x0c\xb1\xccG5\xccM@' +p28674 +tp28675 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp28676 +g527 +asg113 +I10922 +sg280 +I01 +sbaa(lp28677 +g529 +ag0 +(g190 +g2 +Ntp28678 +Rp28679 +(dp28680 +g194 +I01 +sg195 +(lp28681 +g0 +(g197 +g2 +Ntp28682 +Rp28683 +(dp28684 +g201 +g176 +(g177 +(I0 +tp28685 +g179 +tp28686 +Rp28687 +(I1 +(I1 +tp28688 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28689 +tp28690 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28691 +Rp28692 +(dp28693 +g201 +g176 +(g177 +(I0 +tp28694 +g179 +tp28695 +Rp28696 +(I1 +(I2 +tp28697 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28698 +tp28699 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28700 +Rp28701 +(dp28702 +g201 +g176 +(g177 +(I0 +tp28703 +g179 +tp28704 +Rp28705 +(I1 +(I2 +tp28706 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28707 +tp28708 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp28709 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28710 +g179 +tp28711 +Rp28712 +(I1 +(I1 +I1 +I1 +tp28713 +g38 +I00 +S'r\xdcZ\r&\xe47@' +p28714 +tp28715 +bsg238 +g176 +(g177 +(I0 +tp28716 +g179 +tp28717 +Rp28718 +(I1 +(I1 +I1 +I1 +tp28719 +g38 +I00 +S'\\S0]\x1a\xbdN?' +p28720 +tp28721 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28722 +g179 +tp28723 +Rp28724 +(I1 +(I1 +I1 +I1 +tp28725 +g38 +I00 +S'\xcc\x19Q\xda\x1b|\xe0?' +p28726 +tp28727 +bsg252 +g586 +sg48 +(lp28728 +g0 +(g52 +g2 +Ntp28729 +Rp28730 +(dp28731 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp28732 +g179 +tp28733 +Rp28734 +(I1 +(I1 +I1 +I1 +tp28735 +g38 +I00 +S'G\x0c\x02+\x87.G@' +p28736 +tp28737 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp28738 +g600 +asg113 +I10923 +sg280 +I01 +sbaatp28739 +Rp28740 +sg337 +I00 +sg338 +Nsbaa(lp28741 +g604 +ag0 +(g605 +g2 +Ntp28742 +Rp28743 +(dp28744 +g17 +g28384 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28745 +(lp28746 +g611 +ag0 +(g190 +g2 +Ntp28747 +Rp28748 +(dp28749 +g194 +I01 +sg195 +(lp28750 +g0 +(g197 +g2 +Ntp28751 +Rp28752 +(dp28753 +g201 +g176 +(g177 +(I0 +tp28754 +g179 +tp28755 +Rp28756 +(I1 +(I1 +tp28757 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28758 +tp28759 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28760 +Rp28761 +(dp28762 +g201 +g176 +(g177 +(I0 +tp28763 +g179 +tp28764 +Rp28765 +(I1 +(I2 +tp28766 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28767 +tp28768 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp28769 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28770 +g179 +tp28771 +Rp28772 +(I1 +(I1 +I1 +I1 +tp28773 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28774 +tp28775 +bsg238 +g176 +(g177 +(I0 +tp28776 +g179 +tp28777 +Rp28778 +(I1 +(I1 +I1 +I1 +tp28779 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28780 +tp28781 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28782 +g179 +tp28783 +Rp28784 +(I1 +(I1 +I1 +I1 +tp28785 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28786 +tp28787 +bsg252 +g513 +sg48 +(lp28788 +g0 +(g52 +g2 +Ntp28789 +Rp28790 +(dp28791 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp28792 +g179 +tp28793 +Rp28794 +(I1 +(I1 +I1 +I1 +tp28795 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28796 +tp28797 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp28798 +g664 +asg113 +I10926 +sg280 +I01 +sbaa(lp28799 +g666 +ag0 +(g190 +g2 +Ntp28800 +Rp28801 +(dp28802 +g194 +I01 +sg195 +(lp28803 +g0 +(g197 +g2 +Ntp28804 +Rp28805 +(dp28806 +g201 +g176 +(g177 +(I0 +tp28807 +g179 +tp28808 +Rp28809 +(I1 +(I1 +tp28810 +g208 +I00 +S"J'\x00\x00\x00\x00\x00\x00" +p28811 +tp28812 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28813 +Rp28814 +(dp28815 +g201 +g176 +(g177 +(I0 +tp28816 +g179 +tp28817 +Rp28818 +(I1 +(I2 +tp28819 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28820 +tp28821 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp28822 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28823 +g179 +tp28824 +Rp28825 +(I1 +(I1 +I1 +I1 +tp28826 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28827 +tp28828 +bsg238 +g176 +(g177 +(I0 +tp28829 +g179 +tp28830 +Rp28831 +(I1 +(I1 +I1 +I1 +tp28832 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28833 +tp28834 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28835 +g179 +tp28836 +Rp28837 +(I1 +(I1 +I1 +I1 +tp28838 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28839 +tp28840 +bsg252 +g713 +sg48 +(lp28841 +g0 +(g52 +g2 +Ntp28842 +Rp28843 +(dp28844 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp28845 +g179 +tp28846 +Rp28847 +(I1 +(I1 +I1 +I1 +tp28848 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p28849 +tp28850 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp28851 +g727 +asg113 +I10927 +sg280 +I01 +sbaatp28852 +Rp28853 +sg337 +I00 +sg338 +Nsbaatp28854 +Rp28855 +aa(lp28856 +I10059 +ag7 +((lp28857 +(lp28858 +g12 +ag0 +(g13 +g2 +Ntp28859 +Rp28860 +(dp28861 +g17 +g0 +(g18 +g2 +Ntp28862 +Rp28863 +(dp28864 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p28865 +sg116 +g0 +(g117 +g2 +Ntp28866 +Rp28867 +(dp28868 +g121 +(lp28869 +g0 +(g123 +g2 +Ntp28870 +Rp28871 +(dp28872 +g127 +g20590 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp28873 +Rp28874 +(dp28875 +g127 +g0 +(g128 +g2 +Ntp28876 +Rp28877 +(dp28878 +g23 +g132 +sg133 +(dp28879 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x9a\x99\x99\x99\x99\x99\xd9?' +p28880 +tp28881 +Rp28882 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p28883 +sg113 +I87 +sg146 +(lp28884 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10059 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28885 +(lp28886 +g189 +ag0 +(g190 +g2 +Ntp28887 +Rp28888 +(dp28889 +g194 +I01 +sg195 +(lp28890 +g0 +(g197 +g2 +Ntp28891 +Rp28892 +(dp28893 +g201 +g176 +(g177 +(I0 +tp28894 +g179 +tp28895 +Rp28896 +(I1 +(I1 +tp28897 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p28898 +tp28899 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28900 +Rp28901 +(dp28902 +g201 +g176 +(g177 +(I0 +tp28903 +g179 +tp28904 +Rp28905 +(I1 +(I2 +tp28906 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28907 +tp28908 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28909 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28910 +g179 +tp28911 +Rp28912 +(I1 +(I1 +I1 +I1 +tp28913 +g38 +I00 +S"\xc6'`\xfe\x06c8@" +p28914 +tp28915 +bsg238 +g176 +(g177 +(I0 +tp28916 +g179 +tp28917 +Rp28918 +(I1 +(I1 +I1 +I1 +tp28919 +g38 +I00 +S'\xa7L\xacZrLC?' +p28920 +tp28921 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28922 +g179 +tp28923 +Rp28924 +(I1 +(I1 +I1 +I1 +tp28925 +g38 +I00 +S'\xa6i\x12\x07\x0b\xa8\xe0?' +p28926 +tp28927 +bsg252 +g260 +sg48 +(lp28928 +g0 +(g52 +g2 +Ntp28929 +Rp28930 +(dp28931 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28932 +g179 +tp28933 +Rp28934 +(I1 +(I1 +I1 +I1 +tp28935 +g38 +I00 +S'\x92\xe4\xf1\x81OlG@' +p28936 +tp28937 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28938 +g279 +asg113 +I10930 +sg280 +I01 +sbaa(lp28939 +g12 +ag0 +(g190 +g2 +Ntp28940 +Rp28941 +(dp28942 +g194 +I01 +sg195 +(lp28943 +g0 +(g197 +g2 +Ntp28944 +Rp28945 +(dp28946 +g201 +g176 +(g177 +(I0 +tp28947 +g179 +tp28948 +Rp28949 +(I1 +(I1 +tp28950 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p28951 +tp28952 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp28953 +Rp28954 +(dp28955 +g201 +g176 +(g177 +(I0 +tp28956 +g179 +tp28957 +Rp28958 +(I1 +(I2 +tp28959 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p28960 +tp28961 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp28962 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp28963 +g179 +tp28964 +Rp28965 +(I1 +(I1 +I1 +I1 +tp28966 +g38 +I00 +S'\x19\x1d"\xe3\x85&\x0f@' +p28967 +tp28968 +bsg238 +g176 +(g177 +(I0 +tp28969 +g179 +tp28970 +Rp28971 +(I1 +(I1 +I1 +I1 +tp28972 +g38 +I00 +S'e&XQ\xee\xb10?' +p28973 +tp28974 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp28975 +g179 +tp28976 +Rp28977 +(I1 +(I1 +I1 +I1 +tp28978 +g38 +I00 +S'\xefH\xac5U\x9f\xca?' +p28979 +tp28980 +bsg252 +g260 +sg48 +(lp28981 +g0 +(g52 +g2 +Ntp28982 +Rp28983 +(dp28984 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp28985 +g179 +tp28986 +Rp28987 +(I1 +(I1 +I1 +I1 +tp28988 +g38 +I00 +S'H#\xbd\xe9\x07\xb82@' +p28989 +tp28990 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp28991 +g334 +asg113 +I10931 +sg280 +I01 +sbaatp28992 +Rp28993 +sg337 +I00 +sg338 +Nsbaa(lp28994 +g340 +ag0 +(g341 +g2 +Ntp28995 +Rp28996 +(dp28997 +g17 +g28863 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp28998 +(lp28999 +g189 +ag0 +(g190 +g2 +Ntp29000 +Rp29001 +(dp29002 +g194 +I01 +sg195 +(lp29003 +g0 +(g197 +g2 +Ntp29004 +Rp29005 +(dp29006 +g201 +g176 +(g177 +(I0 +tp29007 +g179 +tp29008 +Rp29009 +(I1 +(I1 +tp29010 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29011 +tp29012 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29013 +Rp29014 +(dp29015 +g201 +g176 +(g177 +(I0 +tp29016 +g179 +tp29017 +Rp29018 +(I1 +(I2 +tp29019 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29020 +tp29021 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29022 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29023 +g179 +tp29024 +Rp29025 +(I1 +(I1 +I1 +I1 +tp29026 +g38 +I00 +S"\xc6'`\xfe\x06c8@" +p29027 +tp29028 +bsg238 +g176 +(g177 +(I0 +tp29029 +g179 +tp29030 +Rp29031 +(I1 +(I1 +I1 +I1 +tp29032 +g38 +I00 +S'\xa7L\xacZrLC?' +p29033 +tp29034 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29035 +g179 +tp29036 +Rp29037 +(I1 +(I1 +I1 +I1 +tp29038 +g38 +I00 +S'\xa6i\x12\x07\x0b\xa8\xe0?' +p29039 +tp29040 +bsg252 +g260 +sg48 +(lp29041 +g0 +(g52 +g2 +Ntp29042 +Rp29043 +(dp29044 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29045 +g179 +tp29046 +Rp29047 +(I1 +(I1 +I1 +I1 +tp29048 +g38 +I00 +S'\x92\xe4\xf1\x81OlG@' +p29049 +tp29050 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29051 +g279 +asg113 +I10934 +sg280 +I01 +sbaa(lp29052 +g401 +ag0 +(g190 +g2 +Ntp29053 +Rp29054 +(dp29055 +g194 +I01 +sg195 +(lp29056 +g0 +(g197 +g2 +Ntp29057 +Rp29058 +(dp29059 +g201 +g176 +(g177 +(I0 +tp29060 +g179 +tp29061 +Rp29062 +(I1 +(I1 +tp29063 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29064 +tp29065 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29066 +Rp29067 +(dp29068 +g201 +g176 +(g177 +(I0 +tp29069 +g179 +tp29070 +Rp29071 +(I1 +(I2 +tp29072 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29073 +tp29074 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29075 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29076 +g179 +tp29077 +Rp29078 +(I1 +(I1 +I1 +I1 +tp29079 +g38 +I00 +S'\xc3\xd61^\x9e&\xa0?' +p29080 +tp29081 +bsg238 +g176 +(g177 +(I0 +tp29082 +g179 +tp29083 +Rp29084 +(I1 +(I1 +I1 +I1 +tp29085 +g38 +I00 +S'\xa4+\xa5\x1e\x9bM\x07?' +p29086 +tp29087 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29088 +g179 +tp29089 +Rp29090 +(I1 +(I1 +I1 +I1 +tp29091 +g38 +I00 +S'^\xb5\xe1\xf0\x81*\x93?' +p29092 +tp29093 +bsg252 +g260 +sg48 +(lp29094 +g0 +(g52 +g2 +Ntp29095 +Rp29096 +(dp29097 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29098 +g179 +tp29099 +Rp29100 +(I1 +(I1 +I1 +I1 +tp29101 +g38 +I00 +S'\x0cg\xbd\xba\xc6\xf3\xfa?' +p29102 +tp29103 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29104 +g454 +asg113 +I10935 +sg280 +I01 +sbaatp29105 +Rp29106 +sg337 +I00 +sg338 +Nsbaa(lp29107 +g458 +ag0 +(g459 +g2 +Ntp29108 +Rp29109 +(dp29110 +g17 +g28863 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29111 +(lp29112 +g189 +ag0 +(g190 +g2 +Ntp29113 +Rp29114 +(dp29115 +g194 +I01 +sg195 +(lp29116 +g0 +(g197 +g2 +Ntp29117 +Rp29118 +(dp29119 +g201 +g176 +(g177 +(I0 +tp29120 +g179 +tp29121 +Rp29122 +(I1 +(I1 +tp29123 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29124 +tp29125 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29126 +Rp29127 +(dp29128 +g201 +g176 +(g177 +(I0 +tp29129 +g179 +tp29130 +Rp29131 +(I1 +(I2 +tp29132 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29133 +tp29134 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp29135 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29136 +g179 +tp29137 +Rp29138 +(I1 +(I1 +I1 +I1 +tp29139 +g38 +I00 +S'\xe2\x87\xb3\x8f\xef\x868@' +p29140 +tp29141 +bsg238 +g176 +(g177 +(I0 +tp29142 +g179 +tp29143 +Rp29144 +(I1 +(I1 +I1 +I1 +tp29145 +g38 +I00 +S'\xd6B\xea=_VU?' +p29146 +tp29147 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29148 +g179 +tp29149 +Rp29150 +(I1 +(I1 +I1 +I1 +tp29151 +g38 +I00 +S'\x89o\x8b\xf3X\xb3\xe0?' +p29152 +tp29153 +bsg252 +g513 +sg48 +(lp29154 +g0 +(g52 +g2 +Ntp29155 +Rp29156 +(dp29157 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp29158 +g179 +tp29159 +Rp29160 +(I1 +(I1 +I1 +I1 +tp29161 +g38 +I00 +S'\xd8\x14|\x165|G@' +p29162 +tp29163 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp29164 +g527 +asg113 +I10938 +sg280 +I01 +sbaa(lp29165 +g529 +ag0 +(g190 +g2 +Ntp29166 +Rp29167 +(dp29168 +g194 +I01 +sg195 +(lp29169 +g0 +(g197 +g2 +Ntp29170 +Rp29171 +(dp29172 +g201 +g176 +(g177 +(I0 +tp29173 +g179 +tp29174 +Rp29175 +(I1 +(I1 +tp29176 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29177 +tp29178 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29179 +Rp29180 +(dp29181 +g201 +g176 +(g177 +(I0 +tp29182 +g179 +tp29183 +Rp29184 +(I1 +(I2 +tp29185 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29186 +tp29187 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29188 +Rp29189 +(dp29190 +g201 +g176 +(g177 +(I0 +tp29191 +g179 +tp29192 +Rp29193 +(I1 +(I2 +tp29194 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29195 +tp29196 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp29197 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29198 +g179 +tp29199 +Rp29200 +(I1 +(I1 +I1 +I1 +tp29201 +g38 +I00 +S'\xdc\xdcV\x82\xden\x0b@' +p29202 +tp29203 +bsg238 +g176 +(g177 +(I0 +tp29204 +g179 +tp29205 +Rp29206 +(I1 +(I1 +I1 +I1 +tp29207 +g38 +I00 +S"\x11'\x071N\x91@?" +p29208 +tp29209 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29210 +g179 +tp29211 +Rp29212 +(I1 +(I1 +I1 +I1 +tp29213 +g38 +I00 +S'\x98\x84\xe2RF\xfa\xc8?' +p29214 +tp29215 +bsg252 +g586 +sg48 +(lp29216 +g0 +(g52 +g2 +Ntp29217 +Rp29218 +(dp29219 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp29220 +g179 +tp29221 +Rp29222 +(I1 +(I1 +I1 +I1 +tp29223 +g38 +I00 +S';EGr\xf9\x8f1@' +p29224 +tp29225 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp29226 +g600 +asg113 +I10939 +sg280 +I01 +sbaatp29227 +Rp29228 +sg337 +I00 +sg338 +Nsbaa(lp29229 +g604 +ag0 +(g605 +g2 +Ntp29230 +Rp29231 +(dp29232 +g17 +g28863 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29233 +(lp29234 +g611 +ag0 +(g190 +g2 +Ntp29235 +Rp29236 +(dp29237 +g194 +I01 +sg195 +(lp29238 +g0 +(g197 +g2 +Ntp29239 +Rp29240 +(dp29241 +g201 +g176 +(g177 +(I0 +tp29242 +g179 +tp29243 +Rp29244 +(I1 +(I1 +tp29245 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29246 +tp29247 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29248 +Rp29249 +(dp29250 +g201 +g176 +(g177 +(I0 +tp29251 +g179 +tp29252 +Rp29253 +(I1 +(I2 +tp29254 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29255 +tp29256 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp29257 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29258 +g179 +tp29259 +Rp29260 +(I1 +(I1 +I1 +I1 +tp29261 +g38 +I00 +S'\xdc\x1b\x84\xcfK\x91\xa0?' +p29262 +tp29263 +bsg238 +g176 +(g177 +(I0 +tp29264 +g179 +tp29265 +Rp29266 +(I1 +(I1 +I1 +I1 +tp29267 +g38 +I00 +S'\rwI}\xfb3+?' +p29268 +tp29269 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29270 +g179 +tp29271 +Rp29272 +(I1 +(I1 +I1 +I1 +tp29273 +g38 +I00 +S'\xda\xbf\xdb\xbd\x13P\x93?' +p29274 +tp29275 +bsg252 +g513 +sg48 +(lp29276 +g0 +(g52 +g2 +Ntp29277 +Rp29278 +(dp29279 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp29280 +g179 +tp29281 +Rp29282 +(I1 +(I1 +I1 +I1 +tp29283 +g38 +I00 +S'\xcb\x05\xfd\xc2\x9b(\xfb?' +p29284 +tp29285 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp29286 +g664 +asg113 +I10942 +sg280 +I01 +sbaa(lp29287 +g666 +ag0 +(g190 +g2 +Ntp29288 +Rp29289 +(dp29290 +g194 +I01 +sg195 +(lp29291 +g0 +(g197 +g2 +Ntp29292 +Rp29293 +(dp29294 +g201 +g176 +(g177 +(I0 +tp29295 +g179 +tp29296 +Rp29297 +(I1 +(I1 +tp29298 +g208 +I00 +S"K'\x00\x00\x00\x00\x00\x00" +p29299 +tp29300 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29301 +Rp29302 +(dp29303 +g201 +g176 +(g177 +(I0 +tp29304 +g179 +tp29305 +Rp29306 +(I1 +(I2 +tp29307 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29308 +tp29309 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp29310 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29311 +g179 +tp29312 +Rp29313 +(I1 +(I1 +I1 +I1 +tp29314 +g38 +I00 +S'\xdc\x1b\x84\xcfK\x91\xa0?' +p29315 +tp29316 +bsg238 +g176 +(g177 +(I0 +tp29317 +g179 +tp29318 +Rp29319 +(I1 +(I1 +I1 +I1 +tp29320 +g38 +I00 +S'\xffuI}\xfb3+?' +p29321 +tp29322 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29323 +g179 +tp29324 +Rp29325 +(I1 +(I1 +I1 +I1 +tp29326 +g38 +I00 +S'\xdc\xbf\xdb\xbd\x13P\x93?' +p29327 +tp29328 +bsg252 +g713 +sg48 +(lp29329 +g0 +(g52 +g2 +Ntp29330 +Rp29331 +(dp29332 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp29333 +g179 +tp29334 +Rp29335 +(I1 +(I1 +I1 +I1 +tp29336 +g38 +I00 +S'\xcd\x05\xfd\xc2\x9b(\xfb?' +p29337 +tp29338 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp29339 +g727 +asg113 +I10943 +sg280 +I01 +sbaatp29340 +Rp29341 +sg337 +I00 +sg338 +Nsbaatp29342 +Rp29343 +aa(lp29344 +I10060 +ag7 +((lp29345 +(lp29346 +g12 +ag0 +(g13 +g2 +Ntp29347 +Rp29348 +(dp29349 +g17 +g0 +(g18 +g2 +Ntp29350 +Rp29351 +(dp29352 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p29353 +sg116 +g0 +(g117 +g2 +Ntp29354 +Rp29355 +(dp29356 +g121 +(lp29357 +g0 +(g123 +g2 +Ntp29358 +Rp29359 +(dp29360 +g127 +g2342 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp29361 +Rp29362 +(dp29363 +g127 +g27910 +sg148 +g149 +sbasbsg163 +Nsg113 +I10060 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29364 +(lp29365 +g189 +ag0 +(g190 +g2 +Ntp29366 +Rp29367 +(dp29368 +g194 +I01 +sg195 +(lp29369 +g0 +(g197 +g2 +Ntp29370 +Rp29371 +(dp29372 +g201 +g176 +(g177 +(I0 +tp29373 +g179 +tp29374 +Rp29375 +(I1 +(I1 +tp29376 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29377 +tp29378 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29379 +Rp29380 +(dp29381 +g201 +g176 +(g177 +(I0 +tp29382 +g179 +tp29383 +Rp29384 +(I1 +(I2 +tp29385 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29386 +tp29387 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29388 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29389 +g179 +tp29390 +Rp29391 +(I1 +(I1 +I1 +I1 +tp29392 +g38 +I00 +S'\xd1\xa6\xf3\x07\x12m8@' +p29393 +tp29394 +bsg238 +g176 +(g177 +(I0 +tp29395 +g179 +tp29396 +Rp29397 +(I1 +(I1 +I1 +I1 +tp29398 +g38 +I00 +S'>~\xed\x94\xcd~A?' +p29399 +tp29400 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29401 +g179 +tp29402 +Rp29403 +(I1 +(I1 +I1 +I1 +tp29404 +g38 +I00 +S'\x9a\x0b\x92\xdd\x83\xab\xe0?' +p29405 +tp29406 +bsg252 +g260 +sg48 +(lp29407 +g0 +(g52 +g2 +Ntp29408 +Rp29409 +(dp29410 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29411 +g179 +tp29412 +Rp29413 +(I1 +(I1 +I1 +I1 +tp29414 +g38 +I00 +S'P`\x95o1qG@' +p29415 +tp29416 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29417 +g279 +asg113 +I10946 +sg280 +I01 +sbaa(lp29418 +g12 +ag0 +(g190 +g2 +Ntp29419 +Rp29420 +(dp29421 +g194 +I01 +sg195 +(lp29422 +g0 +(g197 +g2 +Ntp29423 +Rp29424 +(dp29425 +g201 +g176 +(g177 +(I0 +tp29426 +g179 +tp29427 +Rp29428 +(I1 +(I1 +tp29429 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29430 +tp29431 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29432 +Rp29433 +(dp29434 +g201 +g176 +(g177 +(I0 +tp29435 +g179 +tp29436 +Rp29437 +(I1 +(I2 +tp29438 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29439 +tp29440 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29441 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29442 +g179 +tp29443 +Rp29444 +(I1 +(I1 +I1 +I1 +tp29445 +g38 +I00 +S's\xa0\xe6)I\x97\x0f@' +p29446 +tp29447 +bsg238 +g176 +(g177 +(I0 +tp29448 +g179 +tp29449 +Rp29450 +(I1 +(I1 +I1 +I1 +tp29451 +g38 +I00 +S'\x0b\x8a\xd4$&\xf9-?' +p29452 +tp29453 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29454 +g179 +tp29455 +Rp29456 +(I1 +(I1 +I1 +I1 +tp29457 +g38 +I00 +S'+y\x15\x8bq\xcf\xca?' +p29458 +tp29459 +bsg252 +g260 +sg48 +(lp29460 +g0 +(g52 +g2 +Ntp29461 +Rp29462 +(dp29463 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29464 +g179 +tp29465 +Rp29466 +(I1 +(I1 +I1 +I1 +tp29467 +g38 +I00 +S'2\x19\xcb\xd5\xdb\xd92@' +p29468 +tp29469 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29470 +g334 +asg113 +I10947 +sg280 +I01 +sbaatp29471 +Rp29472 +sg337 +I00 +sg338 +Nsbaa(lp29473 +g340 +ag0 +(g341 +g2 +Ntp29474 +Rp29475 +(dp29476 +g17 +g29351 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29477 +(lp29478 +g189 +ag0 +(g190 +g2 +Ntp29479 +Rp29480 +(dp29481 +g194 +I01 +sg195 +(lp29482 +g0 +(g197 +g2 +Ntp29483 +Rp29484 +(dp29485 +g201 +g176 +(g177 +(I0 +tp29486 +g179 +tp29487 +Rp29488 +(I1 +(I1 +tp29489 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29490 +tp29491 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29492 +Rp29493 +(dp29494 +g201 +g176 +(g177 +(I0 +tp29495 +g179 +tp29496 +Rp29497 +(I1 +(I2 +tp29498 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29499 +tp29500 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29501 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29502 +g179 +tp29503 +Rp29504 +(I1 +(I1 +I1 +I1 +tp29505 +g38 +I00 +S'\xd1\xa6\xf3\x07\x12m8@' +p29506 +tp29507 +bsg238 +g176 +(g177 +(I0 +tp29508 +g179 +tp29509 +Rp29510 +(I1 +(I1 +I1 +I1 +tp29511 +g38 +I00 +S'>~\xed\x94\xcd~A?' +p29512 +tp29513 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29514 +g179 +tp29515 +Rp29516 +(I1 +(I1 +I1 +I1 +tp29517 +g38 +I00 +S'\x9a\x0b\x92\xdd\x83\xab\xe0?' +p29518 +tp29519 +bsg252 +g260 +sg48 +(lp29520 +g0 +(g52 +g2 +Ntp29521 +Rp29522 +(dp29523 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29524 +g179 +tp29525 +Rp29526 +(I1 +(I1 +I1 +I1 +tp29527 +g38 +I00 +S'P`\x95o1qG@' +p29528 +tp29529 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29530 +g279 +asg113 +I10950 +sg280 +I01 +sbaa(lp29531 +g401 +ag0 +(g190 +g2 +Ntp29532 +Rp29533 +(dp29534 +g194 +I01 +sg195 +(lp29535 +g0 +(g197 +g2 +Ntp29536 +Rp29537 +(dp29538 +g201 +g176 +(g177 +(I0 +tp29539 +g179 +tp29540 +Rp29541 +(I1 +(I1 +tp29542 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29543 +tp29544 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29545 +Rp29546 +(dp29547 +g201 +g176 +(g177 +(I0 +tp29548 +g179 +tp29549 +Rp29550 +(I1 +(I2 +tp29551 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29552 +tp29553 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29554 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29555 +g179 +tp29556 +Rp29557 +(I1 +(I1 +I1 +I1 +tp29558 +g38 +I00 +S'ZD\xfa\xfa\xacc\xa3?' +p29559 +tp29560 +bsg238 +g176 +(g177 +(I0 +tp29561 +g179 +tp29562 +Rp29563 +(I1 +(I1 +I1 +I1 +tp29564 +g38 +I00 +S'\xcfY\xcb2\xc7E\t?' +p29565 +tp29566 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29567 +g179 +tp29568 +Rp29569 +(I1 +(I1 +I1 +I1 +tp29570 +g38 +I00 +S'\xc1~\t\x16\xfe\xff\x94?' +p29571 +tp29572 +bsg252 +g260 +sg48 +(lp29573 +g0 +(g52 +g2 +Ntp29574 +Rp29575 +(dp29576 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29577 +g179 +tp29578 +Rp29579 +(I1 +(I1 +I1 +I1 +tp29580 +g38 +I00 +S'?Z\xfdN\xfd\x87\xfd?' +p29581 +tp29582 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29583 +g454 +asg113 +I10951 +sg280 +I01 +sbaatp29584 +Rp29585 +sg337 +I00 +sg338 +Nsbaa(lp29586 +g458 +ag0 +(g459 +g2 +Ntp29587 +Rp29588 +(dp29589 +g17 +g29351 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29590 +(lp29591 +g189 +ag0 +(g190 +g2 +Ntp29592 +Rp29593 +(dp29594 +g194 +I01 +sg195 +(lp29595 +g0 +(g197 +g2 +Ntp29596 +Rp29597 +(dp29598 +g201 +g176 +(g177 +(I0 +tp29599 +g179 +tp29600 +Rp29601 +(I1 +(I1 +tp29602 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29603 +tp29604 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29605 +Rp29606 +(dp29607 +g201 +g176 +(g177 +(I0 +tp29608 +g179 +tp29609 +Rp29610 +(I1 +(I2 +tp29611 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29612 +tp29613 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp29614 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29615 +g179 +tp29616 +Rp29617 +(I1 +(I1 +I1 +I1 +tp29618 +g38 +I00 +S'\xf6\x96\x81\xfe\x92j8@' +p29619 +tp29620 +bsg238 +g176 +(g177 +(I0 +tp29621 +g179 +tp29622 +Rp29623 +(I1 +(I1 +I1 +I1 +tp29624 +g38 +I00 +S'B\x8f\x87V75T?' +p29625 +tp29626 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29627 +g179 +tp29628 +Rp29629 +(I1 +(I1 +I1 +I1 +tp29630 +g38 +I00 +S'\xb7\xca(=\xcc\xa9\xe0?' +p29631 +tp29632 +bsg252 +g513 +sg48 +(lp29633 +g0 +(g52 +g2 +Ntp29634 +Rp29635 +(dp29636 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp29637 +g179 +tp29638 +Rp29639 +(I1 +(I1 +I1 +I1 +tp29640 +g38 +I00 +S'\x11]\x016\xc7nG@' +p29641 +tp29642 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp29643 +g527 +asg113 +I10954 +sg280 +I01 +sbaa(lp29644 +g529 +ag0 +(g190 +g2 +Ntp29645 +Rp29646 +(dp29647 +g194 +I01 +sg195 +(lp29648 +g0 +(g197 +g2 +Ntp29649 +Rp29650 +(dp29651 +g201 +g176 +(g177 +(I0 +tp29652 +g179 +tp29653 +Rp29654 +(I1 +(I1 +tp29655 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29656 +tp29657 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29658 +Rp29659 +(dp29660 +g201 +g176 +(g177 +(I0 +tp29661 +g179 +tp29662 +Rp29663 +(I1 +(I2 +tp29664 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29665 +tp29666 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29667 +Rp29668 +(dp29669 +g201 +g176 +(g177 +(I0 +tp29670 +g179 +tp29671 +Rp29672 +(I1 +(I2 +tp29673 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29674 +tp29675 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp29676 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29677 +g179 +tp29678 +Rp29679 +(I1 +(I1 +I1 +I1 +tp29680 +g38 +I00 +S'f\xa6a\xb6l^\x0b@' +p29681 +tp29682 +bsg238 +g176 +(g177 +(I0 +tp29683 +g179 +tp29684 +Rp29685 +(I1 +(I1 +I1 +I1 +tp29686 +g38 +I00 +S'\xaeU\xcc|\x146>?' +p29687 +tp29688 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29689 +g179 +tp29690 +Rp29691 +(I1 +(I1 +I1 +I1 +tp29692 +g38 +I00 +S'yA\x93&\x1a\xf3\xc8?' +p29693 +tp29694 +bsg252 +g586 +sg48 +(lp29695 +g0 +(g52 +g2 +Ntp29696 +Rp29697 +(dp29698 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp29699 +g179 +tp29700 +Rp29701 +(I1 +(I1 +I1 +I1 +tp29702 +g38 +I00 +S'\t\x8a\x1fc\xee\x8a1@' +p29703 +tp29704 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp29705 +g600 +asg113 +I10955 +sg280 +I01 +sbaatp29706 +Rp29707 +sg337 +I00 +sg338 +Nsbaa(lp29708 +g604 +ag0 +(g605 +g2 +Ntp29709 +Rp29710 +(dp29711 +g17 +g29351 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29712 +(lp29713 +g611 +ag0 +(g190 +g2 +Ntp29714 +Rp29715 +(dp29716 +g194 +I01 +sg195 +(lp29717 +g0 +(g197 +g2 +Ntp29718 +Rp29719 +(dp29720 +g201 +g176 +(g177 +(I0 +tp29721 +g179 +tp29722 +Rp29723 +(I1 +(I1 +tp29724 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29725 +tp29726 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29727 +Rp29728 +(dp29729 +g201 +g176 +(g177 +(I0 +tp29730 +g179 +tp29731 +Rp29732 +(I1 +(I2 +tp29733 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29734 +tp29735 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp29736 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29737 +g179 +tp29738 +Rp29739 +(I1 +(I1 +I1 +I1 +tp29740 +g38 +I00 +S'\x11\xf2\xdb\x97\xae\x14\xa3?' +p29741 +tp29742 +bsg238 +g176 +(g177 +(I0 +tp29743 +g179 +tp29744 +Rp29745 +(I1 +(I1 +I1 +I1 +tp29746 +g38 +I00 +S"5\x06C'\xb0\x00'?" +p29747 +tp29748 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29749 +g179 +tp29750 +Rp29751 +(I1 +(I1 +I1 +I1 +tp29752 +g38 +I00 +S';\xa0+6\xab\xc4\x94?' +p29753 +tp29754 +bsg252 +g513 +sg48 +(lp29755 +g0 +(g52 +g2 +Ntp29756 +Rp29757 +(dp29758 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp29759 +g179 +tp29760 +Rp29761 +(I1 +(I1 +I1 +I1 +tp29762 +g38 +I00 +S'SY-\xc4\x904\xfd?' +p29763 +tp29764 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp29765 +g664 +asg113 +I10958 +sg280 +I01 +sbaa(lp29766 +g666 +ag0 +(g190 +g2 +Ntp29767 +Rp29768 +(dp29769 +g194 +I01 +sg195 +(lp29770 +g0 +(g197 +g2 +Ntp29771 +Rp29772 +(dp29773 +g201 +g176 +(g177 +(I0 +tp29774 +g179 +tp29775 +Rp29776 +(I1 +(I1 +tp29777 +g208 +I00 +S"L'\x00\x00\x00\x00\x00\x00" +p29778 +tp29779 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29780 +Rp29781 +(dp29782 +g201 +g176 +(g177 +(I0 +tp29783 +g179 +tp29784 +Rp29785 +(I1 +(I2 +tp29786 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29787 +tp29788 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp29789 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29790 +g179 +tp29791 +Rp29792 +(I1 +(I1 +I1 +I1 +tp29793 +g38 +I00 +S'\x12\xf2\xdb\x97\xae\x14\xa3?' +p29794 +tp29795 +bsg238 +g176 +(g177 +(I0 +tp29796 +g179 +tp29797 +Rp29798 +(I1 +(I1 +I1 +I1 +tp29799 +g38 +I00 +S"u\x06C'\xb0\x00'?" +p29800 +tp29801 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29802 +g179 +tp29803 +Rp29804 +(I1 +(I1 +I1 +I1 +tp29805 +g38 +I00 +S';\xa0+6\xab\xc4\x94?' +p29806 +tp29807 +bsg252 +g713 +sg48 +(lp29808 +g0 +(g52 +g2 +Ntp29809 +Rp29810 +(dp29811 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp29812 +g179 +tp29813 +Rp29814 +(I1 +(I1 +I1 +I1 +tp29815 +g38 +I00 +S'SY-\xc4\x904\xfd?' +p29816 +tp29817 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp29818 +g727 +asg113 +I10959 +sg280 +I01 +sbaatp29819 +Rp29820 +sg337 +I00 +sg338 +Nsbaatp29821 +Rp29822 +aa(lp29823 +I10061 +ag7 +((lp29824 +(lp29825 +g12 +ag0 +(g13 +g2 +Ntp29826 +Rp29827 +(dp29828 +g17 +g0 +(g18 +g2 +Ntp29829 +Rp29830 +(dp29831 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p29832 +sg116 +g0 +(g117 +g2 +Ntp29833 +Rp29834 +(dp29835 +g121 +(lp29836 +g0 +(g123 +g2 +Ntp29837 +Rp29838 +(dp29839 +g127 +g0 +(g128 +g2 +Ntp29840 +Rp29841 +(dp29842 +g23 +g132 +sg133 +(dp29843 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S')\\\x8f\xc2\xf5(\x00@' +p29844 +tp29845 +Rp29846 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p29847 +sg113 +I88 +sg146 +(lp29848 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp29849 +Rp29850 +(dp29851 +g127 +g21563 +sg148 +g149 +sbasbsg163 +Nsg113 +I10061 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29852 +(lp29853 +g189 +ag0 +(g190 +g2 +Ntp29854 +Rp29855 +(dp29856 +g194 +I01 +sg195 +(lp29857 +g0 +(g197 +g2 +Ntp29858 +Rp29859 +(dp29860 +g201 +g176 +(g177 +(I0 +tp29861 +g179 +tp29862 +Rp29863 +(I1 +(I1 +tp29864 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p29865 +tp29866 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29867 +Rp29868 +(dp29869 +g201 +g176 +(g177 +(I0 +tp29870 +g179 +tp29871 +Rp29872 +(I1 +(I2 +tp29873 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29874 +tp29875 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29876 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29877 +g179 +tp29878 +Rp29879 +(I1 +(I1 +I1 +I1 +tp29880 +g38 +I00 +S'\xddhe\xa2\x89\x06\x0f@' +p29881 +tp29882 +bsg238 +g176 +(g177 +(I0 +tp29883 +g179 +tp29884 +Rp29885 +(I1 +(I1 +I1 +I1 +tp29886 +g38 +I00 +S'\x95\xa5\xfen\xe0\x9e+?' +p29887 +tp29888 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29889 +g179 +tp29890 +Rp29891 +(I1 +(I1 +I1 +I1 +tp29892 +g38 +I00 +S'\xf9\xfbb\x13\xcb\x91\xca?' +p29893 +tp29894 +bsg252 +g260 +sg48 +(lp29895 +g0 +(g52 +g2 +Ntp29896 +Rp29897 +(dp29898 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29899 +g179 +tp29900 +Rp29901 +(I1 +(I1 +I1 +I1 +tp29902 +g38 +I00 +S'+\x99\xa1\xc9\x82\xae2@' +p29903 +tp29904 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29905 +g279 +asg113 +I10962 +sg280 +I01 +sbaa(lp29906 +g12 +ag0 +(g190 +g2 +Ntp29907 +Rp29908 +(dp29909 +g194 +I01 +sg195 +(lp29910 +g0 +(g197 +g2 +Ntp29911 +Rp29912 +(dp29913 +g201 +g176 +(g177 +(I0 +tp29914 +g179 +tp29915 +Rp29916 +(I1 +(I1 +tp29917 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p29918 +tp29919 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29920 +Rp29921 +(dp29922 +g201 +g176 +(g177 +(I0 +tp29923 +g179 +tp29924 +Rp29925 +(I1 +(I2 +tp29926 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29927 +tp29928 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29929 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29930 +g179 +tp29931 +Rp29932 +(I1 +(I1 +I1 +I1 +tp29933 +g38 +I00 +S'\x1c\xec\xd5\xb1\xa0\xe7\xd7?' +p29934 +tp29935 +bsg238 +g176 +(g177 +(I0 +tp29936 +g179 +tp29937 +Rp29938 +(I1 +(I1 +I1 +I1 +tp29939 +g38 +I00 +S'\xdc\xd2\xfbM\xde\x7f\x12?' +p29940 +tp29941 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp29942 +g179 +tp29943 +Rp29944 +(I1 +(I1 +I1 +I1 +tp29945 +g38 +I00 +S'3\xc8@\xcf\xb4}\xb0?' +p29946 +tp29947 +bsg252 +g260 +sg48 +(lp29948 +g0 +(g52 +g2 +Ntp29949 +Rp29950 +(dp29951 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp29952 +g179 +tp29953 +Rp29954 +(I1 +(I1 +I1 +I1 +tp29955 +g38 +I00 +S'\x88\x19sC\xc60\x17@' +p29956 +tp29957 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp29958 +g334 +asg113 +I10963 +sg280 +I01 +sbaatp29959 +Rp29960 +sg337 +I00 +sg338 +Nsbaa(lp29961 +g340 +ag0 +(g341 +g2 +Ntp29962 +Rp29963 +(dp29964 +g17 +g29830 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp29965 +(lp29966 +g189 +ag0 +(g190 +g2 +Ntp29967 +Rp29968 +(dp29969 +g194 +I01 +sg195 +(lp29970 +g0 +(g197 +g2 +Ntp29971 +Rp29972 +(dp29973 +g201 +g176 +(g177 +(I0 +tp29974 +g179 +tp29975 +Rp29976 +(I1 +(I1 +tp29977 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p29978 +tp29979 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp29980 +Rp29981 +(dp29982 +g201 +g176 +(g177 +(I0 +tp29983 +g179 +tp29984 +Rp29985 +(I1 +(I2 +tp29986 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p29987 +tp29988 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp29989 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp29990 +g179 +tp29991 +Rp29992 +(I1 +(I1 +I1 +I1 +tp29993 +g38 +I00 +S'\xddhe\xa2\x89\x06\x0f@' +p29994 +tp29995 +bsg238 +g176 +(g177 +(I0 +tp29996 +g179 +tp29997 +Rp29998 +(I1 +(I1 +I1 +I1 +tp29999 +g38 +I00 +S'\x95\xa5\xfen\xe0\x9e+?' +p30000 +tp30001 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30002 +g179 +tp30003 +Rp30004 +(I1 +(I1 +I1 +I1 +tp30005 +g38 +I00 +S'\xf9\xfbb\x13\xcb\x91\xca?' +p30006 +tp30007 +bsg252 +g260 +sg48 +(lp30008 +g0 +(g52 +g2 +Ntp30009 +Rp30010 +(dp30011 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30012 +g179 +tp30013 +Rp30014 +(I1 +(I1 +I1 +I1 +tp30015 +g38 +I00 +S'+\x99\xa1\xc9\x82\xae2@' +p30016 +tp30017 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30018 +g279 +asg113 +I10966 +sg280 +I01 +sbaa(lp30019 +g401 +ag0 +(g190 +g2 +Ntp30020 +Rp30021 +(dp30022 +g194 +I01 +sg195 +(lp30023 +g0 +(g197 +g2 +Ntp30024 +Rp30025 +(dp30026 +g201 +g176 +(g177 +(I0 +tp30027 +g179 +tp30028 +Rp30029 +(I1 +(I1 +tp30030 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p30031 +tp30032 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30033 +Rp30034 +(dp30035 +g201 +g176 +(g177 +(I0 +tp30036 +g179 +tp30037 +Rp30038 +(I1 +(I2 +tp30039 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30040 +tp30041 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30042 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30043 +g179 +tp30044 +Rp30045 +(I1 +(I1 +I1 +I1 +tp30046 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30047 +tp30048 +bsg238 +g176 +(g177 +(I0 +tp30049 +g179 +tp30050 +Rp30051 +(I1 +(I1 +I1 +I1 +tp30052 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30053 +tp30054 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30055 +g179 +tp30056 +Rp30057 +(I1 +(I1 +I1 +I1 +tp30058 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30059 +tp30060 +bsg252 +g260 +sg48 +(lp30061 +g0 +(g52 +g2 +Ntp30062 +Rp30063 +(dp30064 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30065 +g179 +tp30066 +Rp30067 +(I1 +(I1 +I1 +I1 +tp30068 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30069 +tp30070 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30071 +g454 +asg113 +I10967 +sg280 +I01 +sbaatp30072 +Rp30073 +sg337 +I00 +sg338 +Nsbaa(lp30074 +g458 +ag0 +(g459 +g2 +Ntp30075 +Rp30076 +(dp30077 +g17 +g29830 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30078 +(lp30079 +g189 +ag0 +(g190 +g2 +Ntp30080 +Rp30081 +(dp30082 +g194 +I01 +sg195 +(lp30083 +g0 +(g197 +g2 +Ntp30084 +Rp30085 +(dp30086 +g201 +g176 +(g177 +(I0 +tp30087 +g179 +tp30088 +Rp30089 +(I1 +(I1 +tp30090 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p30091 +tp30092 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30093 +Rp30094 +(dp30095 +g201 +g176 +(g177 +(I0 +tp30096 +g179 +tp30097 +Rp30098 +(I1 +(I2 +tp30099 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30100 +tp30101 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp30102 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30103 +g179 +tp30104 +Rp30105 +(I1 +(I1 +I1 +I1 +tp30106 +g38 +I00 +S'\x15\xdd\\\xb5\xaf0\x0f@' +p30107 +tp30108 +bsg238 +g176 +(g177 +(I0 +tp30109 +g179 +tp30110 +Rp30111 +(I1 +(I1 +I1 +I1 +tp30112 +g38 +I00 +S'\xb2\xde\xb6\xa7M\x08Q?' +p30113 +tp30114 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30115 +g179 +tp30116 +Rp30117 +(I1 +(I1 +I1 +I1 +tp30118 +g38 +I00 +S'\x0b\x11\xd9\xd4\x8d\x9c\xca?' +p30119 +tp30120 +bsg252 +g513 +sg48 +(lp30121 +g0 +(g52 +g2 +Ntp30122 +Rp30123 +(dp30124 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp30125 +g179 +tp30126 +Rp30127 +(I1 +(I1 +I1 +I1 +tp30128 +g38 +I00 +S'\xfc\x9f\xa8\xb9\x13\xb62@' +p30129 +tp30130 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp30131 +g527 +asg113 +I10970 +sg280 +I01 +sbaa(lp30132 +g529 +ag0 +(g190 +g2 +Ntp30133 +Rp30134 +(dp30135 +g194 +I01 +sg195 +(lp30136 +g0 +(g197 +g2 +Ntp30137 +Rp30138 +(dp30139 +g201 +g176 +(g177 +(I0 +tp30140 +g179 +tp30141 +Rp30142 +(I1 +(I1 +tp30143 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p30144 +tp30145 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30146 +Rp30147 +(dp30148 +g201 +g176 +(g177 +(I0 +tp30149 +g179 +tp30150 +Rp30151 +(I1 +(I2 +tp30152 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30153 +tp30154 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30155 +Rp30156 +(dp30157 +g201 +g176 +(g177 +(I0 +tp30158 +g179 +tp30159 +Rp30160 +(I1 +(I2 +tp30161 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30162 +tp30163 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp30164 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30165 +g179 +tp30166 +Rp30167 +(I1 +(I1 +I1 +I1 +tp30168 +g38 +I00 +S'\x93\xf2\xc5\xa4\xe0\xe5\xd7?' +p30169 +tp30170 +bsg238 +g176 +(g177 +(I0 +tp30171 +g179 +tp30172 +Rp30173 +(I1 +(I1 +I1 +I1 +tp30174 +g38 +I00 +S'\x91K\nis_4?' +p30175 +tp30176 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30177 +g179 +tp30178 +Rp30179 +(I1 +(I1 +I1 +I1 +tp30180 +g38 +I00 +S'7\n\xc1H\xf3x\xb0?' +p30181 +tp30182 +bsg252 +g586 +sg48 +(lp30183 +g0 +(g52 +g2 +Ntp30184 +Rp30185 +(dp30186 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp30187 +g179 +tp30188 +Rp30189 +(I1 +(I1 +I1 +I1 +tp30190 +g38 +I00 +S'^vO\x1e\x16*\x17@' +p30191 +tp30192 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp30193 +g600 +asg113 +I10971 +sg280 +I01 +sbaatp30194 +Rp30195 +sg337 +I00 +sg338 +Nsbaa(lp30196 +g604 +ag0 +(g605 +g2 +Ntp30197 +Rp30198 +(dp30199 +g17 +g29830 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30200 +(lp30201 +g611 +ag0 +(g190 +g2 +Ntp30202 +Rp30203 +(dp30204 +g194 +I01 +sg195 +(lp30205 +g0 +(g197 +g2 +Ntp30206 +Rp30207 +(dp30208 +g201 +g176 +(g177 +(I0 +tp30209 +g179 +tp30210 +Rp30211 +(I1 +(I1 +tp30212 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p30213 +tp30214 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30215 +Rp30216 +(dp30217 +g201 +g176 +(g177 +(I0 +tp30218 +g179 +tp30219 +Rp30220 +(I1 +(I2 +tp30221 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30222 +tp30223 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp30224 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30225 +g179 +tp30226 +Rp30227 +(I1 +(I1 +I1 +I1 +tp30228 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30229 +tp30230 +bsg238 +g176 +(g177 +(I0 +tp30231 +g179 +tp30232 +Rp30233 +(I1 +(I1 +I1 +I1 +tp30234 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30235 +tp30236 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30237 +g179 +tp30238 +Rp30239 +(I1 +(I1 +I1 +I1 +tp30240 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30241 +tp30242 +bsg252 +g513 +sg48 +(lp30243 +g0 +(g52 +g2 +Ntp30244 +Rp30245 +(dp30246 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp30247 +g179 +tp30248 +Rp30249 +(I1 +(I1 +I1 +I1 +tp30250 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30251 +tp30252 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp30253 +g664 +asg113 +I10974 +sg280 +I01 +sbaa(lp30254 +g666 +ag0 +(g190 +g2 +Ntp30255 +Rp30256 +(dp30257 +g194 +I01 +sg195 +(lp30258 +g0 +(g197 +g2 +Ntp30259 +Rp30260 +(dp30261 +g201 +g176 +(g177 +(I0 +tp30262 +g179 +tp30263 +Rp30264 +(I1 +(I1 +tp30265 +g208 +I00 +S"M'\x00\x00\x00\x00\x00\x00" +p30266 +tp30267 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30268 +Rp30269 +(dp30270 +g201 +g176 +(g177 +(I0 +tp30271 +g179 +tp30272 +Rp30273 +(I1 +(I2 +tp30274 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30275 +tp30276 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp30277 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30278 +g179 +tp30279 +Rp30280 +(I1 +(I1 +I1 +I1 +tp30281 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30282 +tp30283 +bsg238 +g176 +(g177 +(I0 +tp30284 +g179 +tp30285 +Rp30286 +(I1 +(I1 +I1 +I1 +tp30287 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30288 +tp30289 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30290 +g179 +tp30291 +Rp30292 +(I1 +(I1 +I1 +I1 +tp30293 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30294 +tp30295 +bsg252 +g713 +sg48 +(lp30296 +g0 +(g52 +g2 +Ntp30297 +Rp30298 +(dp30299 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp30300 +g179 +tp30301 +Rp30302 +(I1 +(I1 +I1 +I1 +tp30303 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p30304 +tp30305 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp30306 +g727 +asg113 +I10975 +sg280 +I01 +sbaatp30307 +Rp30308 +sg337 +I00 +sg338 +Nsbaatp30309 +Rp30310 +aa(lp30311 +I10062 +ag7 +((lp30312 +(lp30313 +g12 +ag0 +(g13 +g2 +Ntp30314 +Rp30315 +(dp30316 +g17 +g0 +(g18 +g2 +Ntp30317 +Rp30318 +(dp30319 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p30320 +sg116 +g0 +(g117 +g2 +Ntp30321 +Rp30322 +(dp30323 +g121 +(lp30324 +g0 +(g123 +g2 +Ntp30325 +Rp30326 +(dp30327 +g127 +g22051 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp30328 +Rp30329 +(dp30330 +g127 +g26943 +sg148 +g149 +sbasbsg163 +Nsg113 +I10062 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30331 +(lp30332 +g189 +ag0 +(g190 +g2 +Ntp30333 +Rp30334 +(dp30335 +g194 +I01 +sg195 +(lp30336 +g0 +(g197 +g2 +Ntp30337 +Rp30338 +(dp30339 +g201 +g176 +(g177 +(I0 +tp30340 +g179 +tp30341 +Rp30342 +(I1 +(I1 +tp30343 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30344 +tp30345 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30346 +Rp30347 +(dp30348 +g201 +g176 +(g177 +(I0 +tp30349 +g179 +tp30350 +Rp30351 +(I1 +(I2 +tp30352 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30353 +tp30354 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30355 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30356 +g179 +tp30357 +Rp30358 +(I1 +(I1 +I1 +I1 +tp30359 +g38 +I00 +S'>\xc2\x01\xdb\xfd\x878@' +p30360 +tp30361 +bsg238 +g176 +(g177 +(I0 +tp30362 +g179 +tp30363 +Rp30364 +(I1 +(I1 +I1 +I1 +tp30365 +g38 +I00 +S'X\xb2{L\xe9\x0eB?' +p30366 +tp30367 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30368 +g179 +tp30369 +Rp30370 +(I1 +(I1 +I1 +I1 +tp30371 +g38 +I00 +S'k\x0f\xf1\xf2\xad\xb4\xe0?' +p30372 +tp30373 +bsg252 +g260 +sg48 +(lp30374 +g0 +(g52 +g2 +Ntp30375 +Rp30376 +(dp30377 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30378 +g179 +tp30379 +Rp30380 +(I1 +(I1 +I1 +I1 +tp30381 +g38 +I00 +S'\xaf\xfd\xa2\x9d\x14~G@' +p30382 +tp30383 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30384 +g279 +asg113 +I10978 +sg280 +I01 +sbaa(lp30385 +g12 +ag0 +(g190 +g2 +Ntp30386 +Rp30387 +(dp30388 +g194 +I01 +sg195 +(lp30389 +g0 +(g197 +g2 +Ntp30390 +Rp30391 +(dp30392 +g201 +g176 +(g177 +(I0 +tp30393 +g179 +tp30394 +Rp30395 +(I1 +(I1 +tp30396 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30397 +tp30398 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30399 +Rp30400 +(dp30401 +g201 +g176 +(g177 +(I0 +tp30402 +g179 +tp30403 +Rp30404 +(I1 +(I2 +tp30405 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30406 +tp30407 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30408 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30409 +g179 +tp30410 +Rp30411 +(I1 +(I1 +I1 +I1 +tp30412 +g38 +I00 +S'\xdb\x844\x15\x8d\xcc\x10@' +p30413 +tp30414 +bsg238 +g176 +(g177 +(I0 +tp30415 +g179 +tp30416 +Rp30417 +(I1 +(I1 +I1 +I1 +tp30418 +g38 +I00 +S'_\xa3\x19\x8e\xa1\x080?' +p30419 +tp30420 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30421 +g179 +tp30422 +Rp30423 +(I1 +(I1 +I1 +I1 +tp30424 +g38 +I00 +S'eCD\x91\x16\xa6\xcb?' +p30425 +tp30426 +bsg252 +g260 +sg48 +(lp30427 +g0 +(g52 +g2 +Ntp30428 +Rp30429 +(dp30430 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30431 +g179 +tp30432 +Rp30433 +(I1 +(I1 +I1 +I1 +tp30434 +g38 +I00 +S'c\xff#\xde\xc7p3@' +p30435 +tp30436 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30437 +g334 +asg113 +I10979 +sg280 +I01 +sbaatp30438 +Rp30439 +sg337 +I00 +sg338 +Nsbaa(lp30440 +g340 +ag0 +(g341 +g2 +Ntp30441 +Rp30442 +(dp30443 +g17 +g30318 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30444 +(lp30445 +g189 +ag0 +(g190 +g2 +Ntp30446 +Rp30447 +(dp30448 +g194 +I01 +sg195 +(lp30449 +g0 +(g197 +g2 +Ntp30450 +Rp30451 +(dp30452 +g201 +g176 +(g177 +(I0 +tp30453 +g179 +tp30454 +Rp30455 +(I1 +(I1 +tp30456 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30457 +tp30458 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30459 +Rp30460 +(dp30461 +g201 +g176 +(g177 +(I0 +tp30462 +g179 +tp30463 +Rp30464 +(I1 +(I2 +tp30465 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30466 +tp30467 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30468 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30469 +g179 +tp30470 +Rp30471 +(I1 +(I1 +I1 +I1 +tp30472 +g38 +I00 +S'>\xc2\x01\xdb\xfd\x878@' +p30473 +tp30474 +bsg238 +g176 +(g177 +(I0 +tp30475 +g179 +tp30476 +Rp30477 +(I1 +(I1 +I1 +I1 +tp30478 +g38 +I00 +S'X\xb2{L\xe9\x0eB?' +p30479 +tp30480 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30481 +g179 +tp30482 +Rp30483 +(I1 +(I1 +I1 +I1 +tp30484 +g38 +I00 +S'k\x0f\xf1\xf2\xad\xb4\xe0?' +p30485 +tp30486 +bsg252 +g260 +sg48 +(lp30487 +g0 +(g52 +g2 +Ntp30488 +Rp30489 +(dp30490 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30491 +g179 +tp30492 +Rp30493 +(I1 +(I1 +I1 +I1 +tp30494 +g38 +I00 +S'\xaf\xfd\xa2\x9d\x14~G@' +p30495 +tp30496 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30497 +g279 +asg113 +I10982 +sg280 +I01 +sbaa(lp30498 +g401 +ag0 +(g190 +g2 +Ntp30499 +Rp30500 +(dp30501 +g194 +I01 +sg195 +(lp30502 +g0 +(g197 +g2 +Ntp30503 +Rp30504 +(dp30505 +g201 +g176 +(g177 +(I0 +tp30506 +g179 +tp30507 +Rp30508 +(I1 +(I1 +tp30509 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30510 +tp30511 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30512 +Rp30513 +(dp30514 +g201 +g176 +(g177 +(I0 +tp30515 +g179 +tp30516 +Rp30517 +(I1 +(I2 +tp30518 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30519 +tp30520 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30521 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30522 +g179 +tp30523 +Rp30524 +(I1 +(I1 +I1 +I1 +tp30525 +g38 +I00 +S'\xb1\xf4\x8ay\x9fQ\xb2?' +p30526 +tp30527 +bsg238 +g176 +(g177 +(I0 +tp30528 +g179 +tp30529 +Rp30530 +(I1 +(I1 +I1 +I1 +tp30531 +g38 +I00 +S'\xd1\xd5n\xe5$\xf3\x0f?' +p30532 +tp30533 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30534 +g179 +tp30535 +Rp30536 +(I1 +(I1 +I1 +I1 +tp30537 +g38 +I00 +S'\xffEw`8\xde\x9c?' +p30538 +tp30539 +bsg252 +g260 +sg48 +(lp30540 +g0 +(g52 +g2 +Ntp30541 +Rp30542 +(dp30543 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30544 +g179 +tp30545 +Rp30546 +(I1 +(I1 +I1 +I1 +tp30547 +g38 +I00 +S'7\xdd\xd3\xa3?L\x04@' +p30548 +tp30549 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30550 +g454 +asg113 +I10983 +sg280 +I01 +sbaatp30551 +Rp30552 +sg337 +I00 +sg338 +Nsbaa(lp30553 +g458 +ag0 +(g459 +g2 +Ntp30554 +Rp30555 +(dp30556 +g17 +g30318 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30557 +(lp30558 +g189 +ag0 +(g190 +g2 +Ntp30559 +Rp30560 +(dp30561 +g194 +I01 +sg195 +(lp30562 +g0 +(g197 +g2 +Ntp30563 +Rp30564 +(dp30565 +g201 +g176 +(g177 +(I0 +tp30566 +g179 +tp30567 +Rp30568 +(I1 +(I1 +tp30569 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30570 +tp30571 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30572 +Rp30573 +(dp30574 +g201 +g176 +(g177 +(I0 +tp30575 +g179 +tp30576 +Rp30577 +(I1 +(I2 +tp30578 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30579 +tp30580 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp30581 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30582 +g179 +tp30583 +Rp30584 +(I1 +(I1 +I1 +I1 +tp30585 +g38 +I00 +S'\x13\xea\x19\xc8\xb1}8@' +p30586 +tp30587 +bsg238 +g176 +(g177 +(I0 +tp30588 +g179 +tp30589 +Rp30590 +(I1 +(I1 +I1 +I1 +tp30591 +g38 +I00 +S'\xf1\x9a\xcc\x81\xff\x93R?' +p30592 +tp30593 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30594 +g179 +tp30595 +Rp30596 +(I1 +(I1 +I1 +I1 +tp30597 +g38 +I00 +S'\xd7\x1f\xa41|\xb0\xe0?' +p30598 +tp30599 +bsg252 +g513 +sg48 +(lp30600 +g0 +(g52 +g2 +Ntp30601 +Rp30602 +(dp30603 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp30604 +g179 +tp30605 +Rp30606 +(I1 +(I1 +I1 +I1 +tp30607 +g38 +I00 +S'\xc7\xcc\xce\xa5.xG@' +p30608 +tp30609 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp30610 +g527 +asg113 +I10986 +sg280 +I01 +sbaa(lp30611 +g529 +ag0 +(g190 +g2 +Ntp30612 +Rp30613 +(dp30614 +g194 +I01 +sg195 +(lp30615 +g0 +(g197 +g2 +Ntp30616 +Rp30617 +(dp30618 +g201 +g176 +(g177 +(I0 +tp30619 +g179 +tp30620 +Rp30621 +(I1 +(I1 +tp30622 +g208 +I00 +S"N'\x00\x00\x00\x00\x00\x00" +p30623 +tp30624 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30625 +Rp30626 +(dp30627 +g201 +g176 +(g177 +(I0 +tp30628 +g179 +tp30629 +Rp30630 +(I1 +(I2 +tp30631 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30632 +tp30633 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30634 +Rp30635 +(dp30636 +g201 +g176 +(g177 +(I0 +tp30637 +g179 +tp30638 +Rp30639 +(I1 +(I2 +tp30640 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30641 +tp30642 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp30643 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30644 +g179 +tp30645 +Rp30646 +(I1 +(I1 +I1 +I1 +tp30647 +g38 +I00 +S'd\xe2\xfa=\xd2\xcc\x0b@' +p30648 +tp30649 +bsg238 +g176 +(g177 +(I0 +tp30650 +g179 +tp30651 +Rp30652 +(I1 +(I1 +I1 +I1 +tp30653 +g38 +I00 +S'w\xf1\x83\x0b\xec*rF\xe8\x95(\xb0?' +p30904 +tp30905 +bsg252 +g260 +sg48 +(lp30906 +g0 +(g52 +g2 +Ntp30907 +Rp30908 +(dp30909 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30910 +g179 +tp30911 +Rp30912 +(I1 +(I1 +I1 +I1 +tp30913 +g38 +I00 +S'\xa7\x10\xa3\xce\x12\xb9\x16@' +p30914 +tp30915 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30916 +g334 +asg113 +I10995 +sg280 +I01 +sbaatp30917 +Rp30918 +sg337 +I00 +sg338 +Nsbaa(lp30919 +g340 +ag0 +(g341 +g2 +Ntp30920 +Rp30921 +(dp30922 +g17 +g30797 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp30923 +(lp30924 +g189 +ag0 +(g190 +g2 +Ntp30925 +Rp30926 +(dp30927 +g194 +I01 +sg195 +(lp30928 +g0 +(g197 +g2 +Ntp30929 +Rp30930 +(dp30931 +g201 +g176 +(g177 +(I0 +tp30932 +g179 +tp30933 +Rp30934 +(I1 +(I1 +tp30935 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p30936 +tp30937 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30938 +Rp30939 +(dp30940 +g201 +g176 +(g177 +(I0 +tp30941 +g179 +tp30942 +Rp30943 +(I1 +(I2 +tp30944 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30945 +tp30946 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp30947 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp30948 +g179 +tp30949 +Rp30950 +(I1 +(I1 +I1 +I1 +tp30951 +g38 +I00 +S']\x82a\xad\x81\x1c\x0e@' +p30952 +tp30953 +bsg238 +g176 +(g177 +(I0 +tp30954 +g179 +tp30955 +Rp30956 +(I1 +(I1 +I1 +I1 +tp30957 +g38 +I00 +S'\xd6\\\x9aGA[+?' +p30958 +tp30959 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp30960 +g179 +tp30961 +Rp30962 +(I1 +(I1 +I1 +I1 +tp30963 +g38 +I00 +S',N\xe1\xdb\xd4,\xca?' +p30964 +tp30965 +bsg252 +g260 +sg48 +(lp30966 +g0 +(g52 +g2 +Ntp30967 +Rp30968 +(dp30969 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp30970 +g179 +tp30971 +Rp30972 +(I1 +(I1 +I1 +I1 +tp30973 +g38 +I00 +S'\xf7j\x9a\xaa\x85g2@' +p30974 +tp30975 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp30976 +g279 +asg113 +I10998 +sg280 +I01 +sbaa(lp30977 +g401 +ag0 +(g190 +g2 +Ntp30978 +Rp30979 +(dp30980 +g194 +I01 +sg195 +(lp30981 +g0 +(g197 +g2 +Ntp30982 +Rp30983 +(dp30984 +g201 +g176 +(g177 +(I0 +tp30985 +g179 +tp30986 +Rp30987 +(I1 +(I1 +tp30988 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p30989 +tp30990 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp30991 +Rp30992 +(dp30993 +g201 +g176 +(g177 +(I0 +tp30994 +g179 +tp30995 +Rp30996 +(I1 +(I2 +tp30997 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p30998 +tp30999 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp31000 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31001 +g179 +tp31002 +Rp31003 +(I1 +(I1 +I1 +I1 +tp31004 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31005 +tp31006 +bsg238 +g176 +(g177 +(I0 +tp31007 +g179 +tp31008 +Rp31009 +(I1 +(I1 +I1 +I1 +tp31010 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31011 +tp31012 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31013 +g179 +tp31014 +Rp31015 +(I1 +(I1 +I1 +I1 +tp31016 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31017 +tp31018 +bsg252 +g260 +sg48 +(lp31019 +g0 +(g52 +g2 +Ntp31020 +Rp31021 +(dp31022 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp31023 +g179 +tp31024 +Rp31025 +(I1 +(I1 +I1 +I1 +tp31026 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31027 +tp31028 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp31029 +g454 +asg113 +I10999 +sg280 +I01 +sbaatp31030 +Rp31031 +sg337 +I00 +sg338 +Nsbaa(lp31032 +g458 +ag0 +(g459 +g2 +Ntp31033 +Rp31034 +(dp31035 +g17 +g30797 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp31036 +(lp31037 +g189 +ag0 +(g190 +g2 +Ntp31038 +Rp31039 +(dp31040 +g194 +I01 +sg195 +(lp31041 +g0 +(g197 +g2 +Ntp31042 +Rp31043 +(dp31044 +g201 +g176 +(g177 +(I0 +tp31045 +g179 +tp31046 +Rp31047 +(I1 +(I1 +tp31048 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p31049 +tp31050 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31051 +Rp31052 +(dp31053 +g201 +g176 +(g177 +(I0 +tp31054 +g179 +tp31055 +Rp31056 +(I1 +(I2 +tp31057 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31058 +tp31059 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp31060 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31061 +g179 +tp31062 +Rp31063 +(I1 +(I1 +I1 +I1 +tp31064 +g38 +I00 +S'\xba\xd3`\xc14\x0e\x0e@' +p31065 +tp31066 +bsg238 +g176 +(g177 +(I0 +tp31067 +g179 +tp31068 +Rp31069 +(I1 +(I1 +I1 +I1 +tp31070 +g38 +I00 +S'\xb3\x7f\xec\xb8\x84\x03N?' +p31071 +tp31072 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31073 +g179 +tp31074 +Rp31075 +(I1 +(I1 +I1 +I1 +tp31076 +g38 +I00 +S'bm\xd4\xdd\xee \xca?' +p31077 +tp31078 +bsg252 +g513 +sg48 +(lp31079 +g0 +(g52 +g2 +Ntp31080 +Rp31081 +(dp31082 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp31083 +g179 +tp31084 +Rp31085 +(I1 +(I1 +I1 +I1 +tp31086 +g38 +I00 +S"\xe9\\\xf9\xf3'_2@" +p31087 +tp31088 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp31089 +g527 +asg113 +I11002 +sg280 +I01 +sbaa(lp31090 +g529 +ag0 +(g190 +g2 +Ntp31091 +Rp31092 +(dp31093 +g194 +I01 +sg195 +(lp31094 +g0 +(g197 +g2 +Ntp31095 +Rp31096 +(dp31097 +g201 +g176 +(g177 +(I0 +tp31098 +g179 +tp31099 +Rp31100 +(I1 +(I1 +tp31101 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p31102 +tp31103 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31104 +Rp31105 +(dp31106 +g201 +g176 +(g177 +(I0 +tp31107 +g179 +tp31108 +Rp31109 +(I1 +(I2 +tp31110 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31111 +tp31112 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31113 +Rp31114 +(dp31115 +g201 +g176 +(g177 +(I0 +tp31116 +g179 +tp31117 +Rp31118 +(I1 +(I2 +tp31119 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31120 +tp31121 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp31122 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31123 +g179 +tp31124 +Rp31125 +(I1 +(I1 +I1 +I1 +tp31126 +g38 +I00 +S'b\xdc\xbb\xa3R\xae\xd6?' +p31127 +tp31128 +bsg238 +g176 +(g177 +(I0 +tp31129 +g179 +tp31130 +Rp31131 +(I1 +(I1 +I1 +I1 +tp31132 +g38 +I00 +S'7x\xe7\x1b=J2?' +p31133 +tp31134 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31135 +g179 +tp31136 +Rp31137 +(I1 +(I1 +I1 +I1 +tp31138 +g38 +I00 +S'\xa35\xb7\xe0\xd0\x0c\xb0?' +p31139 +tp31140 +bsg252 +g586 +sg48 +(lp31141 +g0 +(g52 +g2 +Ntp31142 +Rp31143 +(dp31144 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp31145 +g179 +tp31146 +Rp31147 +(I1 +(I1 +I1 +I1 +tp31148 +g38 +I00 +S'm\xa3\x01\xbc\x05\x92\x16@' +p31149 +tp31150 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp31151 +g600 +asg113 +I11003 +sg280 +I01 +sbaatp31152 +Rp31153 +sg337 +I00 +sg338 +Nsbaa(lp31154 +g604 +ag0 +(g605 +g2 +Ntp31155 +Rp31156 +(dp31157 +g17 +g30797 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp31158 +(lp31159 +g611 +ag0 +(g190 +g2 +Ntp31160 +Rp31161 +(dp31162 +g194 +I01 +sg195 +(lp31163 +g0 +(g197 +g2 +Ntp31164 +Rp31165 +(dp31166 +g201 +g176 +(g177 +(I0 +tp31167 +g179 +tp31168 +Rp31169 +(I1 +(I1 +tp31170 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p31171 +tp31172 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31173 +Rp31174 +(dp31175 +g201 +g176 +(g177 +(I0 +tp31176 +g179 +tp31177 +Rp31178 +(I1 +(I2 +tp31179 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31180 +tp31181 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp31182 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31183 +g179 +tp31184 +Rp31185 +(I1 +(I1 +I1 +I1 +tp31186 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31187 +tp31188 +bsg238 +g176 +(g177 +(I0 +tp31189 +g179 +tp31190 +Rp31191 +(I1 +(I1 +I1 +I1 +tp31192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31193 +tp31194 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31195 +g179 +tp31196 +Rp31197 +(I1 +(I1 +I1 +I1 +tp31198 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31199 +tp31200 +bsg252 +g513 +sg48 +(lp31201 +g0 +(g52 +g2 +Ntp31202 +Rp31203 +(dp31204 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp31205 +g179 +tp31206 +Rp31207 +(I1 +(I1 +I1 +I1 +tp31208 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31209 +tp31210 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp31211 +g664 +asg113 +I11006 +sg280 +I01 +sbaa(lp31212 +g666 +ag0 +(g190 +g2 +Ntp31213 +Rp31214 +(dp31215 +g194 +I01 +sg195 +(lp31216 +g0 +(g197 +g2 +Ntp31217 +Rp31218 +(dp31219 +g201 +g176 +(g177 +(I0 +tp31220 +g179 +tp31221 +Rp31222 +(I1 +(I1 +tp31223 +g208 +I00 +S"O'\x00\x00\x00\x00\x00\x00" +p31224 +tp31225 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31226 +Rp31227 +(dp31228 +g201 +g176 +(g177 +(I0 +tp31229 +g179 +tp31230 +Rp31231 +(I1 +(I2 +tp31232 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31233 +tp31234 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp31235 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31236 +g179 +tp31237 +Rp31238 +(I1 +(I1 +I1 +I1 +tp31239 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31240 +tp31241 +bsg238 +g176 +(g177 +(I0 +tp31242 +g179 +tp31243 +Rp31244 +(I1 +(I1 +I1 +I1 +tp31245 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31246 +tp31247 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31248 +g179 +tp31249 +Rp31250 +(I1 +(I1 +I1 +I1 +tp31251 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31252 +tp31253 +bsg252 +g713 +sg48 +(lp31254 +g0 +(g52 +g2 +Ntp31255 +Rp31256 +(dp31257 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp31258 +g179 +tp31259 +Rp31260 +(I1 +(I1 +I1 +I1 +tp31261 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31262 +tp31263 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp31264 +g727 +asg113 +I11007 +sg280 +I01 +sbaatp31265 +Rp31266 +sg337 +I00 +sg338 +Nsbaatp31267 +Rp31268 +aa(lp31269 +I10064 +ag7 +((lp31270 +(lp31271 +g12 +ag0 +(g13 +g2 +Ntp31272 +Rp31273 +(dp31274 +g17 +g0 +(g18 +g2 +Ntp31275 +Rp31276 +(dp31277 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p31278 +sg116 +g0 +(g117 +g2 +Ntp31279 +Rp31280 +(dp31281 +g121 +(lp31282 +g0 +(g123 +g2 +Ntp31283 +Rp31284 +(dp31285 +g127 +g0 +(g128 +g2 +Ntp31286 +Rp31287 +(dp31288 +g23 +g132 +sg133 +(dp31289 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\n\xd7\xa3p=\n\x03@' +p31290 +tp31291 +Rp31292 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p31293 +sg113 +I89 +sg146 +(lp31294 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp31295 +Rp31296 +(dp31297 +g127 +g0 +(g128 +g2 +Ntp31298 +Rp31299 +(dp31300 +g23 +g132 +sg133 +(dp31301 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xe1z\x14\xaeG\xe1\x02@' +p31302 +tp31303 +Rp31304 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p31305 +sg113 +I90 +sg146 +(lp31306 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10064 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp31307 +(lp31308 +g189 +ag0 +(g190 +g2 +Ntp31309 +Rp31310 +(dp31311 +g194 +I01 +sg195 +(lp31312 +g0 +(g197 +g2 +Ntp31313 +Rp31314 +(dp31315 +g201 +g176 +(g177 +(I0 +tp31316 +g179 +tp31317 +Rp31318 +(I1 +(I1 +tp31319 +g208 +I00 +S"P'\x00\x00\x00\x00\x00\x00" +p31320 +tp31321 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31322 +Rp31323 +(dp31324 +g201 +g176 +(g177 +(I0 +tp31325 +g179 +tp31326 +Rp31327 +(I1 +(I2 +tp31328 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31329 +tp31330 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp31331 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31332 +g179 +tp31333 +Rp31334 +(I1 +(I1 +I1 +I1 +tp31335 +g38 +I00 +S'Z\xfch\x00=+\r@' +p31336 +tp31337 +bsg238 +g176 +(g177 +(I0 +tp31338 +g179 +tp31339 +Rp31340 +(I1 +(I1 +I1 +I1 +tp31341 +g38 +I00 +S'\xe1\xfd\x80G\x9aQ*?' +p31342 +tp31343 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31344 +g179 +tp31345 +Rp31346 +(I1 +(I1 +I1 +I1 +tp31347 +g38 +I00 +S'\xd4tG\x9c%\xc3\xc9?' +p31348 +tp31349 +bsg252 +g260 +sg48 +(lp31350 +g0 +(g52 +g2 +Ntp31351 +Rp31352 +(dp31353 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp31354 +g179 +tp31355 +Rp31356 +(I1 +(I1 +I1 +I1 +tp31357 +g38 +I00 +S'%>\xe2q6\x1d2@' +p31358 +tp31359 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp31360 +g279 +asg113 +I11010 +sg280 +I01 +sbaa(lp31361 +g12 +ag0 +(g190 +g2 +Ntp31362 +Rp31363 +(dp31364 +g194 +I01 +sg195 +(lp31365 +g0 +(g197 +g2 +Ntp31366 +Rp31367 +(dp31368 +g201 +g176 +(g177 +(I0 +tp31369 +g179 +tp31370 +Rp31371 +(I1 +(I1 +tp31372 +g208 +I00 +S"P'\x00\x00\x00\x00\x00\x00" +p31373 +tp31374 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31375 +Rp31376 +(dp31377 +g201 +g176 +(g177 +(I0 +tp31378 +g179 +tp31379 +Rp31380 +(I1 +(I2 +tp31381 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31382 +tp31383 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp31384 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31385 +g179 +tp31386 +Rp31387 +(I1 +(I1 +I1 +I1 +tp31388 +g38 +I00 +S'_z\xa1O\x1b\xbd\xd6?' +p31389 +tp31390 +bsg238 +g176 +(g177 +(I0 +tp31391 +g179 +tp31392 +Rp31393 +(I1 +(I1 +I1 +I1 +tp31394 +g38 +I00 +S"Kk*'/\xcf\x10?" +p31395 +tp31396 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31397 +g179 +tp31398 +Rp31399 +(I1 +(I1 +I1 +I1 +tp31400 +g38 +I00 +S'y\xf7\xaa\x88z\x15\xb0?' +p31401 +tp31402 +bsg252 +g260 +sg48 +(lp31403 +g0 +(g52 +g2 +Ntp31404 +Rp31405 +(dp31406 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp31407 +g179 +tp31408 +Rp31409 +(I1 +(I1 +I1 +I1 +tp31410 +g38 +I00 +S'\x02l0P4\x9e\x16@' +p31411 +tp31412 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp31413 +g334 +asg113 +I11011 +sg280 +I01 +sbaatp31414 +Rp31415 +sg337 +I00 +sg338 +Nsbaa(lp31416 +g340 +ag0 +(g341 +g2 +Ntp31417 +Rp31418 +(dp31419 +g17 +g31276 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp31420 +(lp31421 +g189 +ag0 +(g190 +g2 +Ntp31422 +Rp31423 +(dp31424 +g194 +I01 +sg195 +(lp31425 +g0 +(g197 +g2 +Ntp31426 +Rp31427 +(dp31428 +g201 +g176 +(g177 +(I0 +tp31429 +g179 +tp31430 +Rp31431 +(I1 +(I1 +tp31432 +g208 +I00 +S"P'\x00\x00\x00\x00\x00\x00" +p31433 +tp31434 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31435 +Rp31436 +(dp31437 +g201 +g176 +(g177 +(I0 +tp31438 +g179 +tp31439 +Rp31440 +(I1 +(I2 +tp31441 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31442 +tp31443 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp31444 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31445 +g179 +tp31446 +Rp31447 +(I1 +(I1 +I1 +I1 +tp31448 +g38 +I00 +S'Z\xfch\x00=+\r@' +p31449 +tp31450 +bsg238 +g176 +(g177 +(I0 +tp31451 +g179 +tp31452 +Rp31453 +(I1 +(I1 +I1 +I1 +tp31454 +g38 +I00 +S'\xe1\xfd\x80G\x9aQ*?' +p31455 +tp31456 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31457 +g179 +tp31458 +Rp31459 +(I1 +(I1 +I1 +I1 +tp31460 +g38 +I00 +S'\xd4tG\x9c%\xc3\xc9?' +p31461 +tp31462 +bsg252 +g260 +sg48 +(lp31463 +g0 +(g52 +g2 +Ntp31464 +Rp31465 +(dp31466 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp31467 +g179 +tp31468 +Rp31469 +(I1 +(I1 +I1 +I1 +tp31470 +g38 +I00 +S'%>\xe2q6\x1d2@' +p31471 +tp31472 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp31473 +g279 +asg113 +I11014 +sg280 +I01 +sbaa(lp31474 +g401 +ag0 +(g190 +g2 +Ntp31475 +Rp31476 +(dp31477 +g194 +I01 +sg195 +(lp31478 +g0 +(g197 +g2 +Ntp31479 +Rp31480 +(dp31481 +g201 +g176 +(g177 +(I0 +tp31482 +g179 +tp31483 +Rp31484 +(I1 +(I1 +tp31485 +g208 +I00 +S"P'\x00\x00\x00\x00\x00\x00" +p31486 +tp31487 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31488 +Rp31489 +(dp31490 +g201 +g176 +(g177 +(I0 +tp31491 +g179 +tp31492 +Rp31493 +(I1 +(I2 +tp31494 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31495 +tp31496 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp31497 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31498 +g179 +tp31499 +Rp31500 +(I1 +(I1 +I1 +I1 +tp31501 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31502 +tp31503 +bsg238 +g176 +(g177 +(I0 +tp31504 +g179 +tp31505 +Rp31506 +(I1 +(I1 +I1 +I1 +tp31507 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31508 +tp31509 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp31510 +g179 +tp31511 +Rp31512 +(I1 +(I1 +I1 +I1 +tp31513 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31514 +tp31515 +bsg252 +g260 +sg48 +(lp31516 +g0 +(g52 +g2 +Ntp31517 +Rp31518 +(dp31519 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp31520 +g179 +tp31521 +Rp31522 +(I1 +(I1 +I1 +I1 +tp31523 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p31524 +tp31525 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp31526 +g454 +asg113 +I11015 +sg280 +I01 +sbaatp31527 +Rp31528 +sg337 +I00 +sg338 +Nsbaa(lp31529 +g458 +ag0 +(g459 +g2 +Ntp31530 +Rp31531 +(dp31532 +g17 +g31276 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp31533 +(lp31534 +g189 +ag0 +(g190 +g2 +Ntp31535 +Rp31536 +(dp31537 +g194 +I01 +sg195 +(lp31538 +g0 +(g197 +g2 +Ntp31539 +Rp31540 +(dp31541 +g201 +g176 +(g177 +(I0 +tp31542 +g179 +tp31543 +Rp31544 +(I1 +(I1 +tp31545 +g208 +I00 +S"P'\x00\x00\x00\x00\x00\x00" +p31546 +tp31547 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp31548 +Rp31549 +(dp31550 +g201 +g176 +(g177 +(I0 +tp31551 +g179 +tp31552 +Rp31553 +(I1 +(I2 +tp31554 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p31555 +tp31556 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp31557 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp31558 +g179 +tp31559 +Rp31560 +(I1 +(I1 +I1 +I1 +tp31561 +g38 +I00 +S'\x16K\xcf\xac\x1a\xa7\x0c@' +p31562 +tp31563 +bsg238 +g176 +(g177 +(I0 +tp31564 +g179 +tp31565 +Rp31566 +(I1 +(I1 +I1 +I1 +tp31567 +g38 +I00 +S'\xd6\xaan\x87\x87,Q?' +p32615 +tp32616 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32617 +g179 +tp32618 +Rp32619 +(I1 +(I1 +I1 +I1 +tp32620 +g38 +I00 +S'\x1d\xb8,\x9b\x88\xe0\xe4?' +p32621 +tp32622 +bsg252 +g586 +sg48 +(lp32623 +g0 +(g52 +g2 +Ntp32624 +Rp32625 +(dp32626 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp32627 +g179 +tp32628 +Rp32629 +(I1 +(I1 +I1 +I1 +tp32630 +g38 +I00 +S'\xe9\xe26\x1a\xc0[M@' +p32631 +tp32632 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp32633 +g600 +asg113 +I11051 +sg280 +I01 +sbaatp32634 +Rp32635 +sg337 +I00 +sg338 +Nsbaa(lp32636 +g604 +ag0 +(g605 +g2 +Ntp32637 +Rp32638 +(dp32639 +g17 +g32270 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp32640 +(lp32641 +g611 +ag0 +(g190 +g2 +Ntp32642 +Rp32643 +(dp32644 +g194 +I01 +sg195 +(lp32645 +g0 +(g197 +g2 +Ntp32646 +Rp32647 +(dp32648 +g201 +g176 +(g177 +(I0 +tp32649 +g179 +tp32650 +Rp32651 +(I1 +(I1 +tp32652 +g208 +I00 +S"R'\x00\x00\x00\x00\x00\x00" +p32653 +tp32654 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32655 +Rp32656 +(dp32657 +g201 +g176 +(g177 +(I0 +tp32658 +g179 +tp32659 +Rp32660 +(I1 +(I2 +tp32661 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32662 +tp32663 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp32664 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32665 +g179 +tp32666 +Rp32667 +(I1 +(I1 +I1 +I1 +tp32668 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32669 +tp32670 +bsg238 +g176 +(g177 +(I0 +tp32671 +g179 +tp32672 +Rp32673 +(I1 +(I1 +I1 +I1 +tp32674 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32675 +tp32676 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32677 +g179 +tp32678 +Rp32679 +(I1 +(I1 +I1 +I1 +tp32680 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32681 +tp32682 +bsg252 +g513 +sg48 +(lp32683 +g0 +(g52 +g2 +Ntp32684 +Rp32685 +(dp32686 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp32687 +g179 +tp32688 +Rp32689 +(I1 +(I1 +I1 +I1 +tp32690 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32691 +tp32692 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp32693 +g664 +asg113 +I11054 +sg280 +I01 +sbaa(lp32694 +g666 +ag0 +(g190 +g2 +Ntp32695 +Rp32696 +(dp32697 +g194 +I01 +sg195 +(lp32698 +g0 +(g197 +g2 +Ntp32699 +Rp32700 +(dp32701 +g201 +g176 +(g177 +(I0 +tp32702 +g179 +tp32703 +Rp32704 +(I1 +(I1 +tp32705 +g208 +I00 +S"R'\x00\x00\x00\x00\x00\x00" +p32706 +tp32707 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32708 +Rp32709 +(dp32710 +g201 +g176 +(g177 +(I0 +tp32711 +g179 +tp32712 +Rp32713 +(I1 +(I2 +tp32714 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32715 +tp32716 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp32717 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32718 +g179 +tp32719 +Rp32720 +(I1 +(I1 +I1 +I1 +tp32721 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32722 +tp32723 +bsg238 +g176 +(g177 +(I0 +tp32724 +g179 +tp32725 +Rp32726 +(I1 +(I1 +I1 +I1 +tp32727 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32728 +tp32729 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32730 +g179 +tp32731 +Rp32732 +(I1 +(I1 +I1 +I1 +tp32733 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32734 +tp32735 +bsg252 +g713 +sg48 +(lp32736 +g0 +(g52 +g2 +Ntp32737 +Rp32738 +(dp32739 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp32740 +g179 +tp32741 +Rp32742 +(I1 +(I1 +I1 +I1 +tp32743 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32744 +tp32745 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp32746 +g727 +asg113 +I11055 +sg280 +I01 +sbaatp32747 +Rp32748 +sg337 +I00 +sg338 +Nsbaatp32749 +Rp32750 +aa(lp32751 +I10067 +ag7 +((lp32752 +(lp32753 +g12 +ag0 +(g13 +g2 +Ntp32754 +Rp32755 +(dp32756 +g17 +g0 +(g18 +g2 +Ntp32757 +Rp32758 +(dp32759 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p32760 +sg116 +g0 +(g117 +g2 +Ntp32761 +Rp32762 +(dp32763 +g121 +(lp32764 +g0 +(g123 +g2 +Ntp32765 +Rp32766 +(dp32767 +g127 +g24491 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp32768 +Rp32769 +(dp32770 +g127 +g750 +sg148 +g162 +sbasbsg163 +Nsg113 +I10067 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp32771 +(lp32772 +g189 +ag0 +(g190 +g2 +Ntp32773 +Rp32774 +(dp32775 +g194 +I01 +sg195 +(lp32776 +g0 +(g197 +g2 +Ntp32777 +Rp32778 +(dp32779 +g201 +g176 +(g177 +(I0 +tp32780 +g179 +tp32781 +Rp32782 +(I1 +(I1 +tp32783 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p32784 +tp32785 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32786 +Rp32787 +(dp32788 +g201 +g176 +(g177 +(I0 +tp32789 +g179 +tp32790 +Rp32791 +(I1 +(I2 +tp32792 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32793 +tp32794 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp32795 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32796 +g179 +tp32797 +Rp32798 +(I1 +(I1 +I1 +I1 +tp32799 +g38 +I00 +S'\xe4\x9f,:\x80\x95\r@' +p32800 +tp32801 +bsg238 +g176 +(g177 +(I0 +tp32802 +g179 +tp32803 +Rp32804 +(I1 +(I1 +I1 +I1 +tp32805 +g38 +I00 +S'"B\x96\x89\xfc,+?' +p32806 +tp32807 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32808 +g179 +tp32809 +Rp32810 +(I1 +(I1 +I1 +I1 +tp32811 +g38 +I00 +S'z\xa7\xf9h\xe4\xf1\xc9?' +p32812 +tp32813 +bsg252 +g260 +sg48 +(lp32814 +g0 +(g52 +g2 +Ntp32815 +Rp32816 +(dp32817 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp32818 +g179 +tp32819 +Rp32820 +(I1 +(I1 +I1 +I1 +tp32821 +g38 +I00 +S'\xc2\x89\xcf\x99\x14>2@' +p32822 +tp32823 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp32824 +g279 +asg113 +I11058 +sg280 +I01 +sbaa(lp32825 +g12 +ag0 +(g190 +g2 +Ntp32826 +Rp32827 +(dp32828 +g194 +I01 +sg195 +(lp32829 +g0 +(g197 +g2 +Ntp32830 +Rp32831 +(dp32832 +g201 +g176 +(g177 +(I0 +tp32833 +g179 +tp32834 +Rp32835 +(I1 +(I1 +tp32836 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p32837 +tp32838 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32839 +Rp32840 +(dp32841 +g201 +g176 +(g177 +(I0 +tp32842 +g179 +tp32843 +Rp32844 +(I1 +(I2 +tp32845 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32846 +tp32847 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp32848 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32849 +g179 +tp32850 +Rp32851 +(I1 +(I1 +I1 +I1 +tp32852 +g38 +I00 +S'#`x\x0c\xa0\xbb\xd6?' +p32853 +tp32854 +bsg238 +g176 +(g177 +(I0 +tp32855 +g179 +tp32856 +Rp32857 +(I1 +(I1 +I1 +I1 +tp32858 +g38 +I00 +S'!c/\x196z\x11?' +p32859 +tp32860 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32861 +g179 +tp32862 +Rp32863 +(I1 +(I1 +I1 +I1 +tp32864 +g38 +I00 +S'\x84\x1e k\xf0\x14\xb0?' +p32865 +tp32866 +bsg252 +g260 +sg48 +(lp32867 +g0 +(g52 +g2 +Ntp32868 +Rp32869 +(dp32870 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp32871 +g179 +tp32872 +Rp32873 +(I1 +(I1 +I1 +I1 +tp32874 +g38 +I00 +S'\xe9*\xa5\x16r\x9d\x16@' +p32875 +tp32876 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp32877 +g334 +asg113 +I11059 +sg280 +I01 +sbaatp32878 +Rp32879 +sg337 +I00 +sg338 +Nsbaa(lp32880 +g340 +ag0 +(g341 +g2 +Ntp32881 +Rp32882 +(dp32883 +g17 +g32758 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp32884 +(lp32885 +g189 +ag0 +(g190 +g2 +Ntp32886 +Rp32887 +(dp32888 +g194 +I01 +sg195 +(lp32889 +g0 +(g197 +g2 +Ntp32890 +Rp32891 +(dp32892 +g201 +g176 +(g177 +(I0 +tp32893 +g179 +tp32894 +Rp32895 +(I1 +(I1 +tp32896 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p32897 +tp32898 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32899 +Rp32900 +(dp32901 +g201 +g176 +(g177 +(I0 +tp32902 +g179 +tp32903 +Rp32904 +(I1 +(I2 +tp32905 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32906 +tp32907 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp32908 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32909 +g179 +tp32910 +Rp32911 +(I1 +(I1 +I1 +I1 +tp32912 +g38 +I00 +S'\xe4\x9f,:\x80\x95\r@' +p32913 +tp32914 +bsg238 +g176 +(g177 +(I0 +tp32915 +g179 +tp32916 +Rp32917 +(I1 +(I1 +I1 +I1 +tp32918 +g38 +I00 +S'"B\x96\x89\xfc,+?' +p32919 +tp32920 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32921 +g179 +tp32922 +Rp32923 +(I1 +(I1 +I1 +I1 +tp32924 +g38 +I00 +S'z\xa7\xf9h\xe4\xf1\xc9?' +p32925 +tp32926 +bsg252 +g260 +sg48 +(lp32927 +g0 +(g52 +g2 +Ntp32928 +Rp32929 +(dp32930 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp32931 +g179 +tp32932 +Rp32933 +(I1 +(I1 +I1 +I1 +tp32934 +g38 +I00 +S'\xc2\x89\xcf\x99\x14>2@' +p32935 +tp32936 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp32937 +g279 +asg113 +I11062 +sg280 +I01 +sbaa(lp32938 +g401 +ag0 +(g190 +g2 +Ntp32939 +Rp32940 +(dp32941 +g194 +I01 +sg195 +(lp32942 +g0 +(g197 +g2 +Ntp32943 +Rp32944 +(dp32945 +g201 +g176 +(g177 +(I0 +tp32946 +g179 +tp32947 +Rp32948 +(I1 +(I1 +tp32949 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p32950 +tp32951 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp32952 +Rp32953 +(dp32954 +g201 +g176 +(g177 +(I0 +tp32955 +g179 +tp32956 +Rp32957 +(I1 +(I2 +tp32958 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p32959 +tp32960 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp32961 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp32962 +g179 +tp32963 +Rp32964 +(I1 +(I1 +I1 +I1 +tp32965 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32966 +tp32967 +bsg238 +g176 +(g177 +(I0 +tp32968 +g179 +tp32969 +Rp32970 +(I1 +(I1 +I1 +I1 +tp32971 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32972 +tp32973 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp32974 +g179 +tp32975 +Rp32976 +(I1 +(I1 +I1 +I1 +tp32977 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32978 +tp32979 +bsg252 +g260 +sg48 +(lp32980 +g0 +(g52 +g2 +Ntp32981 +Rp32982 +(dp32983 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp32984 +g179 +tp32985 +Rp32986 +(I1 +(I1 +I1 +I1 +tp32987 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p32988 +tp32989 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp32990 +g454 +asg113 +I11063 +sg280 +I01 +sbaatp32991 +Rp32992 +sg337 +I00 +sg338 +Nsbaa(lp32993 +g458 +ag0 +(g459 +g2 +Ntp32994 +Rp32995 +(dp32996 +g17 +g32758 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp32997 +(lp32998 +g189 +ag0 +(g190 +g2 +Ntp32999 +Rp33000 +(dp33001 +g194 +I01 +sg195 +(lp33002 +g0 +(g197 +g2 +Ntp33003 +Rp33004 +(dp33005 +g201 +g176 +(g177 +(I0 +tp33006 +g179 +tp33007 +Rp33008 +(I1 +(I1 +tp33009 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p33010 +tp33011 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33012 +Rp33013 +(dp33014 +g201 +g176 +(g177 +(I0 +tp33015 +g179 +tp33016 +Rp33017 +(I1 +(I2 +tp33018 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33019 +tp33020 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp33021 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33022 +g179 +tp33023 +Rp33024 +(I1 +(I1 +I1 +I1 +tp33025 +g38 +I00 +S'\xf1\x05)Yq\x9a\r@' +p33026 +tp33027 +bsg238 +g176 +(g177 +(I0 +tp33028 +g179 +tp33029 +Rp33030 +(I1 +(I1 +I1 +I1 +tp33031 +g38 +I00 +S'c\x16\xf9K\xcbNQ?' +p33032 +tp33033 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33034 +g179 +tp33035 +Rp33036 +(I1 +(I1 +I1 +I1 +tp33037 +g38 +I00 +S"!_'\x99V\xec\xc9?" +p33038 +tp33039 +bsg252 +g513 +sg48 +(lp33040 +g0 +(g52 +g2 +Ntp33041 +Rp33042 +(dp33043 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp33044 +g179 +tp33045 +Rp33046 +(I1 +(I1 +I1 +I1 +tp33047 +g38 +I00 +S'\xe3\xae\xaf\xe3,:2@' +p33048 +tp33049 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp33050 +g527 +asg113 +I11066 +sg280 +I01 +sbaa(lp33051 +g529 +ag0 +(g190 +g2 +Ntp33052 +Rp33053 +(dp33054 +g194 +I01 +sg195 +(lp33055 +g0 +(g197 +g2 +Ntp33056 +Rp33057 +(dp33058 +g201 +g176 +(g177 +(I0 +tp33059 +g179 +tp33060 +Rp33061 +(I1 +(I1 +tp33062 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p33063 +tp33064 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33065 +Rp33066 +(dp33067 +g201 +g176 +(g177 +(I0 +tp33068 +g179 +tp33069 +Rp33070 +(I1 +(I2 +tp33071 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33072 +tp33073 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33074 +Rp33075 +(dp33076 +g201 +g176 +(g177 +(I0 +tp33077 +g179 +tp33078 +Rp33079 +(I1 +(I2 +tp33080 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33081 +tp33082 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp33083 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33084 +g179 +tp33085 +Rp33086 +(I1 +(I1 +I1 +I1 +tp33087 +g38 +I00 +S'\xe8\xd4\x19\x08\x97\x88\xd6?' +p33088 +tp33089 +bsg238 +g176 +(g177 +(I0 +tp33090 +g179 +tp33091 +Rp33092 +(I1 +(I1 +I1 +I1 +tp33093 +g38 +I00 +S'5a\x9f\xc88\xe03?' +p33094 +tp33095 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33096 +g179 +tp33097 +Rp33098 +(I1 +(I1 +I1 +I1 +tp33099 +g38 +I00 +S'\xce\x0f\xae1\x86\xfd\xaf?' +p33100 +tp33101 +bsg252 +g586 +sg48 +(lp33102 +g0 +(g52 +g2 +Ntp33103 +Rp33104 +(dp33105 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp33106 +g179 +tp33107 +Rp33108 +(I1 +(I1 +I1 +I1 +tp33109 +g38 +I00 +S'\x1dc\xeeZB~\x16@' +p33110 +tp33111 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp33112 +g600 +asg113 +I11067 +sg280 +I01 +sbaatp33113 +Rp33114 +sg337 +I00 +sg338 +Nsbaa(lp33115 +g604 +ag0 +(g605 +g2 +Ntp33116 +Rp33117 +(dp33118 +g17 +g32758 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp33119 +(lp33120 +g611 +ag0 +(g190 +g2 +Ntp33121 +Rp33122 +(dp33123 +g194 +I01 +sg195 +(lp33124 +g0 +(g197 +g2 +Ntp33125 +Rp33126 +(dp33127 +g201 +g176 +(g177 +(I0 +tp33128 +g179 +tp33129 +Rp33130 +(I1 +(I1 +tp33131 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p33132 +tp33133 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33134 +Rp33135 +(dp33136 +g201 +g176 +(g177 +(I0 +tp33137 +g179 +tp33138 +Rp33139 +(I1 +(I2 +tp33140 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33141 +tp33142 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp33143 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33144 +g179 +tp33145 +Rp33146 +(I1 +(I1 +I1 +I1 +tp33147 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33148 +tp33149 +bsg238 +g176 +(g177 +(I0 +tp33150 +g179 +tp33151 +Rp33152 +(I1 +(I1 +I1 +I1 +tp33153 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33154 +tp33155 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33156 +g179 +tp33157 +Rp33158 +(I1 +(I1 +I1 +I1 +tp33159 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33160 +tp33161 +bsg252 +g513 +sg48 +(lp33162 +g0 +(g52 +g2 +Ntp33163 +Rp33164 +(dp33165 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp33166 +g179 +tp33167 +Rp33168 +(I1 +(I1 +I1 +I1 +tp33169 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33170 +tp33171 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp33172 +g664 +asg113 +I11070 +sg280 +I01 +sbaa(lp33173 +g666 +ag0 +(g190 +g2 +Ntp33174 +Rp33175 +(dp33176 +g194 +I01 +sg195 +(lp33177 +g0 +(g197 +g2 +Ntp33178 +Rp33179 +(dp33180 +g201 +g176 +(g177 +(I0 +tp33181 +g179 +tp33182 +Rp33183 +(I1 +(I1 +tp33184 +g208 +I00 +S"S'\x00\x00\x00\x00\x00\x00" +p33185 +tp33186 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33187 +Rp33188 +(dp33189 +g201 +g176 +(g177 +(I0 +tp33190 +g179 +tp33191 +Rp33192 +(I1 +(I2 +tp33193 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33194 +tp33195 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp33196 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33197 +g179 +tp33198 +Rp33199 +(I1 +(I1 +I1 +I1 +tp33200 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33201 +tp33202 +bsg238 +g176 +(g177 +(I0 +tp33203 +g179 +tp33204 +Rp33205 +(I1 +(I1 +I1 +I1 +tp33206 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33207 +tp33208 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33209 +g179 +tp33210 +Rp33211 +(I1 +(I1 +I1 +I1 +tp33212 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33213 +tp33214 +bsg252 +g713 +sg48 +(lp33215 +g0 +(g52 +g2 +Ntp33216 +Rp33217 +(dp33218 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp33219 +g179 +tp33220 +Rp33221 +(I1 +(I1 +I1 +I1 +tp33222 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33223 +tp33224 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp33225 +g727 +asg113 +I11071 +sg280 +I01 +sbaatp33226 +Rp33227 +sg337 +I00 +sg338 +Nsbaatp33228 +Rp33229 +aa(lp33230 +I10068 +ag7 +((lp33231 +(lp33232 +g12 +ag0 +(g13 +g2 +Ntp33233 +Rp33234 +(dp33235 +g17 +g0 +(g18 +g2 +Ntp33236 +Rp33237 +(dp33238 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p33239 +sg116 +g0 +(g117 +g2 +Ntp33240 +Rp33241 +(dp33242 +g121 +(lp33243 +g0 +(g123 +g2 +Ntp33244 +Rp33245 +(dp33246 +g127 +g0 +(g128 +g2 +Ntp33247 +Rp33248 +(dp33249 +g23 +g132 +sg133 +(dp33250 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x0b@' +p33251 +tp33252 +Rp33253 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p33254 +sg113 +I94 +sg146 +(lp33255 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp33256 +Rp33257 +(dp33258 +g127 +g0 +(g128 +g2 +Ntp33259 +Rp33260 +(dp33261 +g23 +g132 +sg133 +(dp33262 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x85\xebQ\xb8\x1e\x85\x0b@' +p33263 +tp33264 +Rp33265 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p33266 +sg113 +I95 +sg146 +(lp33267 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10068 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp33268 +(lp33269 +g189 +ag0 +(g190 +g2 +Ntp33270 +Rp33271 +(dp33272 +g194 +I01 +sg195 +(lp33273 +g0 +(g197 +g2 +Ntp33274 +Rp33275 +(dp33276 +g201 +g176 +(g177 +(I0 +tp33277 +g179 +tp33278 +Rp33279 +(I1 +(I1 +tp33280 +g208 +I00 +S"T'\x00\x00\x00\x00\x00\x00" +p33281 +tp33282 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33283 +Rp33284 +(dp33285 +g201 +g176 +(g177 +(I0 +tp33286 +g179 +tp33287 +Rp33288 +(I1 +(I2 +tp33289 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33290 +tp33291 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp33292 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33293 +g179 +tp33294 +Rp33295 +(I1 +(I1 +I1 +I1 +tp33296 +g38 +I00 +S'\xda\x8d4\xa7\xd18G@' +p33297 +tp33298 +bsg238 +g176 +(g177 +(I0 +tp33299 +g179 +tp33300 +Rp33301 +(I1 +(I1 +I1 +I1 +tp33302 +g38 +I00 +S'^\xed\xe6\xa4@JF?' +p33303 +tp33304 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33305 +g179 +tp33306 +Rp33307 +(I1 +(I1 +I1 +I1 +tp33308 +g38 +I00 +S'\x86v\xa8=\x95\xfc\xe6?' +p33309 +tp33310 +bsg252 +g260 +sg48 +(lp33311 +g0 +(g52 +g2 +Ntp33312 +Rp33313 +(dp33314 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp33315 +g179 +tp33316 +Rp33317 +(I1 +(I1 +I1 +I1 +tp33318 +g38 +I00 +S'VsZ\xef\x98)P@' +p33319 +tp33320 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp33321 +g279 +asg113 +I11074 +sg280 +I01 +sbaa(lp33322 +g12 +ag0 +(g190 +g2 +Ntp33323 +Rp33324 +(dp33325 +g194 +I01 +sg195 +(lp33326 +g0 +(g197 +g2 +Ntp33327 +Rp33328 +(dp33329 +g201 +g176 +(g177 +(I0 +tp33330 +g179 +tp33331 +Rp33332 +(I1 +(I1 +tp33333 +g208 +I00 +S"T'\x00\x00\x00\x00\x00\x00" +p33334 +tp33335 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33336 +Rp33337 +(dp33338 +g201 +g176 +(g177 +(I0 +tp33339 +g179 +tp33340 +Rp33341 +(I1 +(I2 +tp33342 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33343 +tp33344 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp33345 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33346 +g179 +tp33347 +Rp33348 +(I1 +(I1 +I1 +I1 +tp33349 +g38 +I00 +S'\xc8\xe1\xcaN@\xddF@' +p33350 +tp33351 +bsg238 +g176 +(g177 +(I0 +tp33352 +g179 +tp33353 +Rp33354 +(I1 +(I1 +I1 +I1 +tp33355 +g38 +I00 +S'\xafd\xc3\xba#\xefM?' +p33356 +tp33357 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33358 +g179 +tp33359 +Rp33360 +(I1 +(I1 +I1 +I1 +tp33361 +g38 +I00 +S'yPZ\xb1\xe4\xce\xe6?' +p33362 +tp33363 +bsg252 +g260 +sg48 +(lp33364 +g0 +(g52 +g2 +Ntp33365 +Rp33366 +(dp33367 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp33368 +g179 +tp33369 +Rp33370 +(I1 +(I1 +I1 +I1 +tp33371 +g38 +I00 +S'\x95\x80\xb3\xccx\tP@' +p33372 +tp33373 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp33374 +g334 +asg113 +I11075 +sg280 +I01 +sbaatp33375 +Rp33376 +sg337 +I00 +sg338 +Nsbaa(lp33377 +g340 +ag0 +(g341 +g2 +Ntp33378 +Rp33379 +(dp33380 +g17 +g33237 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp33381 +(lp33382 +g189 +ag0 +(g190 +g2 +Ntp33383 +Rp33384 +(dp33385 +g194 +I01 +sg195 +(lp33386 +g0 +(g197 +g2 +Ntp33387 +Rp33388 +(dp33389 +g201 +g176 +(g177 +(I0 +tp33390 +g179 +tp33391 +Rp33392 +(I1 +(I1 +tp33393 +g208 +I00 +S"T'\x00\x00\x00\x00\x00\x00" +p33394 +tp33395 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33396 +Rp33397 +(dp33398 +g201 +g176 +(g177 +(I0 +tp33399 +g179 +tp33400 +Rp33401 +(I1 +(I2 +tp33402 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33403 +tp33404 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp33405 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33406 +g179 +tp33407 +Rp33408 +(I1 +(I1 +I1 +I1 +tp33409 +g38 +I00 +S'\xda\x8d4\xa7\xd18G@' +p33410 +tp33411 +bsg238 +g176 +(g177 +(I0 +tp33412 +g179 +tp33413 +Rp33414 +(I1 +(I1 +I1 +I1 +tp33415 +g38 +I00 +S'^\xed\xe6\xa4@JF?' +p33416 +tp33417 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33418 +g179 +tp33419 +Rp33420 +(I1 +(I1 +I1 +I1 +tp33421 +g38 +I00 +S'\x86v\xa8=\x95\xfc\xe6?' +p33422 +tp33423 +bsg252 +g260 +sg48 +(lp33424 +g0 +(g52 +g2 +Ntp33425 +Rp33426 +(dp33427 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp33428 +g179 +tp33429 +Rp33430 +(I1 +(I1 +I1 +I1 +tp33431 +g38 +I00 +S'VsZ\xef\x98)P@' +p33432 +tp33433 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp33434 +g279 +asg113 +I11078 +sg280 +I01 +sbaa(lp33435 +g401 +ag0 +(g190 +g2 +Ntp33436 +Rp33437 +(dp33438 +g194 +I01 +sg195 +(lp33439 +g0 +(g197 +g2 +Ntp33440 +Rp33441 +(dp33442 +g201 +g176 +(g177 +(I0 +tp33443 +g179 +tp33444 +Rp33445 +(I1 +(I1 +tp33446 +g208 +I00 +S"T'\x00\x00\x00\x00\x00\x00" +p33447 +tp33448 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33449 +Rp33450 +(dp33451 +g201 +g176 +(g177 +(I0 +tp33452 +g179 +tp33453 +Rp33454 +(I1 +(I2 +tp33455 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33456 +tp33457 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp33458 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33459 +g179 +tp33460 +Rp33461 +(I1 +(I1 +I1 +I1 +tp33462 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33463 +tp33464 +bsg238 +g176 +(g177 +(I0 +tp33465 +g179 +tp33466 +Rp33467 +(I1 +(I1 +I1 +I1 +tp33468 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33469 +tp33470 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp33471 +g179 +tp33472 +Rp33473 +(I1 +(I1 +I1 +I1 +tp33474 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33475 +tp33476 +bsg252 +g260 +sg48 +(lp33477 +g0 +(g52 +g2 +Ntp33478 +Rp33479 +(dp33480 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp33481 +g179 +tp33482 +Rp33483 +(I1 +(I1 +I1 +I1 +tp33484 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p33485 +tp33486 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp33487 +g454 +asg113 +I11079 +sg280 +I01 +sbaatp33488 +Rp33489 +sg337 +I00 +sg338 +Nsbaa(lp33490 +g458 +ag0 +(g459 +g2 +Ntp33491 +Rp33492 +(dp33493 +g17 +g33237 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp33494 +(lp33495 +g189 +ag0 +(g190 +g2 +Ntp33496 +Rp33497 +(dp33498 +g194 +I01 +sg195 +(lp33499 +g0 +(g197 +g2 +Ntp33500 +Rp33501 +(dp33502 +g201 +g176 +(g177 +(I0 +tp33503 +g179 +tp33504 +Rp33505 +(I1 +(I1 +tp33506 +g208 +I00 +S"T'\x00\x00\x00\x00\x00\x00" +p33507 +tp33508 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp33509 +Rp33510 +(dp33511 +g201 +g176 +(g177 +(I0 +tp33512 +g179 +tp33513 +Rp33514 +(I1 +(I2 +tp33515 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p33516 +tp33517 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp33518 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp33519 +g179 +tp33520 +Rp33521 +(I1 +(I1 +I1 +I1 +tp33522 +g38 +I00 +S']\x8b\x87\xe8\xb9\x881@' +p34086 +tp34087 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp34088 +g600 +asg113 +I11099 +sg280 +I01 +sbaatp34089 +Rp34090 +sg337 +I00 +sg338 +Nsbaa(lp34091 +g604 +ag0 +(g605 +g2 +Ntp34092 +Rp34093 +(dp34094 +g17 +g33734 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34095 +(lp34096 +g611 +ag0 +(g190 +g2 +Ntp34097 +Rp34098 +(dp34099 +g194 +I01 +sg195 +(lp34100 +g0 +(g197 +g2 +Ntp34101 +Rp34102 +(dp34103 +g201 +g176 +(g177 +(I0 +tp34104 +g179 +tp34105 +Rp34106 +(I1 +(I1 +tp34107 +g208 +I00 +S"U'\x00\x00\x00\x00\x00\x00" +p34108 +tp34109 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34110 +Rp34111 +(dp34112 +g201 +g176 +(g177 +(I0 +tp34113 +g179 +tp34114 +Rp34115 +(I1 +(I2 +tp34116 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34117 +tp34118 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp34119 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34120 +g179 +tp34121 +Rp34122 +(I1 +(I1 +I1 +I1 +tp34123 +g38 +I00 +S'm\x117w\x19A\xa1?' +p34124 +tp34125 +bsg238 +g176 +(g177 +(I0 +tp34126 +g179 +tp34127 +Rp34128 +(I1 +(I1 +I1 +I1 +tp34129 +g38 +I00 +S'\x7f\x96a8\xd3\x8c(?' +p34130 +tp34131 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34132 +g179 +tp34133 +Rp34134 +(I1 +(I1 +I1 +I1 +tp34135 +g38 +I00 +S'1\xbf\xdb\x14m\xbb\x93?' +p34136 +tp34137 +bsg252 +g513 +sg48 +(lp34138 +g0 +(g52 +g2 +Ntp34139 +Rp34140 +(dp34141 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp34142 +g179 +tp34143 +Rp34144 +(I1 +(I1 +I1 +I1 +tp34145 +g38 +I00 +S'\xdd\x04Ue\x91\xbf\xfb?' +p34146 +tp34147 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp34148 +g664 +asg113 +I11102 +sg280 +I01 +sbaa(lp34149 +g666 +ag0 +(g190 +g2 +Ntp34150 +Rp34151 +(dp34152 +g194 +I01 +sg195 +(lp34153 +g0 +(g197 +g2 +Ntp34154 +Rp34155 +(dp34156 +g201 +g176 +(g177 +(I0 +tp34157 +g179 +tp34158 +Rp34159 +(I1 +(I1 +tp34160 +g208 +I00 +S"U'\x00\x00\x00\x00\x00\x00" +p34161 +tp34162 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34163 +Rp34164 +(dp34165 +g201 +g176 +(g177 +(I0 +tp34166 +g179 +tp34167 +Rp34168 +(I1 +(I2 +tp34169 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34170 +tp34171 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp34172 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34173 +g179 +tp34174 +Rp34175 +(I1 +(I1 +I1 +I1 +tp34176 +g38 +I00 +S'n\x117w\x19A\xa1?' +p34177 +tp34178 +bsg238 +g176 +(g177 +(I0 +tp34179 +g179 +tp34180 +Rp34181 +(I1 +(I1 +I1 +I1 +tp34182 +g38 +I00 +S'C\x96a8\xd3\x8c(?' +p34183 +tp34184 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34185 +g179 +tp34186 +Rp34187 +(I1 +(I1 +I1 +I1 +tp34188 +g38 +I00 +S'2\xbf\xdb\x14m\xbb\x93?' +p34189 +tp34190 +bsg252 +g713 +sg48 +(lp34191 +g0 +(g52 +g2 +Ntp34192 +Rp34193 +(dp34194 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp34195 +g179 +tp34196 +Rp34197 +(I1 +(I1 +I1 +I1 +tp34198 +g38 +I00 +S'\xde\x04Ue\x91\xbf\xfb?' +p34199 +tp34200 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp34201 +g727 +asg113 +I11103 +sg280 +I01 +sbaatp34202 +Rp34203 +sg337 +I00 +sg338 +Nsbaatp34204 +Rp34205 +aa(lp34206 +I10070 +ag7 +((lp34207 +(lp34208 +g12 +ag0 +(g13 +g2 +Ntp34209 +Rp34210 +(dp34211 +g17 +g0 +(g18 +g2 +Ntp34212 +Rp34213 +(dp34214 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p34215 +sg116 +g0 +(g117 +g2 +Ntp34216 +Rp34217 +(dp34218 +g121 +(lp34219 +g0 +(g123 +g2 +Ntp34220 +Rp34221 +(dp34222 +g127 +g25476 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp34223 +Rp34224 +(dp34225 +g127 +g31796 +sg148 +g162 +sbasbsg163 +Nsg113 +I10070 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34226 +(lp34227 +g189 +ag0 +(g190 +g2 +Ntp34228 +Rp34229 +(dp34230 +g194 +I01 +sg195 +(lp34231 +g0 +(g197 +g2 +Ntp34232 +Rp34233 +(dp34234 +g201 +g176 +(g177 +(I0 +tp34235 +g179 +tp34236 +Rp34237 +(I1 +(I1 +tp34238 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34239 +tp34240 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34241 +Rp34242 +(dp34243 +g201 +g176 +(g177 +(I0 +tp34244 +g179 +tp34245 +Rp34246 +(I1 +(I2 +tp34247 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34248 +tp34249 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34250 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34251 +g179 +tp34252 +Rp34253 +(I1 +(I1 +I1 +I1 +tp34254 +g38 +I00 +S'\x008\xd6\x1a\x87XH@' +p34255 +tp34256 +bsg238 +g176 +(g177 +(I0 +tp34257 +g179 +tp34258 +Rp34259 +(I1 +(I1 +I1 +I1 +tp34260 +g38 +I00 +S'\xfb:\xf6\x04?\xabE?' +p34261 +tp34262 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34263 +g179 +tp34264 +Rp34265 +(I1 +(I1 +I1 +I1 +tp34266 +g38 +I00 +S'\xa5J\xd00R\x89\xe7?' +p34267 +tp34268 +bsg252 +g260 +sg48 +(lp34269 +g0 +(g52 +g2 +Ntp34270 +Rp34271 +(dp34272 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34273 +g179 +tp34274 +Rp34275 +(I1 +(I1 +I1 +I1 +tp34276 +g38 +I00 +S'|tR\xca\x8d\x8cP@' +p34277 +tp34278 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34279 +g279 +asg113 +I11106 +sg280 +I01 +sbaa(lp34280 +g12 +ag0 +(g190 +g2 +Ntp34281 +Rp34282 +(dp34283 +g194 +I01 +sg195 +(lp34284 +g0 +(g197 +g2 +Ntp34285 +Rp34286 +(dp34287 +g201 +g176 +(g177 +(I0 +tp34288 +g179 +tp34289 +Rp34290 +(I1 +(I1 +tp34291 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34292 +tp34293 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34294 +Rp34295 +(dp34296 +g201 +g176 +(g177 +(I0 +tp34297 +g179 +tp34298 +Rp34299 +(I1 +(I2 +tp34300 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34301 +tp34302 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34303 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34304 +g179 +tp34305 +Rp34306 +(I1 +(I1 +I1 +I1 +tp34307 +g38 +I00 +S'\xf1\x9fX\x9c\xc3\xb0J@' +p34308 +tp34309 +bsg238 +g176 +(g177 +(I0 +tp34310 +g179 +tp34311 +Rp34312 +(I1 +(I1 +I1 +I1 +tp34313 +g38 +I00 +S'\x16[\x1b\xad\x85~P?' +p34314 +tp34315 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34316 +g179 +tp34317 +Rp34318 +(I1 +(I1 +I1 +I1 +tp34319 +g38 +I00 +S'G\xd6\x82Z\x8a\xa4\xe8?' +p34320 +tp34321 +bsg252 +g260 +sg48 +(lp34322 +g0 +(g52 +g2 +Ntp34323 +Rp34324 +(dp34325 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34326 +g179 +tp34327 +Rp34328 +(I1 +(I1 +I1 +I1 +tp34329 +g38 +I00 +S'\xaa\xfe\xa3G\xb1SQ@' +p34330 +tp34331 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34332 +g334 +asg113 +I11107 +sg280 +I01 +sbaatp34333 +Rp34334 +sg337 +I00 +sg338 +Nsbaa(lp34335 +g340 +ag0 +(g341 +g2 +Ntp34336 +Rp34337 +(dp34338 +g17 +g34213 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34339 +(lp34340 +g189 +ag0 +(g190 +g2 +Ntp34341 +Rp34342 +(dp34343 +g194 +I01 +sg195 +(lp34344 +g0 +(g197 +g2 +Ntp34345 +Rp34346 +(dp34347 +g201 +g176 +(g177 +(I0 +tp34348 +g179 +tp34349 +Rp34350 +(I1 +(I1 +tp34351 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34352 +tp34353 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34354 +Rp34355 +(dp34356 +g201 +g176 +(g177 +(I0 +tp34357 +g179 +tp34358 +Rp34359 +(I1 +(I2 +tp34360 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34361 +tp34362 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34363 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34364 +g179 +tp34365 +Rp34366 +(I1 +(I1 +I1 +I1 +tp34367 +g38 +I00 +S'\x008\xd6\x1a\x87XH@' +p34368 +tp34369 +bsg238 +g176 +(g177 +(I0 +tp34370 +g179 +tp34371 +Rp34372 +(I1 +(I1 +I1 +I1 +tp34373 +g38 +I00 +S'\xfb:\xf6\x04?\xabE?' +p34374 +tp34375 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34376 +g179 +tp34377 +Rp34378 +(I1 +(I1 +I1 +I1 +tp34379 +g38 +I00 +S'\xa5J\xd00R\x89\xe7?' +p34380 +tp34381 +bsg252 +g260 +sg48 +(lp34382 +g0 +(g52 +g2 +Ntp34383 +Rp34384 +(dp34385 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34386 +g179 +tp34387 +Rp34388 +(I1 +(I1 +I1 +I1 +tp34389 +g38 +I00 +S'|tR\xca\x8d\x8cP@' +p34390 +tp34391 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34392 +g279 +asg113 +I11110 +sg280 +I01 +sbaa(lp34393 +g401 +ag0 +(g190 +g2 +Ntp34394 +Rp34395 +(dp34396 +g194 +I01 +sg195 +(lp34397 +g0 +(g197 +g2 +Ntp34398 +Rp34399 +(dp34400 +g201 +g176 +(g177 +(I0 +tp34401 +g179 +tp34402 +Rp34403 +(I1 +(I1 +tp34404 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34405 +tp34406 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34407 +Rp34408 +(dp34409 +g201 +g176 +(g177 +(I0 +tp34410 +g179 +tp34411 +Rp34412 +(I1 +(I2 +tp34413 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34414 +tp34415 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34416 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34417 +g179 +tp34418 +Rp34419 +(I1 +(I1 +I1 +I1 +tp34420 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34421 +tp34422 +bsg238 +g176 +(g177 +(I0 +tp34423 +g179 +tp34424 +Rp34425 +(I1 +(I1 +I1 +I1 +tp34426 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34427 +tp34428 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34429 +g179 +tp34430 +Rp34431 +(I1 +(I1 +I1 +I1 +tp34432 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34433 +tp34434 +bsg252 +g260 +sg48 +(lp34435 +g0 +(g52 +g2 +Ntp34436 +Rp34437 +(dp34438 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34439 +g179 +tp34440 +Rp34441 +(I1 +(I1 +I1 +I1 +tp34442 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34443 +tp34444 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34445 +g454 +asg113 +I11111 +sg280 +I01 +sbaatp34446 +Rp34447 +sg337 +I00 +sg338 +Nsbaa(lp34448 +g458 +ag0 +(g459 +g2 +Ntp34449 +Rp34450 +(dp34451 +g17 +g34213 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34452 +(lp34453 +g189 +ag0 +(g190 +g2 +Ntp34454 +Rp34455 +(dp34456 +g194 +I01 +sg195 +(lp34457 +g0 +(g197 +g2 +Ntp34458 +Rp34459 +(dp34460 +g201 +g176 +(g177 +(I0 +tp34461 +g179 +tp34462 +Rp34463 +(I1 +(I1 +tp34464 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34465 +tp34466 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34467 +Rp34468 +(dp34469 +g201 +g176 +(g177 +(I0 +tp34470 +g179 +tp34471 +Rp34472 +(I1 +(I2 +tp34473 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34474 +tp34475 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp34476 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34477 +g179 +tp34478 +Rp34479 +(I1 +(I1 +I1 +I1 +tp34480 +g38 +I00 +S'\x9f\xbe\xa0\xb6\xe8]H@' +p34481 +tp34482 +bsg238 +g176 +(g177 +(I0 +tp34483 +g179 +tp34484 +Rp34485 +(I1 +(I1 +I1 +I1 +tp34486 +g38 +I00 +S'\x93\xee\xf1\xf7\x0cfV?' +p34487 +tp34488 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34489 +g179 +tp34490 +Rp34491 +(I1 +(I1 +I1 +I1 +tp34492 +g38 +I00 +S'e\xff\xaci6\x8b\xe7?' +p34493 +tp34494 +bsg252 +g513 +sg48 +(lp34495 +g0 +(g52 +g2 +Ntp34496 +Rp34497 +(dp34498 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp34499 +g179 +tp34500 +Rp34501 +(I1 +(I1 +I1 +I1 +tp34502 +g38 +I00 +S'\x93\xa3MB\xe2\x8dP@' +p34503 +tp34504 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp34505 +g527 +asg113 +I11114 +sg280 +I01 +sbaa(lp34506 +g529 +ag0 +(g190 +g2 +Ntp34507 +Rp34508 +(dp34509 +g194 +I01 +sg195 +(lp34510 +g0 +(g197 +g2 +Ntp34511 +Rp34512 +(dp34513 +g201 +g176 +(g177 +(I0 +tp34514 +g179 +tp34515 +Rp34516 +(I1 +(I1 +tp34517 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34518 +tp34519 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34520 +Rp34521 +(dp34522 +g201 +g176 +(g177 +(I0 +tp34523 +g179 +tp34524 +Rp34525 +(I1 +(I2 +tp34526 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34527 +tp34528 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34529 +Rp34530 +(dp34531 +g201 +g176 +(g177 +(I0 +tp34532 +g179 +tp34533 +Rp34534 +(I1 +(I2 +tp34535 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34536 +tp34537 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp34538 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34539 +g179 +tp34540 +Rp34541 +(I1 +(I1 +I1 +I1 +tp34542 +g38 +I00 +S'TD\x02\x1d\x18\x10J@' +p34543 +tp34544 +bsg238 +g176 +(g177 +(I0 +tp34545 +g179 +tp34546 +Rp34547 +(I1 +(I1 +I1 +I1 +tp34548 +g38 +I00 +S'\\!\x04\xcf\x9d\xa4U?' +p34549 +tp34550 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34551 +g179 +tp34552 +Rp34553 +(I1 +(I1 +I1 +I1 +tp34554 +g38 +I00 +S'9K\xa3\xdc\x90Y\xe8?' +p34555 +tp34556 +bsg252 +g586 +sg48 +(lp34557 +g0 +(g52 +g2 +Ntp34558 +Rp34559 +(dp34560 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp34561 +g179 +tp34562 +Rp34563 +(I1 +(I1 +I1 +I1 +tp34564 +g38 +I00 +S'\xe4\xd0"\xdb\xf9\x1eQ@' +p34565 +tp34566 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp34567 +g600 +asg113 +I11115 +sg280 +I01 +sbaatp34568 +Rp34569 +sg337 +I00 +sg338 +Nsbaa(lp34570 +g604 +ag0 +(g605 +g2 +Ntp34571 +Rp34572 +(dp34573 +g17 +g34213 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34574 +(lp34575 +g611 +ag0 +(g190 +g2 +Ntp34576 +Rp34577 +(dp34578 +g194 +I01 +sg195 +(lp34579 +g0 +(g197 +g2 +Ntp34580 +Rp34581 +(dp34582 +g201 +g176 +(g177 +(I0 +tp34583 +g179 +tp34584 +Rp34585 +(I1 +(I1 +tp34586 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34587 +tp34588 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34589 +Rp34590 +(dp34591 +g201 +g176 +(g177 +(I0 +tp34592 +g179 +tp34593 +Rp34594 +(I1 +(I2 +tp34595 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34596 +tp34597 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp34598 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34599 +g179 +tp34600 +Rp34601 +(I1 +(I1 +I1 +I1 +tp34602 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34603 +tp34604 +bsg238 +g176 +(g177 +(I0 +tp34605 +g179 +tp34606 +Rp34607 +(I1 +(I1 +I1 +I1 +tp34608 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34609 +tp34610 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34611 +g179 +tp34612 +Rp34613 +(I1 +(I1 +I1 +I1 +tp34614 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34615 +tp34616 +bsg252 +g513 +sg48 +(lp34617 +g0 +(g52 +g2 +Ntp34618 +Rp34619 +(dp34620 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp34621 +g179 +tp34622 +Rp34623 +(I1 +(I1 +I1 +I1 +tp34624 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34625 +tp34626 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp34627 +g664 +asg113 +I11118 +sg280 +I01 +sbaa(lp34628 +g666 +ag0 +(g190 +g2 +Ntp34629 +Rp34630 +(dp34631 +g194 +I01 +sg195 +(lp34632 +g0 +(g197 +g2 +Ntp34633 +Rp34634 +(dp34635 +g201 +g176 +(g177 +(I0 +tp34636 +g179 +tp34637 +Rp34638 +(I1 +(I1 +tp34639 +g208 +I00 +S"V'\x00\x00\x00\x00\x00\x00" +p34640 +tp34641 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34642 +Rp34643 +(dp34644 +g201 +g176 +(g177 +(I0 +tp34645 +g179 +tp34646 +Rp34647 +(I1 +(I2 +tp34648 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34649 +tp34650 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp34651 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34652 +g179 +tp34653 +Rp34654 +(I1 +(I1 +I1 +I1 +tp34655 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34656 +tp34657 +bsg238 +g176 +(g177 +(I0 +tp34658 +g179 +tp34659 +Rp34660 +(I1 +(I1 +I1 +I1 +tp34661 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34662 +tp34663 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34664 +g179 +tp34665 +Rp34666 +(I1 +(I1 +I1 +I1 +tp34667 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34668 +tp34669 +bsg252 +g713 +sg48 +(lp34670 +g0 +(g52 +g2 +Ntp34671 +Rp34672 +(dp34673 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp34674 +g179 +tp34675 +Rp34676 +(I1 +(I1 +I1 +I1 +tp34677 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p34678 +tp34679 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp34680 +g727 +asg113 +I11119 +sg280 +I01 +sbaatp34681 +Rp34682 +sg337 +I00 +sg338 +Nsbaatp34683 +Rp34684 +aa(lp34685 +I10071 +ag7 +((lp34686 +(lp34687 +g12 +ag0 +(g13 +g2 +Ntp34688 +Rp34689 +(dp34690 +g17 +g0 +(g18 +g2 +Ntp34691 +Rp34692 +(dp34693 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p34694 +sg116 +g0 +(g117 +g2 +Ntp34695 +Rp34696 +(dp34697 +g121 +(lp34698 +g0 +(g123 +g2 +Ntp34699 +Rp34700 +(dp34701 +g127 +g17144 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp34702 +Rp34703 +(dp34704 +g127 +g8291 +sg148 +g149 +sbasbsg163 +Nsg113 +I10071 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34705 +(lp34706 +g189 +ag0 +(g190 +g2 +Ntp34707 +Rp34708 +(dp34709 +g194 +I01 +sg195 +(lp34710 +g0 +(g197 +g2 +Ntp34711 +Rp34712 +(dp34713 +g201 +g176 +(g177 +(I0 +tp34714 +g179 +tp34715 +Rp34716 +(I1 +(I1 +tp34717 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34718 +tp34719 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34720 +Rp34721 +(dp34722 +g201 +g176 +(g177 +(I0 +tp34723 +g179 +tp34724 +Rp34725 +(I1 +(I2 +tp34726 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34727 +tp34728 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34729 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34730 +g179 +tp34731 +Rp34732 +(I1 +(I1 +I1 +I1 +tp34733 +g38 +I00 +S'eow\x95\x19\x838@' +p34734 +tp34735 +bsg238 +g176 +(g177 +(I0 +tp34736 +g179 +tp34737 +Rp34738 +(I1 +(I1 +I1 +I1 +tp34739 +g38 +I00 +S'[EOE\xb4\x87B?' +p34740 +tp34741 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34742 +g179 +tp34743 +Rp34744 +(I1 +(I1 +I1 +I1 +tp34745 +g38 +I00 +S'r\xb4\x9d\x8c\x00\xb3\xe0?' +p34746 +tp34747 +bsg252 +g260 +sg48 +(lp34748 +g0 +(g52 +g2 +Ntp34749 +Rp34750 +(dp34751 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34752 +g179 +tp34753 +Rp34754 +(I1 +(I1 +I1 +I1 +tp34755 +g38 +I00 +S'\xc1\xc5\xbd\xc5\xb8{G@' +p34756 +tp34757 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34758 +g279 +asg113 +I11122 +sg280 +I01 +sbaa(lp34759 +g12 +ag0 +(g190 +g2 +Ntp34760 +Rp34761 +(dp34762 +g194 +I01 +sg195 +(lp34763 +g0 +(g197 +g2 +Ntp34764 +Rp34765 +(dp34766 +g201 +g176 +(g177 +(I0 +tp34767 +g179 +tp34768 +Rp34769 +(I1 +(I1 +tp34770 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34771 +tp34772 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34773 +Rp34774 +(dp34775 +g201 +g176 +(g177 +(I0 +tp34776 +g179 +tp34777 +Rp34778 +(I1 +(I2 +tp34779 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34780 +tp34781 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34782 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34783 +g179 +tp34784 +Rp34785 +(I1 +(I1 +I1 +I1 +tp34786 +g38 +I00 +S'5\x1b\xf7\xa7 b\x10@' +p34787 +tp34788 +bsg238 +g176 +(g177 +(I0 +tp34789 +g179 +tp34790 +Rp34791 +(I1 +(I1 +I1 +I1 +tp34792 +g38 +I00 +S'\xe40\xc1yGJ0?' +p34793 +tp34794 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34795 +g179 +tp34796 +Rp34797 +(I1 +(I1 +I1 +I1 +tp34798 +g38 +I00 +S'f\x9bg\xf2\xefM\xcb?' +p34799 +tp34800 +bsg252 +g260 +sg48 +(lp34801 +g0 +(g52 +g2 +Ntp34802 +Rp34803 +(dp34804 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34805 +g179 +tp34806 +Rp34807 +(I1 +(I1 +I1 +I1 +tp34808 +g38 +I00 +S'D\xd9p\xb6\xcc23@' +p34809 +tp34810 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34811 +g334 +asg113 +I11123 +sg280 +I01 +sbaatp34812 +Rp34813 +sg337 +I00 +sg338 +Nsbaa(lp34814 +g340 +ag0 +(g341 +g2 +Ntp34815 +Rp34816 +(dp34817 +g17 +g34692 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34818 +(lp34819 +g189 +ag0 +(g190 +g2 +Ntp34820 +Rp34821 +(dp34822 +g194 +I01 +sg195 +(lp34823 +g0 +(g197 +g2 +Ntp34824 +Rp34825 +(dp34826 +g201 +g176 +(g177 +(I0 +tp34827 +g179 +tp34828 +Rp34829 +(I1 +(I1 +tp34830 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34831 +tp34832 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34833 +Rp34834 +(dp34835 +g201 +g176 +(g177 +(I0 +tp34836 +g179 +tp34837 +Rp34838 +(I1 +(I2 +tp34839 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34840 +tp34841 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34842 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34843 +g179 +tp34844 +Rp34845 +(I1 +(I1 +I1 +I1 +tp34846 +g38 +I00 +S'eow\x95\x19\x838@' +p34847 +tp34848 +bsg238 +g176 +(g177 +(I0 +tp34849 +g179 +tp34850 +Rp34851 +(I1 +(I1 +I1 +I1 +tp34852 +g38 +I00 +S'[EOE\xb4\x87B?' +p34853 +tp34854 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34855 +g179 +tp34856 +Rp34857 +(I1 +(I1 +I1 +I1 +tp34858 +g38 +I00 +S'r\xb4\x9d\x8c\x00\xb3\xe0?' +p34859 +tp34860 +bsg252 +g260 +sg48 +(lp34861 +g0 +(g52 +g2 +Ntp34862 +Rp34863 +(dp34864 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34865 +g179 +tp34866 +Rp34867 +(I1 +(I1 +I1 +I1 +tp34868 +g38 +I00 +S'\xc1\xc5\xbd\xc5\xb8{G@' +p34869 +tp34870 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34871 +g279 +asg113 +I11126 +sg280 +I01 +sbaa(lp34872 +g401 +ag0 +(g190 +g2 +Ntp34873 +Rp34874 +(dp34875 +g194 +I01 +sg195 +(lp34876 +g0 +(g197 +g2 +Ntp34877 +Rp34878 +(dp34879 +g201 +g176 +(g177 +(I0 +tp34880 +g179 +tp34881 +Rp34882 +(I1 +(I1 +tp34883 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34884 +tp34885 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34886 +Rp34887 +(dp34888 +g201 +g176 +(g177 +(I0 +tp34889 +g179 +tp34890 +Rp34891 +(I1 +(I2 +tp34892 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34893 +tp34894 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp34895 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34896 +g179 +tp34897 +Rp34898 +(I1 +(I1 +I1 +I1 +tp34899 +g38 +I00 +S'\xe5\xcf=\x1d\x993\xad?' +p34900 +tp34901 +bsg238 +g176 +(g177 +(I0 +tp34902 +g179 +tp34903 +Rp34904 +(I1 +(I1 +I1 +I1 +tp34905 +g38 +I00 +S'\xdcsY\xa66\xf3\n?' +p34906 +tp34907 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34908 +g179 +tp34909 +Rp34910 +(I1 +(I1 +I1 +I1 +tp34911 +g38 +I00 +S')\xff\x0f\xc5\xe7\xc5\x99?' +p34912 +tp34913 +bsg252 +g260 +sg48 +(lp34914 +g0 +(g52 +g2 +Ntp34915 +Rp34916 +(dp34917 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp34918 +g179 +tp34919 +Rp34920 +(I1 +(I1 +I1 +I1 +tp34921 +g38 +I00 +S'i?\x8f\xf6&\x1f\x02@' +p34922 +tp34923 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp34924 +g454 +asg113 +I11127 +sg280 +I01 +sbaatp34925 +Rp34926 +sg337 +I00 +sg338 +Nsbaa(lp34927 +g458 +ag0 +(g459 +g2 +Ntp34928 +Rp34929 +(dp34930 +g17 +g34692 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp34931 +(lp34932 +g189 +ag0 +(g190 +g2 +Ntp34933 +Rp34934 +(dp34935 +g194 +I01 +sg195 +(lp34936 +g0 +(g197 +g2 +Ntp34937 +Rp34938 +(dp34939 +g201 +g176 +(g177 +(I0 +tp34940 +g179 +tp34941 +Rp34942 +(I1 +(I1 +tp34943 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34944 +tp34945 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34946 +Rp34947 +(dp34948 +g201 +g176 +(g177 +(I0 +tp34949 +g179 +tp34950 +Rp34951 +(I1 +(I2 +tp34952 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p34953 +tp34954 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp34955 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp34956 +g179 +tp34957 +Rp34958 +(I1 +(I1 +I1 +I1 +tp34959 +g38 +I00 +S'\xa3\xce\x01\xfc\xd4~8@' +p34960 +tp34961 +bsg238 +g176 +(g177 +(I0 +tp34962 +g179 +tp34963 +Rp34964 +(I1 +(I1 +I1 +I1 +tp34965 +g38 +I00 +S'\xdaF;\xd0|\x88X?' +p34966 +tp34967 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp34968 +g179 +tp34969 +Rp34970 +(I1 +(I1 +I1 +I1 +tp34971 +g38 +I00 +S'\xfae\xecQ4\xb0\xe0?' +p34972 +tp34973 +bsg252 +g513 +sg48 +(lp34974 +g0 +(g52 +g2 +Ntp34975 +Rp34976 +(dp34977 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp34978 +g179 +tp34979 +Rp34980 +(I1 +(I1 +I1 +I1 +tp34981 +g38 +I00 +S'ho4\x93\xc9wG@' +p34982 +tp34983 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp34984 +g527 +asg113 +I11130 +sg280 +I01 +sbaa(lp34985 +g529 +ag0 +(g190 +g2 +Ntp34986 +Rp34987 +(dp34988 +g194 +I01 +sg195 +(lp34989 +g0 +(g197 +g2 +Ntp34990 +Rp34991 +(dp34992 +g201 +g176 +(g177 +(I0 +tp34993 +g179 +tp34994 +Rp34995 +(I1 +(I1 +tp34996 +g208 +I00 +S"W'\x00\x00\x00\x00\x00\x00" +p34997 +tp34998 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp34999 +Rp35000 +(dp35001 +g201 +g176 +(g177 +(I0 +tp35002 +g179 +tp35003 +Rp35004 +(I1 +(I2 +tp35005 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35006 +tp35007 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35008 +Rp35009 +(dp35010 +g201 +g176 +(g177 +(I0 +tp35011 +g179 +tp35012 +Rp35013 +(I1 +(I2 +tp35014 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35015 +tp35016 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp35017 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35018 +g179 +tp35019 +Rp35020 +(I1 +(I1 +I1 +I1 +tp35021 +g38 +I00 +S'\x04\x9a\xada+\xa5\x0b@' +p35022 +tp35023 +bsg238 +g176 +(g177 +(I0 +tp35024 +g179 +tp35025 +Rp35026 +(I1 +(I1 +I1 +I1 +tp35027 +g38 +I00 +S'OE\x07pA\xeb~xS8@' +p35213 +tp35214 +bsg238 +g176 +(g177 +(I0 +tp35215 +g179 +tp35216 +Rp35217 +(I1 +(I1 +I1 +I1 +tp35218 +g38 +I00 +S'sW\xbf7S\x99D?' +p35219 +tp35220 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35221 +g179 +tp35222 +Rp35223 +(I1 +(I1 +I1 +I1 +tp35224 +g38 +I00 +S'n,ZO\xb1\xa2\xe0?' +p35225 +tp35226 +bsg252 +g260 +sg48 +(lp35227 +g0 +(g52 +g2 +Ntp35228 +Rp35229 +(dp35230 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35231 +g179 +tp35232 +Rp35233 +(I1 +(I1 +I1 +I1 +tp35234 +g38 +I00 +S'{\xce\x96W\xc9dG@' +p35235 +tp35236 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35237 +g279 +asg113 +I11138 +sg280 +I01 +sbaa(lp35238 +g12 +ag0 +(g190 +g2 +Ntp35239 +Rp35240 +(dp35241 +g194 +I01 +sg195 +(lp35242 +g0 +(g197 +g2 +Ntp35243 +Rp35244 +(dp35245 +g201 +g176 +(g177 +(I0 +tp35246 +g179 +tp35247 +Rp35248 +(I1 +(I1 +tp35249 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35250 +tp35251 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35252 +Rp35253 +(dp35254 +g201 +g176 +(g177 +(I0 +tp35255 +g179 +tp35256 +Rp35257 +(I1 +(I2 +tp35258 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35259 +tp35260 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35261 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35262 +g179 +tp35263 +Rp35264 +(I1 +(I1 +I1 +I1 +tp35265 +g38 +I00 +S'{\x0cQ/\x9e\xf0\x0e@' +p35266 +tp35267 +bsg238 +g176 +(g177 +(I0 +tp35268 +g179 +tp35269 +Rp35270 +(I1 +(I1 +I1 +I1 +tp35271 +g38 +I00 +S'\x07\x00\x95\xc4\xc8\x052?' +p35272 +tp35273 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35274 +g179 +tp35275 +Rp35276 +(I1 +(I1 +I1 +I1 +tp35277 +g38 +I00 +S'\x12L\xcd7.\x88\xca?' +p35278 +tp35279 +bsg252 +g260 +sg48 +(lp35280 +g0 +(g52 +g2 +Ntp35281 +Rp35282 +(dp35283 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35284 +g179 +tp35285 +Rp35286 +(I1 +(I1 +I1 +I1 +tp35287 +g38 +I00 +S'}Y<\x7f\xc0\xa72@' +p35288 +tp35289 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35290 +g334 +asg113 +I11139 +sg280 +I01 +sbaatp35291 +Rp35292 +sg337 +I00 +sg338 +Nsbaa(lp35293 +g340 +ag0 +(g341 +g2 +Ntp35294 +Rp35295 +(dp35296 +g17 +g35171 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35297 +(lp35298 +g189 +ag0 +(g190 +g2 +Ntp35299 +Rp35300 +(dp35301 +g194 +I01 +sg195 +(lp35302 +g0 +(g197 +g2 +Ntp35303 +Rp35304 +(dp35305 +g201 +g176 +(g177 +(I0 +tp35306 +g179 +tp35307 +Rp35308 +(I1 +(I1 +tp35309 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35310 +tp35311 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35312 +Rp35313 +(dp35314 +g201 +g176 +(g177 +(I0 +tp35315 +g179 +tp35316 +Rp35317 +(I1 +(I2 +tp35318 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35319 +tp35320 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35321 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35322 +g179 +tp35323 +Rp35324 +(I1 +(I1 +I1 +I1 +tp35325 +g38 +I00 +S'\x9e>\xeb~xS8@' +p35326 +tp35327 +bsg238 +g176 +(g177 +(I0 +tp35328 +g179 +tp35329 +Rp35330 +(I1 +(I1 +I1 +I1 +tp35331 +g38 +I00 +S'sW\xbf7S\x99D?' +p35332 +tp35333 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35334 +g179 +tp35335 +Rp35336 +(I1 +(I1 +I1 +I1 +tp35337 +g38 +I00 +S'n,ZO\xb1\xa2\xe0?' +p35338 +tp35339 +bsg252 +g260 +sg48 +(lp35340 +g0 +(g52 +g2 +Ntp35341 +Rp35342 +(dp35343 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35344 +g179 +tp35345 +Rp35346 +(I1 +(I1 +I1 +I1 +tp35347 +g38 +I00 +S'{\xce\x96W\xc9dG@' +p35348 +tp35349 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35350 +g279 +asg113 +I11142 +sg280 +I01 +sbaa(lp35351 +g401 +ag0 +(g190 +g2 +Ntp35352 +Rp35353 +(dp35354 +g194 +I01 +sg195 +(lp35355 +g0 +(g197 +g2 +Ntp35356 +Rp35357 +(dp35358 +g201 +g176 +(g177 +(I0 +tp35359 +g179 +tp35360 +Rp35361 +(I1 +(I1 +tp35362 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35363 +tp35364 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35365 +Rp35366 +(dp35367 +g201 +g176 +(g177 +(I0 +tp35368 +g179 +tp35369 +Rp35370 +(I1 +(I2 +tp35371 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35372 +tp35373 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35374 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35375 +g179 +tp35376 +Rp35377 +(I1 +(I1 +I1 +I1 +tp35378 +g38 +I00 +S'T\xc4f\xa3JC\x9e?' +p35379 +tp35380 +bsg238 +g176 +(g177 +(I0 +tp35381 +g179 +tp35382 +Rp35383 +(I1 +(I1 +I1 +I1 +tp35384 +g38 +I00 +S'Q\xaa\x10\xf3I\t\n?' +p35385 +tp35386 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35387 +g179 +tp35388 +Rp35389 +(I1 +(I1 +I1 +I1 +tp35390 +g38 +I00 +S'\xac\x98\x10\xa5\xbd\x8c\x92?' +p35391 +tp35392 +bsg252 +g260 +sg48 +(lp35393 +g0 +(g52 +g2 +Ntp35394 +Rp35395 +(dp35396 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35397 +g179 +tp35398 +Rp35399 +(I1 +(I1 +I1 +I1 +tp35400 +g38 +I00 +S'\xb2V\x1f\xb0\xea\x15\xfa?' +p35401 +tp35402 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35403 +g454 +asg113 +I11143 +sg280 +I01 +sbaatp35404 +Rp35405 +sg337 +I00 +sg338 +Nsbaa(lp35406 +g458 +ag0 +(g459 +g2 +Ntp35407 +Rp35408 +(dp35409 +g17 +g35171 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35410 +(lp35411 +g189 +ag0 +(g190 +g2 +Ntp35412 +Rp35413 +(dp35414 +g194 +I01 +sg195 +(lp35415 +g0 +(g197 +g2 +Ntp35416 +Rp35417 +(dp35418 +g201 +g176 +(g177 +(I0 +tp35419 +g179 +tp35420 +Rp35421 +(I1 +(I1 +tp35422 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35423 +tp35424 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35425 +Rp35426 +(dp35427 +g201 +g176 +(g177 +(I0 +tp35428 +g179 +tp35429 +Rp35430 +(I1 +(I2 +tp35431 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35432 +tp35433 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp35434 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35435 +g179 +tp35436 +Rp35437 +(I1 +(I1 +I1 +I1 +tp35438 +g38 +I00 +S'Q-\xc8.\xad$8@' +p35439 +tp35440 +bsg238 +g176 +(g177 +(I0 +tp35441 +g179 +tp35442 +Rp35443 +(I1 +(I1 +I1 +I1 +tp35444 +g38 +I00 +S'\x9d\xdc\xa0=T\x80V?' +p35445 +tp35446 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35447 +g179 +tp35448 +Rp35449 +(I1 +(I1 +I1 +I1 +tp35450 +g38 +I00 +S'y\n\xa4J\x9c\x91\xe0?' +p35451 +tp35452 +bsg252 +g513 +sg48 +(lp35453 +g0 +(g52 +g2 +Ntp35454 +Rp35455 +(dp35456 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp35457 +g179 +tp35458 +Rp35459 +(I1 +(I1 +I1 +I1 +tp35460 +g38 +I00 +S'\xba\xae\xf6\xc8\xc3LG@' +p35461 +tp35462 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp35463 +g527 +asg113 +I11146 +sg280 +I01 +sbaa(lp35464 +g529 +ag0 +(g190 +g2 +Ntp35465 +Rp35466 +(dp35467 +g194 +I01 +sg195 +(lp35468 +g0 +(g197 +g2 +Ntp35469 +Rp35470 +(dp35471 +g201 +g176 +(g177 +(I0 +tp35472 +g179 +tp35473 +Rp35474 +(I1 +(I1 +tp35475 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35476 +tp35477 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35478 +Rp35479 +(dp35480 +g201 +g176 +(g177 +(I0 +tp35481 +g179 +tp35482 +Rp35483 +(I1 +(I2 +tp35484 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35485 +tp35486 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35487 +Rp35488 +(dp35489 +g201 +g176 +(g177 +(I0 +tp35490 +g179 +tp35491 +Rp35492 +(I1 +(I2 +tp35493 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35494 +tp35495 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp35496 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35497 +g179 +tp35498 +Rp35499 +(I1 +(I1 +I1 +I1 +tp35500 +g38 +I00 +S'\xeda\xab\xdb\x0b\n\x0b@' +p35501 +tp35502 +bsg238 +g176 +(g177 +(I0 +tp35503 +g179 +tp35504 +Rp35505 +(I1 +(I1 +I1 +I1 +tp35506 +g38 +I00 +S'\x97\xfe\xe5\xe6\xeai@?' +p35507 +tp35508 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35509 +g179 +tp35510 +Rp35511 +(I1 +(I1 +I1 +I1 +tp35512 +g38 +I00 +S'\xd1\x1bP\xab7\xcc\xc8?' +p35513 +tp35514 +bsg252 +g586 +sg48 +(lp35515 +g0 +(g52 +g2 +Ntp35516 +Rp35517 +(dp35518 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp35519 +g179 +tp35520 +Rp35521 +(I1 +(I1 +I1 +I1 +tp35522 +g38 +I00 +S'\x8fSt$\x97o1@' +p35523 +tp35524 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp35525 +g600 +asg113 +I11147 +sg280 +I01 +sbaatp35526 +Rp35527 +sg337 +I00 +sg338 +Nsbaa(lp35528 +g604 +ag0 +(g605 +g2 +Ntp35529 +Rp35530 +(dp35531 +g17 +g35171 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35532 +(lp35533 +g611 +ag0 +(g190 +g2 +Ntp35534 +Rp35535 +(dp35536 +g194 +I01 +sg195 +(lp35537 +g0 +(g197 +g2 +Ntp35538 +Rp35539 +(dp35540 +g201 +g176 +(g177 +(I0 +tp35541 +g179 +tp35542 +Rp35543 +(I1 +(I1 +tp35544 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35545 +tp35546 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35547 +Rp35548 +(dp35549 +g201 +g176 +(g177 +(I0 +tp35550 +g179 +tp35551 +Rp35552 +(I1 +(I2 +tp35553 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35554 +tp35555 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp35556 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35557 +g179 +tp35558 +Rp35559 +(I1 +(I1 +I1 +I1 +tp35560 +g38 +I00 +S'w\xac1U\x9c\xd7\x9e?' +p35561 +tp35562 +bsg238 +g176 +(g177 +(I0 +tp35563 +g179 +tp35564 +Rp35565 +(I1 +(I1 +I1 +I1 +tp35566 +g38 +I00 +S'\xc2\xbf\xb3\xc8N!(?' +p35567 +tp35568 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35569 +g179 +tp35570 +Rp35571 +(I1 +(I1 +I1 +I1 +tp35572 +g38 +I00 +S'cz~x\xec\xa5\x92?' +p35573 +tp35574 +bsg252 +g513 +sg48 +(lp35575 +g0 +(g52 +g2 +Ntp35576 +Rp35577 +(dp35578 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp35579 +g179 +tp35580 +Rp35581 +(I1 +(I1 +I1 +I1 +tp35582 +g38 +I00 +S'\x1b\xdcq\x89T9\xfa?' +p35583 +tp35584 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp35585 +g664 +asg113 +I11150 +sg280 +I01 +sbaa(lp35586 +g666 +ag0 +(g190 +g2 +Ntp35587 +Rp35588 +(dp35589 +g194 +I01 +sg195 +(lp35590 +g0 +(g197 +g2 +Ntp35591 +Rp35592 +(dp35593 +g201 +g176 +(g177 +(I0 +tp35594 +g179 +tp35595 +Rp35596 +(I1 +(I1 +tp35597 +g208 +I00 +S"X'\x00\x00\x00\x00\x00\x00" +p35598 +tp35599 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35600 +Rp35601 +(dp35602 +g201 +g176 +(g177 +(I0 +tp35603 +g179 +tp35604 +Rp35605 +(I1 +(I2 +tp35606 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35607 +tp35608 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp35609 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35610 +g179 +tp35611 +Rp35612 +(I1 +(I1 +I1 +I1 +tp35613 +g38 +I00 +S'w\xac1U\x9c\xd7\x9e?' +p35614 +tp35615 +bsg238 +g176 +(g177 +(I0 +tp35616 +g179 +tp35617 +Rp35618 +(I1 +(I1 +I1 +I1 +tp35619 +g38 +I00 +S'\xc2\xbf\xb3\xc8N!(?' +p35620 +tp35621 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35622 +g179 +tp35623 +Rp35624 +(I1 +(I1 +I1 +I1 +tp35625 +g38 +I00 +S'cz~x\xec\xa5\x92?' +p35626 +tp35627 +bsg252 +g713 +sg48 +(lp35628 +g0 +(g52 +g2 +Ntp35629 +Rp35630 +(dp35631 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp35632 +g179 +tp35633 +Rp35634 +(I1 +(I1 +I1 +I1 +tp35635 +g38 +I00 +S'\x1b\xdcq\x89T9\xfa?' +p35636 +tp35637 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp35638 +g727 +asg113 +I11151 +sg280 +I01 +sbaatp35639 +Rp35640 +sg337 +I00 +sg338 +Nsbaatp35641 +Rp35642 +aa(lp35643 +I10073 +ag7 +((lp35644 +(lp35645 +g12 +ag0 +(g13 +g2 +Ntp35646 +Rp35647 +(dp35648 +g17 +g0 +(g18 +g2 +Ntp35649 +Rp35650 +(dp35651 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p35652 +sg116 +g0 +(g117 +g2 +Ntp35653 +Rp35654 +(dp35655 +g121 +(lp35656 +g0 +(g123 +g2 +Ntp35657 +Rp35658 +(dp35659 +g127 +g2354 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp35660 +Rp35661 +(dp35662 +g127 +g24003 +sg148 +g162 +sbasbsg163 +Nsg113 +I10073 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35663 +(lp35664 +g189 +ag0 +(g190 +g2 +Ntp35665 +Rp35666 +(dp35667 +g194 +I01 +sg195 +(lp35668 +g0 +(g197 +g2 +Ntp35669 +Rp35670 +(dp35671 +g201 +g176 +(g177 +(I0 +tp35672 +g179 +tp35673 +Rp35674 +(I1 +(I1 +tp35675 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35676 +tp35677 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35678 +Rp35679 +(dp35680 +g201 +g176 +(g177 +(I0 +tp35681 +g179 +tp35682 +Rp35683 +(I1 +(I2 +tp35684 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35685 +tp35686 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35687 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35688 +g179 +tp35689 +Rp35690 +(I1 +(I1 +I1 +I1 +tp35691 +g38 +I00 +S'\x13QAD\xdfo8@' +p35692 +tp35693 +bsg238 +g176 +(g177 +(I0 +tp35694 +g179 +tp35695 +Rp35696 +(I1 +(I1 +I1 +I1 +tp35697 +g38 +I00 +S'\x80E\xbdO\xb7\x05C?' +p35698 +tp35699 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35700 +g179 +tp35701 +Rp35702 +(I1 +(I1 +I1 +I1 +tp35703 +g38 +I00 +S'J"\xe9Mo\xac\xe0?' +p35704 +tp35705 +bsg252 +g260 +sg48 +(lp35706 +g0 +(g52 +g2 +Ntp35707 +Rp35708 +(dp35709 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35710 +g179 +tp35711 +Rp35712 +(I1 +(I1 +I1 +I1 +tp35713 +g38 +I00 +S'8\xd8\x8f\x85|rG@' +p35714 +tp35715 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35716 +g279 +asg113 +I11154 +sg280 +I01 +sbaa(lp35717 +g12 +ag0 +(g190 +g2 +Ntp35718 +Rp35719 +(dp35720 +g194 +I01 +sg195 +(lp35721 +g0 +(g197 +g2 +Ntp35722 +Rp35723 +(dp35724 +g201 +g176 +(g177 +(I0 +tp35725 +g179 +tp35726 +Rp35727 +(I1 +(I1 +tp35728 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35729 +tp35730 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35731 +Rp35732 +(dp35733 +g201 +g176 +(g177 +(I0 +tp35734 +g179 +tp35735 +Rp35736 +(I1 +(I2 +tp35737 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35738 +tp35739 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35740 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35741 +g179 +tp35742 +Rp35743 +(I1 +(I1 +I1 +I1 +tp35744 +g38 +I00 +S'h\x96$\xc1h\x83\x0f@' +p35745 +tp35746 +bsg238 +g176 +(g177 +(I0 +tp35747 +g179 +tp35748 +Rp35749 +(I1 +(I1 +I1 +I1 +tp35750 +g38 +I00 +S'\xbd\xc4V\xa3\xd5\xb90?' +p35751 +tp35752 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35753 +g179 +tp35754 +Rp35755 +(I1 +(I1 +I1 +I1 +tp35756 +g38 +I00 +S'\x94\xd1\x99\xe0\xe9\xc6\xca?' +p35757 +tp35758 +bsg252 +g260 +sg48 +(lp35759 +g0 +(g52 +g2 +Ntp35760 +Rp35761 +(dp35762 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35763 +g179 +tp35764 +Rp35765 +(I1 +(I1 +I1 +I1 +tp35766 +g38 +I00 +S"\\'\xecq\xdc\xd32@" +p35767 +tp35768 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35769 +g334 +asg113 +I11155 +sg280 +I01 +sbaatp35770 +Rp35771 +sg337 +I00 +sg338 +Nsbaa(lp35772 +g340 +ag0 +(g341 +g2 +Ntp35773 +Rp35774 +(dp35775 +g17 +g35650 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35776 +(lp35777 +g189 +ag0 +(g190 +g2 +Ntp35778 +Rp35779 +(dp35780 +g194 +I01 +sg195 +(lp35781 +g0 +(g197 +g2 +Ntp35782 +Rp35783 +(dp35784 +g201 +g176 +(g177 +(I0 +tp35785 +g179 +tp35786 +Rp35787 +(I1 +(I1 +tp35788 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35789 +tp35790 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35791 +Rp35792 +(dp35793 +g201 +g176 +(g177 +(I0 +tp35794 +g179 +tp35795 +Rp35796 +(I1 +(I2 +tp35797 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35798 +tp35799 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35800 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35801 +g179 +tp35802 +Rp35803 +(I1 +(I1 +I1 +I1 +tp35804 +g38 +I00 +S'\x13QAD\xdfo8@' +p35805 +tp35806 +bsg238 +g176 +(g177 +(I0 +tp35807 +g179 +tp35808 +Rp35809 +(I1 +(I1 +I1 +I1 +tp35810 +g38 +I00 +S'\x80E\xbdO\xb7\x05C?' +p35811 +tp35812 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35813 +g179 +tp35814 +Rp35815 +(I1 +(I1 +I1 +I1 +tp35816 +g38 +I00 +S'J"\xe9Mo\xac\xe0?' +p35817 +tp35818 +bsg252 +g260 +sg48 +(lp35819 +g0 +(g52 +g2 +Ntp35820 +Rp35821 +(dp35822 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35823 +g179 +tp35824 +Rp35825 +(I1 +(I1 +I1 +I1 +tp35826 +g38 +I00 +S'8\xd8\x8f\x85|rG@' +p35827 +tp35828 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35829 +g279 +asg113 +I11158 +sg280 +I01 +sbaa(lp35830 +g401 +ag0 +(g190 +g2 +Ntp35831 +Rp35832 +(dp35833 +g194 +I01 +sg195 +(lp35834 +g0 +(g197 +g2 +Ntp35835 +Rp35836 +(dp35837 +g201 +g176 +(g177 +(I0 +tp35838 +g179 +tp35839 +Rp35840 +(I1 +(I1 +tp35841 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35842 +tp35843 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35844 +Rp35845 +(dp35846 +g201 +g176 +(g177 +(I0 +tp35847 +g179 +tp35848 +Rp35849 +(I1 +(I2 +tp35850 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35851 +tp35852 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp35853 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35854 +g179 +tp35855 +Rp35856 +(I1 +(I1 +I1 +I1 +tp35857 +g38 +I00 +S'\xfc\x9e\x9d\x9dmR\xa2?' +p35858 +tp35859 +bsg238 +g176 +(g177 +(I0 +tp35860 +g179 +tp35861 +Rp35862 +(I1 +(I1 +I1 +I1 +tp35863 +g38 +I00 +S'$\xff\xden\x84\x81\x08?' +p35864 +tp35865 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35866 +g179 +tp35867 +Rp35868 +(I1 +(I1 +I1 +I1 +tp35869 +g38 +I00 +S'B\x08\x96\x86\xeei\x94?' +p35870 +tp35871 +bsg252 +g260 +sg48 +(lp35872 +g0 +(g52 +g2 +Ntp35873 +Rp35874 +(dp35875 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp35876 +g179 +tp35877 +Rp35878 +(I1 +(I1 +I1 +I1 +tp35879 +g38 +I00 +S'\x9d\xfbBm\xf7\xb4\xfc?' +p35880 +tp35881 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp35882 +g454 +asg113 +I11159 +sg280 +I01 +sbaatp35883 +Rp35884 +sg337 +I00 +sg338 +Nsbaa(lp35885 +g458 +ag0 +(g459 +g2 +Ntp35886 +Rp35887 +(dp35888 +g17 +g35650 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp35889 +(lp35890 +g189 +ag0 +(g190 +g2 +Ntp35891 +Rp35892 +(dp35893 +g194 +I01 +sg195 +(lp35894 +g0 +(g197 +g2 +Ntp35895 +Rp35896 +(dp35897 +g201 +g176 +(g177 +(I0 +tp35898 +g179 +tp35899 +Rp35900 +(I1 +(I1 +tp35901 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35902 +tp35903 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35904 +Rp35905 +(dp35906 +g201 +g176 +(g177 +(I0 +tp35907 +g179 +tp35908 +Rp35909 +(I1 +(I2 +tp35910 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35911 +tp35912 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp35913 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35914 +g179 +tp35915 +Rp35916 +(I1 +(I1 +I1 +I1 +tp35917 +g38 +I00 +S'"\xac,\x93\x0f\x978@' +p35918 +tp35919 +bsg238 +g176 +(g177 +(I0 +tp35920 +g179 +tp35921 +Rp35922 +(I1 +(I1 +I1 +I1 +tp35923 +g38 +I00 +S'\x0b\xe8\xfc8\xf9$V?' +p35924 +tp35925 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35926 +g179 +tp35927 +Rp35928 +(I1 +(I1 +I1 +I1 +tp35929 +g38 +I00 +S"'\xda\xe2\xde\xbe\xb8\xe0?" +p35930 +tp35931 +bsg252 +g513 +sg48 +(lp35932 +g0 +(g52 +g2 +Ntp35933 +Rp35934 +(dp35935 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp35936 +g179 +tp35937 +Rp35938 +(I1 +(I1 +I1 +I1 +tp35939 +g38 +I00 +S'\xc7\x02oi\xcc\x83G@' +p35940 +tp35941 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp35942 +g527 +asg113 +I11162 +sg280 +I01 +sbaa(lp35943 +g529 +ag0 +(g190 +g2 +Ntp35944 +Rp35945 +(dp35946 +g194 +I01 +sg195 +(lp35947 +g0 +(g197 +g2 +Ntp35948 +Rp35949 +(dp35950 +g201 +g176 +(g177 +(I0 +tp35951 +g179 +tp35952 +Rp35953 +(I1 +(I1 +tp35954 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p35955 +tp35956 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35957 +Rp35958 +(dp35959 +g201 +g176 +(g177 +(I0 +tp35960 +g179 +tp35961 +Rp35962 +(I1 +(I2 +tp35963 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35964 +tp35965 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp35966 +Rp35967 +(dp35968 +g201 +g176 +(g177 +(I0 +tp35969 +g179 +tp35970 +Rp35971 +(I1 +(I2 +tp35972 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p35973 +tp35974 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp35975 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp35976 +g179 +tp35977 +Rp35978 +(I1 +(I1 +I1 +I1 +tp35979 +g38 +I00 +S'\xd4Xo\x92\xee\x98\x0b@' +p35980 +tp35981 +bsg238 +g176 +(g177 +(I0 +tp35982 +g179 +tp35983 +Rp35984 +(I1 +(I1 +I1 +I1 +tp35985 +g38 +I00 +S'qf\x94\xc4\xc3BA?' +p35986 +tp35987 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp35988 +g179 +tp35989 +Rp35990 +(I1 +(I1 +I1 +I1 +tp35991 +g38 +I00 +S'\x9e\xc7Ne>\r\xc9?' +p35992 +tp35993 +bsg252 +g586 +sg48 +(lp35994 +g0 +(g52 +g2 +Ntp35995 +Rp35996 +(dp35997 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp35998 +g179 +tp35999 +Rp36000 +(I1 +(I1 +I1 +I1 +tp36001 +g38 +I00 +S'[d;\xdfO\x9d1@' +p36002 +tp36003 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp36004 +g600 +asg113 +I11163 +sg280 +I01 +sbaatp36005 +Rp36006 +sg337 +I00 +sg338 +Nsbaa(lp36007 +g604 +ag0 +(g605 +g2 +Ntp36008 +Rp36009 +(dp36010 +g17 +g35650 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36011 +(lp36012 +g611 +ag0 +(g190 +g2 +Ntp36013 +Rp36014 +(dp36015 +g194 +I01 +sg195 +(lp36016 +g0 +(g197 +g2 +Ntp36017 +Rp36018 +(dp36019 +g201 +g176 +(g177 +(I0 +tp36020 +g179 +tp36021 +Rp36022 +(I1 +(I1 +tp36023 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p36024 +tp36025 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36026 +Rp36027 +(dp36028 +g201 +g176 +(g177 +(I0 +tp36029 +g179 +tp36030 +Rp36031 +(I1 +(I2 +tp36032 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36033 +tp36034 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp36035 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36036 +g179 +tp36037 +Rp36038 +(I1 +(I1 +I1 +I1 +tp36039 +g38 +I00 +S'w\xeb\xf1p\x86f\xa2?' +p36040 +tp36041 +bsg238 +g176 +(g177 +(I0 +tp36042 +g179 +tp36043 +Rp36044 +(I1 +(I1 +I1 +I1 +tp36045 +g38 +I00 +S'wv:\nQC)?' +p36046 +tp36047 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36048 +g179 +tp36049 +Rp36050 +(I1 +(I1 +I1 +I1 +tp36051 +g38 +I00 +S'\x80U57\xaa`\x94?' +p36052 +tp36053 +bsg252 +g513 +sg48 +(lp36054 +g0 +(g52 +g2 +Ntp36055 +Rp36056 +(dp36057 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp36058 +g179 +tp36059 +Rp36060 +(I1 +(I1 +I1 +I1 +tp36061 +g38 +I00 +S'<\x00\xa3]\xef\xa7\xfc?' +p36062 +tp36063 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp36064 +g664 +asg113 +I11166 +sg280 +I01 +sbaa(lp36065 +g666 +ag0 +(g190 +g2 +Ntp36066 +Rp36067 +(dp36068 +g194 +I01 +sg195 +(lp36069 +g0 +(g197 +g2 +Ntp36070 +Rp36071 +(dp36072 +g201 +g176 +(g177 +(I0 +tp36073 +g179 +tp36074 +Rp36075 +(I1 +(I1 +tp36076 +g208 +I00 +S"Y'\x00\x00\x00\x00\x00\x00" +p36077 +tp36078 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36079 +Rp36080 +(dp36081 +g201 +g176 +(g177 +(I0 +tp36082 +g179 +tp36083 +Rp36084 +(I1 +(I2 +tp36085 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36086 +tp36087 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp36088 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36089 +g179 +tp36090 +Rp36091 +(I1 +(I1 +I1 +I1 +tp36092 +g38 +I00 +S'v\xeb\xf1p\x86f\xa2?' +p36093 +tp36094 +bsg238 +g176 +(g177 +(I0 +tp36095 +g179 +tp36096 +Rp36097 +(I1 +(I1 +I1 +I1 +tp36098 +g38 +I00 +S'\xc8u:\nQC)?' +p36099 +tp36100 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36101 +g179 +tp36102 +Rp36103 +(I1 +(I1 +I1 +I1 +tp36104 +g38 +I00 +S'\x81U57\xaa`\x94?' +p36105 +tp36106 +bsg252 +g713 +sg48 +(lp36107 +g0 +(g52 +g2 +Ntp36108 +Rp36109 +(dp36110 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp36111 +g179 +tp36112 +Rp36113 +(I1 +(I1 +I1 +I1 +tp36114 +g38 +I00 +S'>\x00\xa3]\xef\xa7\xfc?' +p36115 +tp36116 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp36117 +g727 +asg113 +I11167 +sg280 +I01 +sbaatp36118 +Rp36119 +sg337 +I00 +sg338 +Nsbaatp36120 +Rp36121 +aa(lp36122 +I10074 +ag7 +((lp36123 +(lp36124 +g12 +ag0 +(g13 +g2 +Ntp36125 +Rp36126 +(dp36127 +g17 +g0 +(g18 +g2 +Ntp36128 +Rp36129 +(dp36130 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p36131 +sg116 +g0 +(g117 +g2 +Ntp36132 +Rp36133 +(dp36134 +g121 +(lp36135 +g0 +(g123 +g2 +Ntp36136 +Rp36137 +(dp36138 +g127 +g0 +(g128 +g2 +Ntp36139 +Rp36140 +(dp36141 +g23 +g132 +sg133 +(dp36142 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x14\xaeG\xe1z\x14\x02@' +p36143 +tp36144 +Rp36145 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p36146 +sg113 +I96 +sg146 +(lp36147 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp36148 +Rp36149 +(dp36150 +g127 +g762 +sg148 +g149 +sbasbsg163 +Nsg113 +I10074 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36151 +(lp36152 +g189 +ag0 +(g190 +g2 +Ntp36153 +Rp36154 +(dp36155 +g194 +I01 +sg195 +(lp36156 +g0 +(g197 +g2 +Ntp36157 +Rp36158 +(dp36159 +g201 +g176 +(g177 +(I0 +tp36160 +g179 +tp36161 +Rp36162 +(I1 +(I1 +tp36163 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36164 +tp36165 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36166 +Rp36167 +(dp36168 +g201 +g176 +(g177 +(I0 +tp36169 +g179 +tp36170 +Rp36171 +(I1 +(I2 +tp36172 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36173 +tp36174 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36175 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36176 +g179 +tp36177 +Rp36178 +(I1 +(I1 +I1 +I1 +tp36179 +g38 +I00 +S'\x19\xfc\xa3N\x0f\xc5\r@' +p36180 +tp36181 +bsg238 +g176 +(g177 +(I0 +tp36182 +g179 +tp36183 +Rp36184 +(I1 +(I1 +I1 +I1 +tp36185 +g38 +I00 +S'\xfcJ\x93\x9dX8)?' +p36186 +tp36187 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36188 +g179 +tp36189 +Rp36190 +(I1 +(I1 +I1 +I1 +tp36191 +g38 +I00 +S'\x8b\xa7\xe27\xc2\x06\xca?' +p36192 +tp36193 +bsg252 +g260 +sg48 +(lp36194 +g0 +(g52 +g2 +Ntp36195 +Rp36196 +(dp36197 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36198 +g179 +tp36199 +Rp36200 +(I1 +(I1 +I1 +I1 +tp36201 +g38 +I00 +S'\xce]K\x8f\xc0L2@' +p36202 +tp36203 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36204 +g279 +asg113 +I11170 +sg280 +I01 +sbaa(lp36205 +g12 +ag0 +(g190 +g2 +Ntp36206 +Rp36207 +(dp36208 +g194 +I01 +sg195 +(lp36209 +g0 +(g197 +g2 +Ntp36210 +Rp36211 +(dp36212 +g201 +g176 +(g177 +(I0 +tp36213 +g179 +tp36214 +Rp36215 +(I1 +(I1 +tp36216 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36217 +tp36218 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36219 +Rp36220 +(dp36221 +g201 +g176 +(g177 +(I0 +tp36222 +g179 +tp36223 +Rp36224 +(I1 +(I2 +tp36225 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36226 +tp36227 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36228 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36229 +g179 +tp36230 +Rp36231 +(I1 +(I1 +I1 +I1 +tp36232 +g38 +I00 +S'y\x0e\x06H\x0e\xc6\xd6?' +p36233 +tp36234 +bsg238 +g176 +(g177 +(I0 +tp36235 +g179 +tp36236 +Rp36237 +(I1 +(I1 +I1 +I1 +tp36238 +g38 +I00 +S'\xa2\xc6\x05\x1dvs\x10?' +p36239 +tp36240 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36241 +g179 +tp36242 +Rp36243 +(I1 +(I1 +I1 +I1 +tp36244 +g38 +I00 +S'z=\x8c\x99\xa6\x18\xb0?' +p36245 +tp36246 +bsg252 +g260 +sg48 +(lp36247 +g0 +(g52 +g2 +Ntp36248 +Rp36249 +(dp36250 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36251 +g179 +tp36252 +Rp36253 +(I1 +(I1 +I1 +I1 +tp36254 +g38 +I00 +S't6\xedG\xaa\xa2\x16@' +p36255 +tp36256 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36257 +g334 +asg113 +I11171 +sg280 +I01 +sbaatp36258 +Rp36259 +sg337 +I00 +sg338 +Nsbaa(lp36260 +g340 +ag0 +(g341 +g2 +Ntp36261 +Rp36262 +(dp36263 +g17 +g36129 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36264 +(lp36265 +g189 +ag0 +(g190 +g2 +Ntp36266 +Rp36267 +(dp36268 +g194 +I01 +sg195 +(lp36269 +g0 +(g197 +g2 +Ntp36270 +Rp36271 +(dp36272 +g201 +g176 +(g177 +(I0 +tp36273 +g179 +tp36274 +Rp36275 +(I1 +(I1 +tp36276 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36277 +tp36278 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36279 +Rp36280 +(dp36281 +g201 +g176 +(g177 +(I0 +tp36282 +g179 +tp36283 +Rp36284 +(I1 +(I2 +tp36285 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36286 +tp36287 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36288 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36289 +g179 +tp36290 +Rp36291 +(I1 +(I1 +I1 +I1 +tp36292 +g38 +I00 +S'\x19\xfc\xa3N\x0f\xc5\r@' +p36293 +tp36294 +bsg238 +g176 +(g177 +(I0 +tp36295 +g179 +tp36296 +Rp36297 +(I1 +(I1 +I1 +I1 +tp36298 +g38 +I00 +S'\xfcJ\x93\x9dX8)?' +p36299 +tp36300 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36301 +g179 +tp36302 +Rp36303 +(I1 +(I1 +I1 +I1 +tp36304 +g38 +I00 +S'\x8b\xa7\xe27\xc2\x06\xca?' +p36305 +tp36306 +bsg252 +g260 +sg48 +(lp36307 +g0 +(g52 +g2 +Ntp36308 +Rp36309 +(dp36310 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36311 +g179 +tp36312 +Rp36313 +(I1 +(I1 +I1 +I1 +tp36314 +g38 +I00 +S'\xce]K\x8f\xc0L2@' +p36315 +tp36316 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36317 +g279 +asg113 +I11174 +sg280 +I01 +sbaa(lp36318 +g401 +ag0 +(g190 +g2 +Ntp36319 +Rp36320 +(dp36321 +g194 +I01 +sg195 +(lp36322 +g0 +(g197 +g2 +Ntp36323 +Rp36324 +(dp36325 +g201 +g176 +(g177 +(I0 +tp36326 +g179 +tp36327 +Rp36328 +(I1 +(I1 +tp36329 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36330 +tp36331 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36332 +Rp36333 +(dp36334 +g201 +g176 +(g177 +(I0 +tp36335 +g179 +tp36336 +Rp36337 +(I1 +(I2 +tp36338 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36339 +tp36340 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36341 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36342 +g179 +tp36343 +Rp36344 +(I1 +(I1 +I1 +I1 +tp36345 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36346 +tp36347 +bsg238 +g176 +(g177 +(I0 +tp36348 +g179 +tp36349 +Rp36350 +(I1 +(I1 +I1 +I1 +tp36351 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36352 +tp36353 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36354 +g179 +tp36355 +Rp36356 +(I1 +(I1 +I1 +I1 +tp36357 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36358 +tp36359 +bsg252 +g260 +sg48 +(lp36360 +g0 +(g52 +g2 +Ntp36361 +Rp36362 +(dp36363 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36364 +g179 +tp36365 +Rp36366 +(I1 +(I1 +I1 +I1 +tp36367 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36368 +tp36369 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36370 +g454 +asg113 +I11175 +sg280 +I01 +sbaatp36371 +Rp36372 +sg337 +I00 +sg338 +Nsbaa(lp36373 +g458 +ag0 +(g459 +g2 +Ntp36374 +Rp36375 +(dp36376 +g17 +g36129 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36377 +(lp36378 +g189 +ag0 +(g190 +g2 +Ntp36379 +Rp36380 +(dp36381 +g194 +I01 +sg195 +(lp36382 +g0 +(g197 +g2 +Ntp36383 +Rp36384 +(dp36385 +g201 +g176 +(g177 +(I0 +tp36386 +g179 +tp36387 +Rp36388 +(I1 +(I1 +tp36389 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36390 +tp36391 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36392 +Rp36393 +(dp36394 +g201 +g176 +(g177 +(I0 +tp36395 +g179 +tp36396 +Rp36397 +(I1 +(I2 +tp36398 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36399 +tp36400 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp36401 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36402 +g179 +tp36403 +Rp36404 +(I1 +(I1 +I1 +I1 +tp36405 +g38 +I00 +S'\xfe\xf3\x0c1\x87\xd6\r@' +p36406 +tp36407 +bsg238 +g176 +(g177 +(I0 +tp36408 +g179 +tp36409 +Rp36410 +(I1 +(I1 +I1 +I1 +tp36411 +g38 +I00 +S',\xb2\x8b\xb1z\xddQ?' +p36412 +tp36413 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36414 +g179 +tp36415 +Rp36416 +(I1 +(I1 +I1 +I1 +tp36417 +g38 +I00 +S'<$\xc2K"\x06\xca?' +p36418 +tp36419 +bsg252 +g513 +sg48 +(lp36420 +g0 +(g52 +g2 +Ntp36421 +Rp36422 +(dp36423 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp36424 +g179 +tp36425 +Rp36426 +(I1 +(I1 +I1 +I1 +tp36427 +g38 +I00 +S'z\x81D\x1dPL2@' +p36428 +tp36429 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp36430 +g527 +asg113 +I11178 +sg280 +I01 +sbaa(lp36431 +g529 +ag0 +(g190 +g2 +Ntp36432 +Rp36433 +(dp36434 +g194 +I01 +sg195 +(lp36435 +g0 +(g197 +g2 +Ntp36436 +Rp36437 +(dp36438 +g201 +g176 +(g177 +(I0 +tp36439 +g179 +tp36440 +Rp36441 +(I1 +(I1 +tp36442 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36443 +tp36444 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36445 +Rp36446 +(dp36447 +g201 +g176 +(g177 +(I0 +tp36448 +g179 +tp36449 +Rp36450 +(I1 +(I2 +tp36451 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36452 +tp36453 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36454 +Rp36455 +(dp36456 +g201 +g176 +(g177 +(I0 +tp36457 +g179 +tp36458 +Rp36459 +(I1 +(I2 +tp36460 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36461 +tp36462 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp36463 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36464 +g179 +tp36465 +Rp36466 +(I1 +(I1 +I1 +I1 +tp36467 +g38 +I00 +S'\xaf8j\xbf\x94\x85\xd6?' +p36468 +tp36469 +bsg238 +g176 +(g177 +(I0 +tp36470 +g179 +tp36471 +Rp36472 +(I1 +(I1 +I1 +I1 +tp36473 +g38 +I00 +S"\x92|\x1d'\x85\x964?" +p36474 +tp36475 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36476 +g179 +tp36477 +Rp36478 +(I1 +(I1 +I1 +I1 +tp36479 +g38 +I00 +S'%\xc7\x9d\xd2\xc1\xfa\xaf?' +p36480 +tp36481 +bsg252 +g586 +sg48 +(lp36482 +g0 +(g52 +g2 +Ntp36483 +Rp36484 +(dp36485 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp36486 +g179 +tp36487 +Rp36488 +(I1 +(I1 +I1 +I1 +tp36489 +g38 +I00 +S'\x06\xf0\x16HP|\x16@' +p36490 +tp36491 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp36492 +g600 +asg113 +I11179 +sg280 +I01 +sbaatp36493 +Rp36494 +sg337 +I00 +sg338 +Nsbaa(lp36495 +g604 +ag0 +(g605 +g2 +Ntp36496 +Rp36497 +(dp36498 +g17 +g36129 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36499 +(lp36500 +g611 +ag0 +(g190 +g2 +Ntp36501 +Rp36502 +(dp36503 +g194 +I01 +sg195 +(lp36504 +g0 +(g197 +g2 +Ntp36505 +Rp36506 +(dp36507 +g201 +g176 +(g177 +(I0 +tp36508 +g179 +tp36509 +Rp36510 +(I1 +(I1 +tp36511 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36512 +tp36513 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36514 +Rp36515 +(dp36516 +g201 +g176 +(g177 +(I0 +tp36517 +g179 +tp36518 +Rp36519 +(I1 +(I2 +tp36520 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36521 +tp36522 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp36523 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36524 +g179 +tp36525 +Rp36526 +(I1 +(I1 +I1 +I1 +tp36527 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36528 +tp36529 +bsg238 +g176 +(g177 +(I0 +tp36530 +g179 +tp36531 +Rp36532 +(I1 +(I1 +I1 +I1 +tp36533 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36534 +tp36535 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36536 +g179 +tp36537 +Rp36538 +(I1 +(I1 +I1 +I1 +tp36539 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36540 +tp36541 +bsg252 +g513 +sg48 +(lp36542 +g0 +(g52 +g2 +Ntp36543 +Rp36544 +(dp36545 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp36546 +g179 +tp36547 +Rp36548 +(I1 +(I1 +I1 +I1 +tp36549 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36550 +tp36551 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp36552 +g664 +asg113 +I11182 +sg280 +I01 +sbaa(lp36553 +g666 +ag0 +(g190 +g2 +Ntp36554 +Rp36555 +(dp36556 +g194 +I01 +sg195 +(lp36557 +g0 +(g197 +g2 +Ntp36558 +Rp36559 +(dp36560 +g201 +g176 +(g177 +(I0 +tp36561 +g179 +tp36562 +Rp36563 +(I1 +(I1 +tp36564 +g208 +I00 +S"Z'\x00\x00\x00\x00\x00\x00" +p36565 +tp36566 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36567 +Rp36568 +(dp36569 +g201 +g176 +(g177 +(I0 +tp36570 +g179 +tp36571 +Rp36572 +(I1 +(I2 +tp36573 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36574 +tp36575 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp36576 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36577 +g179 +tp36578 +Rp36579 +(I1 +(I1 +I1 +I1 +tp36580 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36581 +tp36582 +bsg238 +g176 +(g177 +(I0 +tp36583 +g179 +tp36584 +Rp36585 +(I1 +(I1 +I1 +I1 +tp36586 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36587 +tp36588 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36589 +g179 +tp36590 +Rp36591 +(I1 +(I1 +I1 +I1 +tp36592 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36593 +tp36594 +bsg252 +g713 +sg48 +(lp36595 +g0 +(g52 +g2 +Ntp36596 +Rp36597 +(dp36598 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp36599 +g179 +tp36600 +Rp36601 +(I1 +(I1 +I1 +I1 +tp36602 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p36603 +tp36604 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp36605 +g727 +asg113 +I11183 +sg280 +I01 +sbaatp36606 +Rp36607 +sg337 +I00 +sg338 +Nsbaatp36608 +Rp36609 +aa(lp36610 +I10075 +ag7 +((lp36611 +(lp36612 +g12 +ag0 +(g13 +g2 +Ntp36613 +Rp36614 +(dp36615 +g17 +g0 +(g18 +g2 +Ntp36616 +Rp36617 +(dp36618 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p36619 +sg116 +g0 +(g117 +g2 +Ntp36620 +Rp36621 +(dp36622 +g121 +(lp36623 +g0 +(g123 +g2 +Ntp36624 +Rp36625 +(dp36626 +g127 +g0 +(g128 +g2 +Ntp36627 +Rp36628 +(dp36629 +g23 +g132 +sg133 +(dp36630 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xcd\xcc\xcc\xcc\xcc\xcc\xfc?' +p36631 +tp36632 +Rp36633 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p36634 +sg113 +I97 +sg146 +(lp36635 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp36636 +Rp36637 +(dp36638 +g127 +g0 +(g128 +g2 +Ntp36639 +Rp36640 +(dp36641 +g23 +g132 +sg133 +(dp36642 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xfc?' +p36643 +tp36644 +Rp36645 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p36646 +sg113 +I98 +sg146 +(lp36647 +g138 +asbsg148 +g162 +sbasbsg163 +Nsg113 +I10075 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36648 +(lp36649 +g189 +ag0 +(g190 +g2 +Ntp36650 +Rp36651 +(dp36652 +g194 +I01 +sg195 +(lp36653 +g0 +(g197 +g2 +Ntp36654 +Rp36655 +(dp36656 +g201 +g176 +(g177 +(I0 +tp36657 +g179 +tp36658 +Rp36659 +(I1 +(I1 +tp36660 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36661 +tp36662 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36663 +Rp36664 +(dp36665 +g201 +g176 +(g177 +(I0 +tp36666 +g179 +tp36667 +Rp36668 +(I1 +(I2 +tp36669 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36670 +tp36671 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36672 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36673 +g179 +tp36674 +Rp36675 +(I1 +(I1 +I1 +I1 +tp36676 +g38 +I00 +S'\xd0"a\x81\x91\x828@' +p36677 +tp36678 +bsg238 +g176 +(g177 +(I0 +tp36679 +g179 +tp36680 +Rp36681 +(I1 +(I1 +I1 +I1 +tp36682 +g38 +I00 +S' \x95x\xb3\xf2\xadA?' +p36683 +tp36684 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36685 +g179 +tp36686 +Rp36687 +(I1 +(I1 +I1 +I1 +tp36688 +g38 +I00 +S'\xbf\xb6\x1aR\xd7\xb2\xe0?' +p36689 +tp36690 +bsg252 +g260 +sg48 +(lp36691 +g0 +(g52 +g2 +Ntp36692 +Rp36693 +(dp36694 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36695 +g179 +tp36696 +Rp36697 +(I1 +(I1 +I1 +I1 +tp36698 +g38 +I00 +S'\xfc\x90u\xcb~{G@' +p36699 +tp36700 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36701 +g279 +asg113 +I11186 +sg280 +I01 +sbaa(lp36702 +g12 +ag0 +(g190 +g2 +Ntp36703 +Rp36704 +(dp36705 +g194 +I01 +sg195 +(lp36706 +g0 +(g197 +g2 +Ntp36707 +Rp36708 +(dp36709 +g201 +g176 +(g177 +(I0 +tp36710 +g179 +tp36711 +Rp36712 +(I1 +(I1 +tp36713 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36714 +tp36715 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36716 +Rp36717 +(dp36718 +g201 +g176 +(g177 +(I0 +tp36719 +g179 +tp36720 +Rp36721 +(I1 +(I2 +tp36722 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36723 +tp36724 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36725 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36726 +g179 +tp36727 +Rp36728 +(I1 +(I1 +I1 +I1 +tp36729 +g38 +I00 +S'\xab\\D\x00\xbe\x9c\x11@' +p36730 +tp36731 +bsg238 +g176 +(g177 +(I0 +tp36732 +g179 +tp36733 +Rp36734 +(I1 +(I1 +I1 +I1 +tp36735 +g38 +I00 +S'<\xa1\xc6\x8f\x7f\n0?' +p36736 +tp36737 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36738 +g179 +tp36739 +Rp36740 +(I1 +(I1 +I1 +I1 +tp36741 +g38 +I00 +S'\xbf|\xa2\x8dhO\xcc?' +p36742 +tp36743 +bsg252 +g260 +sg48 +(lp36744 +g0 +(g52 +g2 +Ntp36745 +Rp36746 +(dp36747 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36748 +g179 +tp36749 +Rp36750 +(I1 +(I1 +I1 +I1 +tp36751 +g38 +I00 +S'\xb6?\x96\x83\xd5\xe73@' +p36752 +tp36753 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36754 +g334 +asg113 +I11187 +sg280 +I01 +sbaatp36755 +Rp36756 +sg337 +I00 +sg338 +Nsbaa(lp36757 +g340 +ag0 +(g341 +g2 +Ntp36758 +Rp36759 +(dp36760 +g17 +g36617 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36761 +(lp36762 +g189 +ag0 +(g190 +g2 +Ntp36763 +Rp36764 +(dp36765 +g194 +I01 +sg195 +(lp36766 +g0 +(g197 +g2 +Ntp36767 +Rp36768 +(dp36769 +g201 +g176 +(g177 +(I0 +tp36770 +g179 +tp36771 +Rp36772 +(I1 +(I1 +tp36773 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36774 +tp36775 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36776 +Rp36777 +(dp36778 +g201 +g176 +(g177 +(I0 +tp36779 +g179 +tp36780 +Rp36781 +(I1 +(I2 +tp36782 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36783 +tp36784 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36785 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36786 +g179 +tp36787 +Rp36788 +(I1 +(I1 +I1 +I1 +tp36789 +g38 +I00 +S'\xd0"a\x81\x91\x828@' +p36790 +tp36791 +bsg238 +g176 +(g177 +(I0 +tp36792 +g179 +tp36793 +Rp36794 +(I1 +(I1 +I1 +I1 +tp36795 +g38 +I00 +S' \x95x\xb3\xf2\xadA?' +p36796 +tp36797 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36798 +g179 +tp36799 +Rp36800 +(I1 +(I1 +I1 +I1 +tp36801 +g38 +I00 +S'\xbf\xb6\x1aR\xd7\xb2\xe0?' +p36802 +tp36803 +bsg252 +g260 +sg48 +(lp36804 +g0 +(g52 +g2 +Ntp36805 +Rp36806 +(dp36807 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36808 +g179 +tp36809 +Rp36810 +(I1 +(I1 +I1 +I1 +tp36811 +g38 +I00 +S'\xfc\x90u\xcb~{G@' +p36812 +tp36813 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36814 +g279 +asg113 +I11190 +sg280 +I01 +sbaa(lp36815 +g401 +ag0 +(g190 +g2 +Ntp36816 +Rp36817 +(dp36818 +g194 +I01 +sg195 +(lp36819 +g0 +(g197 +g2 +Ntp36820 +Rp36821 +(dp36822 +g201 +g176 +(g177 +(I0 +tp36823 +g179 +tp36824 +Rp36825 +(I1 +(I1 +tp36826 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36827 +tp36828 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36829 +Rp36830 +(dp36831 +g201 +g176 +(g177 +(I0 +tp36832 +g179 +tp36833 +Rp36834 +(I1 +(I2 +tp36835 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36836 +tp36837 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp36838 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36839 +g179 +tp36840 +Rp36841 +(I1 +(I1 +I1 +I1 +tp36842 +g38 +I00 +S'\xd89\x1aO\xd7\xdd\xb9?' +p36843 +tp36844 +bsg238 +g176 +(g177 +(I0 +tp36845 +g179 +tp36846 +Rp36847 +(I1 +(I1 +I1 +I1 +tp36848 +g38 +I00 +S'$lB\xfc)\x1b\x11?' +p36849 +tp36850 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36851 +g179 +tp36852 +Rp36853 +(I1 +(I1 +I1 +I1 +tp36854 +g38 +I00 +S"\x8e\xb7Or\x03'\xa1?" +p36855 +tp36856 +bsg252 +g260 +sg48 +(lp36857 +g0 +(g52 +g2 +Ntp36858 +Rp36859 +(dp36860 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp36861 +g179 +tp36862 +Rp36863 +(I1 +(I1 +I1 +I1 +tp36864 +g38 +I00 +S'\x1f\x1a\xc0\xd8\xdc\x1e\x08@' +p36865 +tp36866 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp36867 +g454 +asg113 +I11191 +sg280 +I01 +sbaatp36868 +Rp36869 +sg337 +I00 +sg338 +Nsbaa(lp36870 +g458 +ag0 +(g459 +g2 +Ntp36871 +Rp36872 +(dp36873 +g17 +g36617 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36874 +(lp36875 +g189 +ag0 +(g190 +g2 +Ntp36876 +Rp36877 +(dp36878 +g194 +I01 +sg195 +(lp36879 +g0 +(g197 +g2 +Ntp36880 +Rp36881 +(dp36882 +g201 +g176 +(g177 +(I0 +tp36883 +g179 +tp36884 +Rp36885 +(I1 +(I1 +tp36886 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36887 +tp36888 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36889 +Rp36890 +(dp36891 +g201 +g176 +(g177 +(I0 +tp36892 +g179 +tp36893 +Rp36894 +(I1 +(I2 +tp36895 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36896 +tp36897 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp36898 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36899 +g179 +tp36900 +Rp36901 +(I1 +(I1 +I1 +I1 +tp36902 +g38 +I00 +S'\x08\xc7\x1e\x9e{\xad8@' +p36903 +tp36904 +bsg238 +g176 +(g177 +(I0 +tp36905 +g179 +tp36906 +Rp36907 +(I1 +(I1 +I1 +I1 +tp36908 +g38 +I00 +S'>\xb4v\xd1\xceoW?' +p36909 +tp36910 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36911 +g179 +tp36912 +Rp36913 +(I1 +(I1 +I1 +I1 +tp36914 +g38 +I00 +S'\xe9\xd22\xd66\xc0\xe0?' +p36915 +tp36916 +bsg252 +g513 +sg48 +(lp36917 +g0 +(g52 +g2 +Ntp36918 +Rp36919 +(dp36920 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp36921 +g179 +tp36922 +Rp36923 +(I1 +(I1 +I1 +I1 +tp36924 +g38 +I00 +S'\x98x7\x1dM\x8eG@' +p36925 +tp36926 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp36927 +g527 +asg113 +I11194 +sg280 +I01 +sbaa(lp36928 +g529 +ag0 +(g190 +g2 +Ntp36929 +Rp36930 +(dp36931 +g194 +I01 +sg195 +(lp36932 +g0 +(g197 +g2 +Ntp36933 +Rp36934 +(dp36935 +g201 +g176 +(g177 +(I0 +tp36936 +g179 +tp36937 +Rp36938 +(I1 +(I1 +tp36939 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p36940 +tp36941 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36942 +Rp36943 +(dp36944 +g201 +g176 +(g177 +(I0 +tp36945 +g179 +tp36946 +Rp36947 +(I1 +(I2 +tp36948 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36949 +tp36950 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp36951 +Rp36952 +(dp36953 +g201 +g176 +(g177 +(I0 +tp36954 +g179 +tp36955 +Rp36956 +(I1 +(I2 +tp36957 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p36958 +tp36959 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp36960 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp36961 +g179 +tp36962 +Rp36963 +(I1 +(I1 +I1 +I1 +tp36964 +g38 +I00 +S'\xae\x9a\xcf5\xa3\x91\x0c@' +p36965 +tp36966 +bsg238 +g176 +(g177 +(I0 +tp36967 +g179 +tp36968 +Rp36969 +(I1 +(I1 +I1 +I1 +tp36970 +g38 +I00 +S'\x19\xe5E\r\x7fXA?' +p36971 +tp36972 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp36973 +g179 +tp36974 +Rp36975 +(I1 +(I1 +I1 +I1 +tp36976 +g38 +I00 +S'\xa5\xe5\x1ay3}\xc9?' +p36977 +tp36978 +bsg252 +g586 +sg48 +(lp36979 +g0 +(g52 +g2 +Ntp36980 +Rp36981 +(dp36982 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp36983 +g179 +tp36984 +Rp36985 +(I1 +(I1 +I1 +I1 +tp36986 +g38 +I00 +S'x\xe9&1\x08\xec1@' +p36987 +tp36988 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp36989 +g600 +asg113 +I11195 +sg280 +I01 +sbaatp36990 +Rp36991 +sg337 +I00 +sg338 +Nsbaa(lp36992 +g604 +ag0 +(g605 +g2 +Ntp36993 +Rp36994 +(dp36995 +g17 +g36617 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp36996 +(lp36997 +g611 +ag0 +(g190 +g2 +Ntp36998 +Rp36999 +(dp37000 +g194 +I01 +sg195 +(lp37001 +g0 +(g197 +g2 +Ntp37002 +Rp37003 +(dp37004 +g201 +g176 +(g177 +(I0 +tp37005 +g179 +tp37006 +Rp37007 +(I1 +(I1 +tp37008 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p37009 +tp37010 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37011 +Rp37012 +(dp37013 +g201 +g176 +(g177 +(I0 +tp37014 +g179 +tp37015 +Rp37016 +(I1 +(I2 +tp37017 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37018 +tp37019 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp37020 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37021 +g179 +tp37022 +Rp37023 +(I1 +(I1 +I1 +I1 +tp37024 +g38 +I00 +S'H}\xb0\xc0\xdf\x1f\xba?' +p37025 +tp37026 +bsg238 +g176 +(g177 +(I0 +tp37027 +g179 +tp37028 +Rp37029 +(I1 +(I1 +I1 +I1 +tp37030 +g38 +I00 +S'\xce\xc6E\xe2\x9e\xad.?' +p37031 +tp37032 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37033 +g179 +tp37034 +Rp37035 +(I1 +(I1 +I1 +I1 +tp37036 +g38 +I00 +S'\xc4\xba\xc8.\x194\xa1?' +p37037 +tp37038 +bsg252 +g513 +sg48 +(lp37039 +g0 +(g52 +g2 +Ntp37040 +Rp37041 +(dp37042 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp37043 +g179 +tp37044 +Rp37045 +(I1 +(I1 +I1 +I1 +tp37046 +g38 +I00 +S'\xa3F\xcaiC1\x08@' +p37047 +tp37048 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp37049 +g664 +asg113 +I11198 +sg280 +I01 +sbaa(lp37050 +g666 +ag0 +(g190 +g2 +Ntp37051 +Rp37052 +(dp37053 +g194 +I01 +sg195 +(lp37054 +g0 +(g197 +g2 +Ntp37055 +Rp37056 +(dp37057 +g201 +g176 +(g177 +(I0 +tp37058 +g179 +tp37059 +Rp37060 +(I1 +(I1 +tp37061 +g208 +I00 +S"['\x00\x00\x00\x00\x00\x00" +p37062 +tp37063 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37064 +Rp37065 +(dp37066 +g201 +g176 +(g177 +(I0 +tp37067 +g179 +tp37068 +Rp37069 +(I1 +(I2 +tp37070 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37071 +tp37072 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp37073 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37074 +g179 +tp37075 +Rp37076 +(I1 +(I1 +I1 +I1 +tp37077 +g38 +I00 +S'L}\xb0\xc0\xdf\x1f\xba?' +p37078 +tp37079 +bsg238 +g176 +(g177 +(I0 +tp37080 +g179 +tp37081 +Rp37082 +(I1 +(I1 +I1 +I1 +tp37083 +g38 +I00 +S'\x8e\xc7E\xe2\x9e\xad.?' +p37084 +tp37085 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37086 +g179 +tp37087 +Rp37088 +(I1 +(I1 +I1 +I1 +tp37089 +g38 +I00 +S'\xc5\xba\xc8.\x194\xa1?' +p37090 +tp37091 +bsg252 +g713 +sg48 +(lp37092 +g0 +(g52 +g2 +Ntp37093 +Rp37094 +(dp37095 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp37096 +g179 +tp37097 +Rp37098 +(I1 +(I1 +I1 +I1 +tp37099 +g38 +I00 +S'\xa5F\xcaiC1\x08@' +p37100 +tp37101 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp37102 +g727 +asg113 +I11199 +sg280 +I01 +sbaatp37103 +Rp37104 +sg337 +I00 +sg338 +Nsbaatp37105 +Rp37106 +aa(lp37107 +I10076 +ag7 +((lp37108 +(lp37109 +g12 +ag0 +(g13 +g2 +Ntp37110 +Rp37111 +(dp37112 +g17 +g0 +(g18 +g2 +Ntp37113 +Rp37114 +(dp37115 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p37116 +sg116 +g0 +(g117 +g2 +Ntp37117 +Rp37118 +(dp37119 +g121 +(lp37120 +g0 +(g123 +g2 +Ntp37121 +Rp37122 +(dp37123 +g127 +g23518 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp37124 +Rp37125 +(dp37126 +g127 +g20102 +sg148 +g162 +sbasbsg163 +Nsg113 +I10076 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp37127 +(lp37128 +g189 +ag0 +(g190 +g2 +Ntp37129 +Rp37130 +(dp37131 +g194 +I01 +sg195 +(lp37132 +g0 +(g197 +g2 +Ntp37133 +Rp37134 +(dp37135 +g201 +g176 +(g177 +(I0 +tp37136 +g179 +tp37137 +Rp37138 +(I1 +(I1 +tp37139 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37140 +tp37141 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37142 +Rp37143 +(dp37144 +g201 +g176 +(g177 +(I0 +tp37145 +g179 +tp37146 +Rp37147 +(I1 +(I2 +tp37148 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37149 +tp37150 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp37151 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37152 +g179 +tp37153 +Rp37154 +(I1 +(I1 +I1 +I1 +tp37155 +g38 +I00 +S'!/\xa8\xb4A/I@' +p37156 +tp37157 +bsg238 +g176 +(g177 +(I0 +tp37158 +g179 +tp37159 +Rp37160 +(I1 +(I1 +I1 +I1 +tp37161 +g38 +I00 +S'q\x7f\x7f\xfe\xc0\x88G?' +p37162 +tp37163 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37164 +g179 +tp37165 +Rp37166 +(I1 +(I1 +I1 +I1 +tp37167 +g38 +I00 +S'\x04\xf9m\xca4\xf0\xe7?' +p37168 +tp37169 +bsg252 +g260 +sg48 +(lp37170 +g0 +(g52 +g2 +Ntp37171 +Rp37172 +(dp37173 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp37174 +g179 +tp37175 +Rp37176 +(I1 +(I1 +I1 +I1 +tp37177 +g38 +I00 +S'\x17SU\x1e\xe5\xd4P@' +p37178 +tp37179 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp37180 +g279 +asg113 +I11202 +sg280 +I01 +sbaa(lp37181 +g12 +ag0 +(g190 +g2 +Ntp37182 +Rp37183 +(dp37184 +g194 +I01 +sg195 +(lp37185 +g0 +(g197 +g2 +Ntp37186 +Rp37187 +(dp37188 +g201 +g176 +(g177 +(I0 +tp37189 +g179 +tp37190 +Rp37191 +(I1 +(I1 +tp37192 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37193 +tp37194 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37195 +Rp37196 +(dp37197 +g201 +g176 +(g177 +(I0 +tp37198 +g179 +tp37199 +Rp37200 +(I1 +(I2 +tp37201 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37202 +tp37203 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp37204 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37205 +g179 +tp37206 +Rp37207 +(I1 +(I1 +I1 +I1 +tp37208 +g38 +I00 +S'9\x8c\x98w\xc0\xcfM@' +p37209 +tp37210 +bsg238 +g176 +(g177 +(I0 +tp37211 +g179 +tp37212 +Rp37213 +(I1 +(I1 +I1 +I1 +tp37214 +g38 +I00 +S'\x07h\x9f;\xae(S?' +p37215 +tp37216 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37217 +g179 +tp37218 +Rp37219 +(I1 +(I1 +I1 +I1 +tp37220 +g38 +I00 +S'F\x9f3\x83\x15\x0b\xea?' +p37221 +tp37222 +bsg252 +g260 +sg48 +(lp37223 +g0 +(g52 +g2 +Ntp37224 +Rp37225 +(dp37226 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp37227 +g179 +tp37228 +Rp37229 +(I1 +(I1 +I1 +I1 +tp37230 +g38 +I00 +S'\xfdK@ \xcbOR@' +p37231 +tp37232 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp37233 +g334 +asg113 +I11203 +sg280 +I01 +sbaatp37234 +Rp37235 +sg337 +I00 +sg338 +Nsbaa(lp37236 +g340 +ag0 +(g341 +g2 +Ntp37237 +Rp37238 +(dp37239 +g17 +g37114 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp37240 +(lp37241 +g189 +ag0 +(g190 +g2 +Ntp37242 +Rp37243 +(dp37244 +g194 +I01 +sg195 +(lp37245 +g0 +(g197 +g2 +Ntp37246 +Rp37247 +(dp37248 +g201 +g176 +(g177 +(I0 +tp37249 +g179 +tp37250 +Rp37251 +(I1 +(I1 +tp37252 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37253 +tp37254 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37255 +Rp37256 +(dp37257 +g201 +g176 +(g177 +(I0 +tp37258 +g179 +tp37259 +Rp37260 +(I1 +(I2 +tp37261 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37262 +tp37263 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp37264 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37265 +g179 +tp37266 +Rp37267 +(I1 +(I1 +I1 +I1 +tp37268 +g38 +I00 +S'!/\xa8\xb4A/I@' +p37269 +tp37270 +bsg238 +g176 +(g177 +(I0 +tp37271 +g179 +tp37272 +Rp37273 +(I1 +(I1 +I1 +I1 +tp37274 +g38 +I00 +S'q\x7f\x7f\xfe\xc0\x88G?' +p37275 +tp37276 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37277 +g179 +tp37278 +Rp37279 +(I1 +(I1 +I1 +I1 +tp37280 +g38 +I00 +S'\x04\xf9m\xca4\xf0\xe7?' +p37281 +tp37282 +bsg252 +g260 +sg48 +(lp37283 +g0 +(g52 +g2 +Ntp37284 +Rp37285 +(dp37286 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp37287 +g179 +tp37288 +Rp37289 +(I1 +(I1 +I1 +I1 +tp37290 +g38 +I00 +S'\x17SU\x1e\xe5\xd4P@' +p37291 +tp37292 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp37293 +g279 +asg113 +I11206 +sg280 +I01 +sbaa(lp37294 +g401 +ag0 +(g190 +g2 +Ntp37295 +Rp37296 +(dp37297 +g194 +I01 +sg195 +(lp37298 +g0 +(g197 +g2 +Ntp37299 +Rp37300 +(dp37301 +g201 +g176 +(g177 +(I0 +tp37302 +g179 +tp37303 +Rp37304 +(I1 +(I1 +tp37305 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37306 +tp37307 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37308 +Rp37309 +(dp37310 +g201 +g176 +(g177 +(I0 +tp37311 +g179 +tp37312 +Rp37313 +(I1 +(I2 +tp37314 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37315 +tp37316 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp37317 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37318 +g179 +tp37319 +Rp37320 +(I1 +(I1 +I1 +I1 +tp37321 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37322 +tp37323 +bsg238 +g176 +(g177 +(I0 +tp37324 +g179 +tp37325 +Rp37326 +(I1 +(I1 +I1 +I1 +tp37327 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37328 +tp37329 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37330 +g179 +tp37331 +Rp37332 +(I1 +(I1 +I1 +I1 +tp37333 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37334 +tp37335 +bsg252 +g260 +sg48 +(lp37336 +g0 +(g52 +g2 +Ntp37337 +Rp37338 +(dp37339 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp37340 +g179 +tp37341 +Rp37342 +(I1 +(I1 +I1 +I1 +tp37343 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37344 +tp37345 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp37346 +g454 +asg113 +I11207 +sg280 +I01 +sbaatp37347 +Rp37348 +sg337 +I00 +sg338 +Nsbaa(lp37349 +g458 +ag0 +(g459 +g2 +Ntp37350 +Rp37351 +(dp37352 +g17 +g37114 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp37353 +(lp37354 +g189 +ag0 +(g190 +g2 +Ntp37355 +Rp37356 +(dp37357 +g194 +I01 +sg195 +(lp37358 +g0 +(g197 +g2 +Ntp37359 +Rp37360 +(dp37361 +g201 +g176 +(g177 +(I0 +tp37362 +g179 +tp37363 +Rp37364 +(I1 +(I1 +tp37365 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37366 +tp37367 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37368 +Rp37369 +(dp37370 +g201 +g176 +(g177 +(I0 +tp37371 +g179 +tp37372 +Rp37373 +(I1 +(I2 +tp37374 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37375 +tp37376 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp37377 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37378 +g179 +tp37379 +Rp37380 +(I1 +(I1 +I1 +I1 +tp37381 +g38 +I00 +S'\xdd@\x85\xbe\xcbPI@' +p37382 +tp37383 +bsg238 +g176 +(g177 +(I0 +tp37384 +g179 +tp37385 +Rp37386 +(I1 +(I1 +I1 +I1 +tp37387 +g38 +I00 +S'lMV\xd9`;W?' +p37388 +tp37389 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37390 +g179 +tp37391 +Rp37392 +(I1 +(I1 +I1 +I1 +tp37393 +g38 +I00 +S'\x86\x9c\xe9ef\xff\xe7?' +p37394 +tp37395 +bsg252 +g513 +sg48 +(lp37396 +g0 +(g52 +g2 +Ntp37397 +Rp37398 +(dp37399 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp37400 +g179 +tp37401 +Rp37402 +(I1 +(I1 +I1 +I1 +tp37403 +g38 +I00 +S'\x0eB\xa8\xff\x93\xdfP@' +p37404 +tp37405 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp37406 +g527 +asg113 +I11210 +sg280 +I01 +sbaa(lp37407 +g529 +ag0 +(g190 +g2 +Ntp37408 +Rp37409 +(dp37410 +g194 +I01 +sg195 +(lp37411 +g0 +(g197 +g2 +Ntp37412 +Rp37413 +(dp37414 +g201 +g176 +(g177 +(I0 +tp37415 +g179 +tp37416 +Rp37417 +(I1 +(I1 +tp37418 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37419 +tp37420 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37421 +Rp37422 +(dp37423 +g201 +g176 +(g177 +(I0 +tp37424 +g179 +tp37425 +Rp37426 +(I1 +(I2 +tp37427 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37428 +tp37429 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37430 +Rp37431 +(dp37432 +g201 +g176 +(g177 +(I0 +tp37433 +g179 +tp37434 +Rp37435 +(I1 +(I2 +tp37436 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37437 +tp37438 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp37439 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37440 +g179 +tp37441 +Rp37442 +(I1 +(I1 +I1 +I1 +tp37443 +g38 +I00 +S'KnfWN:M@' +p37444 +tp37445 +bsg238 +g176 +(g177 +(I0 +tp37446 +g179 +tp37447 +Rp37448 +(I1 +(I1 +I1 +I1 +tp37449 +g38 +I00 +S'\x90\xfb)\xb1\xa2\x80W?' +p37450 +tp37451 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37452 +g179 +tp37453 +Rp37454 +(I1 +(I1 +I1 +I1 +tp37455 +g38 +I00 +S'\xa6z\x81\xbb(\xc9\xe9?' +p37456 +tp37457 +bsg252 +g586 +sg48 +(lp37458 +g0 +(g52 +g2 +Ntp37459 +Rp37460 +(dp37461 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp37462 +g179 +tp37463 +Rp37464 +(I1 +(I1 +I1 +I1 +tp37465 +g38 +I00 +S'=\n\xd7\xa3p!R@' +p37466 +tp37467 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp37468 +g600 +asg113 +I11211 +sg280 +I01 +sbaatp37469 +Rp37470 +sg337 +I00 +sg338 +Nsbaa(lp37471 +g604 +ag0 +(g605 +g2 +Ntp37472 +Rp37473 +(dp37474 +g17 +g37114 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp37475 +(lp37476 +g611 +ag0 +(g190 +g2 +Ntp37477 +Rp37478 +(dp37479 +g194 +I01 +sg195 +(lp37480 +g0 +(g197 +g2 +Ntp37481 +Rp37482 +(dp37483 +g201 +g176 +(g177 +(I0 +tp37484 +g179 +tp37485 +Rp37486 +(I1 +(I1 +tp37487 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37488 +tp37489 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37490 +Rp37491 +(dp37492 +g201 +g176 +(g177 +(I0 +tp37493 +g179 +tp37494 +Rp37495 +(I1 +(I2 +tp37496 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37497 +tp37498 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp37499 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37500 +g179 +tp37501 +Rp37502 +(I1 +(I1 +I1 +I1 +tp37503 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37504 +tp37505 +bsg238 +g176 +(g177 +(I0 +tp37506 +g179 +tp37507 +Rp37508 +(I1 +(I1 +I1 +I1 +tp37509 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37510 +tp37511 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37512 +g179 +tp37513 +Rp37514 +(I1 +(I1 +I1 +I1 +tp37515 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37516 +tp37517 +bsg252 +g513 +sg48 +(lp37518 +g0 +(g52 +g2 +Ntp37519 +Rp37520 +(dp37521 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp37522 +g179 +tp37523 +Rp37524 +(I1 +(I1 +I1 +I1 +tp37525 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37526 +tp37527 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp37528 +g664 +asg113 +I11214 +sg280 +I01 +sbaa(lp37529 +g666 +ag0 +(g190 +g2 +Ntp37530 +Rp37531 +(dp37532 +g194 +I01 +sg195 +(lp37533 +g0 +(g197 +g2 +Ntp37534 +Rp37535 +(dp37536 +g201 +g176 +(g177 +(I0 +tp37537 +g179 +tp37538 +Rp37539 +(I1 +(I1 +tp37540 +g208 +I00 +S"\\'\x00\x00\x00\x00\x00\x00" +p37541 +tp37542 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37543 +Rp37544 +(dp37545 +g201 +g176 +(g177 +(I0 +tp37546 +g179 +tp37547 +Rp37548 +(I1 +(I2 +tp37549 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37550 +tp37551 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp37552 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37553 +g179 +tp37554 +Rp37555 +(I1 +(I1 +I1 +I1 +tp37556 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37557 +tp37558 +bsg238 +g176 +(g177 +(I0 +tp37559 +g179 +tp37560 +Rp37561 +(I1 +(I1 +I1 +I1 +tp37562 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37563 +tp37564 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp37565 +g179 +tp37566 +Rp37567 +(I1 +(I1 +I1 +I1 +tp37568 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37569 +tp37570 +bsg252 +g713 +sg48 +(lp37571 +g0 +(g52 +g2 +Ntp37572 +Rp37573 +(dp37574 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp37575 +g179 +tp37576 +Rp37577 +(I1 +(I1 +I1 +I1 +tp37578 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p37579 +tp37580 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp37581 +g727 +asg113 +I11215 +sg280 +I01 +sbaatp37582 +Rp37583 +sg337 +I00 +sg338 +Nsbaatp37584 +Rp37585 +aa(lp37586 +I10077 +ag7 +((lp37587 +(lp37588 +g12 +ag0 +(g13 +g2 +Ntp37589 +Rp37590 +(dp37591 +g17 +g0 +(g18 +g2 +Ntp37592 +Rp37593 +(dp37594 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p37595 +sg116 +g0 +(g117 +g2 +Ntp37596 +Rp37597 +(dp37598 +g121 +(lp37599 +g0 +(g123 +g2 +Ntp37600 +Rp37601 +(dp37602 +g127 +g13701 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp37603 +Rp37604 +(dp37605 +g127 +g28877 +sg148 +g149 +sbasbsg163 +Nsg113 +I10077 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp37606 +(lp37607 +g189 +ag0 +(g190 +g2 +Ntp37608 +Rp37609 +(dp37610 +g194 +I01 +sg195 +(lp37611 +g0 +(g197 +g2 +Ntp37612 +Rp37613 +(dp37614 +g201 +g176 +(g177 +(I0 +tp37615 +g179 +tp37616 +Rp37617 +(I1 +(I1 +tp37618 +g208 +I00 +S"]'\x00\x00\x00\x00\x00\x00" +p37619 +tp37620 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp37621 +Rp37622 +(dp37623 +g201 +g176 +(g177 +(I0 +tp37624 +g179 +tp37625 +Rp37626 +(I1 +(I2 +tp37627 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p37628 +tp37629 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp37630 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp37631 +g179 +tp37632 +Rp37633 +(I1 +(I1 +I1 +I1 +tp37634 +g38 +I00 +S'O4\x19\x195^\xbaI\xec1@' +p40846 +tp40847 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp40848 +g600 +asg113 +I11323 +sg280 +I01 +sbaatp40849 +Rp40850 +sg337 +I00 +sg338 +Nsbaa(lp40851 +g604 +ag0 +(g605 +g2 +Ntp40852 +Rp40853 +(dp40854 +g17 +g40494 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp40855 +(lp40856 +g611 +ag0 +(g190 +g2 +Ntp40857 +Rp40858 +(dp40859 +g194 +I01 +sg195 +(lp40860 +g0 +(g197 +g2 +Ntp40861 +Rp40862 +(dp40863 +g201 +g176 +(g177 +(I0 +tp40864 +g179 +tp40865 +Rp40866 +(I1 +(I1 +tp40867 +g208 +I00 +S"c'\x00\x00\x00\x00\x00\x00" +p40868 +tp40869 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp40870 +Rp40871 +(dp40872 +g201 +g176 +(g177 +(I0 +tp40873 +g179 +tp40874 +Rp40875 +(I1 +(I2 +tp40876 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p40877 +tp40878 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp40879 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp40880 +g179 +tp40881 +Rp40882 +(I1 +(I1 +I1 +I1 +tp40883 +g38 +I00 +S'\xfb;\xfa\xdd\xd1\xd9\xbb?' +p40884 +tp40885 +bsg238 +g176 +(g177 +(I0 +tp40886 +g179 +tp40887 +Rp40888 +(I1 +(I1 +I1 +I1 +tp40889 +g38 +I00 +S'\xfc\xc7t\x83\xd9\xb03?' +p40890 +tp40891 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp40892 +g179 +tp40893 +Rp40894 +(I1 +(I1 +I1 +I1 +tp40895 +g38 +I00 +S'F\xcfE\x8e\xec\xbd\xa1?' +p40896 +tp40897 +bsg252 +g513 +sg48 +(lp40898 +g0 +(g52 +g2 +Ntp40899 +Rp40900 +(dp40901 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp40902 +g179 +tp40903 +Rp40904 +(I1 +(I1 +I1 +I1 +tp40905 +g38 +I00 +S'{+\x12\xa8\x14\xf3\x08@' +p40906 +tp40907 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp40908 +g664 +asg113 +I11326 +sg280 +I01 +sbaa(lp40909 +g666 +ag0 +(g190 +g2 +Ntp40910 +Rp40911 +(dp40912 +g194 +I01 +sg195 +(lp40913 +g0 +(g197 +g2 +Ntp40914 +Rp40915 +(dp40916 +g201 +g176 +(g177 +(I0 +tp40917 +g179 +tp40918 +Rp40919 +(I1 +(I1 +tp40920 +g208 +I00 +S"c'\x00\x00\x00\x00\x00\x00" +p40921 +tp40922 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp40923 +Rp40924 +(dp40925 +g201 +g176 +(g177 +(I0 +tp40926 +g179 +tp40927 +Rp40928 +(I1 +(I2 +tp40929 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p40930 +tp40931 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp40932 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp40933 +g179 +tp40934 +Rp40935 +(I1 +(I1 +I1 +I1 +tp40936 +g38 +I00 +S'\xfa;\xfa\xdd\xd1\xd9\xbb?' +p40937 +tp40938 +bsg238 +g176 +(g177 +(I0 +tp40939 +g179 +tp40940 +Rp40941 +(I1 +(I1 +I1 +I1 +tp40942 +g38 +I00 +S'\x1b\xc7t\x83\xd9\xb03?' +p40943 +tp40944 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp40945 +g179 +tp40946 +Rp40947 +(I1 +(I1 +I1 +I1 +tp40948 +g38 +I00 +S'G\xcfE\x8e\xec\xbd\xa1?' +p40949 +tp40950 +bsg252 +g713 +sg48 +(lp40951 +g0 +(g52 +g2 +Ntp40952 +Rp40953 +(dp40954 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp40955 +g179 +tp40956 +Rp40957 +(I1 +(I1 +I1 +I1 +tp40958 +g38 +I00 +S'|+\x12\xa8\x14\xf3\x08@' +p40959 +tp40960 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp40961 +g727 +asg113 +I11327 +sg280 +I01 +sbaatp40962 +Rp40963 +sg337 +I00 +sg338 +Nsbaatp40964 +Rp40965 +aa(lp40966 +I10084 +ag7 +((lp40967 +(lp40968 +g12 +ag0 +(g13 +g2 +Ntp40969 +Rp40970 +(dp40971 +g17 +g0 +(g18 +g2 +Ntp40972 +Rp40973 +(dp40974 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p40975 +sg116 +g0 +(g117 +g2 +Ntp40976 +Rp40977 +(dp40978 +g121 +(lp40979 +g0 +(g123 +g2 +Ntp40980 +Rp40981 +(dp40982 +g127 +g10252 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp40983 +Rp40984 +(dp40985 +g127 +g20090 +sg148 +g149 +sbasbsg163 +Nsg113 +I10084 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp40986 +(lp40987 +g189 +ag0 +(g190 +g2 +Ntp40988 +Rp40989 +(dp40990 +g194 +I01 +sg195 +(lp40991 +g0 +(g197 +g2 +Ntp40992 +Rp40993 +(dp40994 +g201 +g176 +(g177 +(I0 +tp40995 +g179 +tp40996 +Rp40997 +(I1 +(I1 +tp40998 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p40999 +tp41000 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41001 +Rp41002 +(dp41003 +g201 +g176 +(g177 +(I0 +tp41004 +g179 +tp41005 +Rp41006 +(I1 +(I2 +tp41007 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41008 +tp41009 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41010 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41011 +g179 +tp41012 +Rp41013 +(I1 +(I1 +I1 +I1 +tp41014 +g38 +I00 +S'\xf8\x0b\x94V2\rI@' +p41015 +tp41016 +bsg238 +g176 +(g177 +(I0 +tp41017 +g179 +tp41018 +Rp41019 +(I1 +(I1 +I1 +I1 +tp41020 +g38 +I00 +S'\xad\x13:\xa4\xad\x1cF?' +p41021 +tp41022 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41023 +g179 +tp41024 +Rp41025 +(I1 +(I1 +I1 +I1 +tp41026 +g38 +I00 +S'\x90\xba\xd3\x95\x06\xe0\xe7?' +p41027 +tp41028 +bsg252 +g260 +sg48 +(lp41029 +g0 +(g52 +g2 +Ntp41030 +Rp41031 +(dp41032 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41033 +g179 +tp41034 +Rp41035 +(I1 +(I1 +I1 +I1 +tp41036 +g38 +I00 +S'-\xdfX\xa1\x84\xc9P@' +p41037 +tp41038 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41039 +g279 +asg113 +I11330 +sg280 +I01 +sbaa(lp41040 +g12 +ag0 +(g190 +g2 +Ntp41041 +Rp41042 +(dp41043 +g194 +I01 +sg195 +(lp41044 +g0 +(g197 +g2 +Ntp41045 +Rp41046 +(dp41047 +g201 +g176 +(g177 +(I0 +tp41048 +g179 +tp41049 +Rp41050 +(I1 +(I1 +tp41051 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41052 +tp41053 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41054 +Rp41055 +(dp41056 +g201 +g176 +(g177 +(I0 +tp41057 +g179 +tp41058 +Rp41059 +(I1 +(I2 +tp41060 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41061 +tp41062 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41063 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41064 +g179 +tp41065 +Rp41066 +(I1 +(I1 +I1 +I1 +tp41067 +g38 +I00 +S'\x12\x1a\xec0>SM@' +p41068 +tp41069 +bsg238 +g176 +(g177 +(I0 +tp41070 +g179 +tp41071 +Rp41072 +(I1 +(I1 +I1 +I1 +tp41073 +g38 +I00 +S'\x05]_IQaQ?' +p41074 +tp41075 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41076 +g179 +tp41077 +Rp41078 +(I1 +(I1 +I1 +I1 +tp41079 +g38 +I00 +S'W>\xcf\x04\x93\xd4\xe9?' +p41080 +tp41081 +bsg252 +g260 +sg48 +(lp41082 +g0 +(g52 +g2 +Ntp41083 +Rp41084 +(dp41085 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41086 +g179 +tp41087 +Rp41088 +(I1 +(I1 +I1 +I1 +tp41089 +g38 +I00 +S'\xd5\xb7a_w)R@' +p41090 +tp41091 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41092 +g334 +asg113 +I11331 +sg280 +I01 +sbaatp41093 +Rp41094 +sg337 +I00 +sg338 +Nsbaa(lp41095 +g340 +ag0 +(g341 +g2 +Ntp41096 +Rp41097 +(dp41098 +g17 +g40973 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41099 +(lp41100 +g189 +ag0 +(g190 +g2 +Ntp41101 +Rp41102 +(dp41103 +g194 +I01 +sg195 +(lp41104 +g0 +(g197 +g2 +Ntp41105 +Rp41106 +(dp41107 +g201 +g176 +(g177 +(I0 +tp41108 +g179 +tp41109 +Rp41110 +(I1 +(I1 +tp41111 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41112 +tp41113 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41114 +Rp41115 +(dp41116 +g201 +g176 +(g177 +(I0 +tp41117 +g179 +tp41118 +Rp41119 +(I1 +(I2 +tp41120 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41121 +tp41122 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41123 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41124 +g179 +tp41125 +Rp41126 +(I1 +(I1 +I1 +I1 +tp41127 +g38 +I00 +S'\xf8\x0b\x94V2\rI@' +p41128 +tp41129 +bsg238 +g176 +(g177 +(I0 +tp41130 +g179 +tp41131 +Rp41132 +(I1 +(I1 +I1 +I1 +tp41133 +g38 +I00 +S'\xad\x13:\xa4\xad\x1cF?' +p41134 +tp41135 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41136 +g179 +tp41137 +Rp41138 +(I1 +(I1 +I1 +I1 +tp41139 +g38 +I00 +S'\x90\xba\xd3\x95\x06\xe0\xe7?' +p41140 +tp41141 +bsg252 +g260 +sg48 +(lp41142 +g0 +(g52 +g2 +Ntp41143 +Rp41144 +(dp41145 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41146 +g179 +tp41147 +Rp41148 +(I1 +(I1 +I1 +I1 +tp41149 +g38 +I00 +S'-\xdfX\xa1\x84\xc9P@' +p41150 +tp41151 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41152 +g279 +asg113 +I11334 +sg280 +I01 +sbaa(lp41153 +g401 +ag0 +(g190 +g2 +Ntp41154 +Rp41155 +(dp41156 +g194 +I01 +sg195 +(lp41157 +g0 +(g197 +g2 +Ntp41158 +Rp41159 +(dp41160 +g201 +g176 +(g177 +(I0 +tp41161 +g179 +tp41162 +Rp41163 +(I1 +(I1 +tp41164 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41165 +tp41166 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41167 +Rp41168 +(dp41169 +g201 +g176 +(g177 +(I0 +tp41170 +g179 +tp41171 +Rp41172 +(I1 +(I2 +tp41173 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41174 +tp41175 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41176 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41177 +g179 +tp41178 +Rp41179 +(I1 +(I1 +I1 +I1 +tp41180 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41181 +tp41182 +bsg238 +g176 +(g177 +(I0 +tp41183 +g179 +tp41184 +Rp41185 +(I1 +(I1 +I1 +I1 +tp41186 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41187 +tp41188 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41189 +g179 +tp41190 +Rp41191 +(I1 +(I1 +I1 +I1 +tp41192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41193 +tp41194 +bsg252 +g260 +sg48 +(lp41195 +g0 +(g52 +g2 +Ntp41196 +Rp41197 +(dp41198 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41199 +g179 +tp41200 +Rp41201 +(I1 +(I1 +I1 +I1 +tp41202 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41203 +tp41204 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41205 +g454 +asg113 +I11335 +sg280 +I01 +sbaatp41206 +Rp41207 +sg337 +I00 +sg338 +Nsbaa(lp41208 +g458 +ag0 +(g459 +g2 +Ntp41209 +Rp41210 +(dp41211 +g17 +g40973 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41212 +(lp41213 +g189 +ag0 +(g190 +g2 +Ntp41214 +Rp41215 +(dp41216 +g194 +I01 +sg195 +(lp41217 +g0 +(g197 +g2 +Ntp41218 +Rp41219 +(dp41220 +g201 +g176 +(g177 +(I0 +tp41221 +g179 +tp41222 +Rp41223 +(I1 +(I1 +tp41224 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41225 +tp41226 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41227 +Rp41228 +(dp41229 +g201 +g176 +(g177 +(I0 +tp41230 +g179 +tp41231 +Rp41232 +(I1 +(I2 +tp41233 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41234 +tp41235 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp41236 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41237 +g179 +tp41238 +Rp41239 +(I1 +(I1 +I1 +I1 +tp41240 +g38 +I00 +S'\xb2\xe4e\x04\xa9\xfaH@' +p41241 +tp41242 +bsg238 +g176 +(g177 +(I0 +tp41243 +g179 +tp41244 +Rp41245 +(I1 +(I1 +I1 +I1 +tp41246 +g38 +I00 +S's5\xfe-\x8f:T?' +p41247 +tp41248 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41249 +g179 +tp41250 +Rp41251 +(I1 +(I1 +I1 +I1 +tp41252 +g38 +I00 +S'\xa8\xf6G\xa1\xa9\xd6\xe7?' +p41253 +tp41254 +bsg252 +g513 +sg48 +(lp41255 +g0 +(g52 +g2 +Ntp41256 +Rp41257 +(dp41258 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp41259 +g179 +tp41260 +Rp41261 +(I1 +(I1 +I1 +I1 +tp41262 +g38 +I00 +S'n\x99fE\xef\xc2P@' +p41263 +tp41264 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp41265 +g527 +asg113 +I11338 +sg280 +I01 +sbaa(lp41266 +g529 +ag0 +(g190 +g2 +Ntp41267 +Rp41268 +(dp41269 +g194 +I01 +sg195 +(lp41270 +g0 +(g197 +g2 +Ntp41271 +Rp41272 +(dp41273 +g201 +g176 +(g177 +(I0 +tp41274 +g179 +tp41275 +Rp41276 +(I1 +(I1 +tp41277 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41278 +tp41279 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41280 +Rp41281 +(dp41282 +g201 +g176 +(g177 +(I0 +tp41283 +g179 +tp41284 +Rp41285 +(I1 +(I2 +tp41286 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41287 +tp41288 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41289 +Rp41290 +(dp41291 +g201 +g176 +(g177 +(I0 +tp41292 +g179 +tp41293 +Rp41294 +(I1 +(I2 +tp41295 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41296 +tp41297 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp41298 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41299 +g179 +tp41300 +Rp41301 +(I1 +(I1 +I1 +I1 +tp41302 +g38 +I00 +S')d\xa5Q\x1a\x99L@' +p41303 +tp41304 +bsg238 +g176 +(g177 +(I0 +tp41305 +g179 +tp41306 +Rp41307 +(I1 +(I1 +I1 +I1 +tp41308 +g38 +I00 +S'_ \xf5\xd5h4V?' +p41309 +tp41310 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41311 +g179 +tp41312 +Rp41313 +(I1 +(I1 +I1 +I1 +tp41314 +g38 +I00 +S'\x91\x193:\xbe\x81\xe9?' +p41315 +tp41316 +bsg252 +g586 +sg48 +(lp41317 +g0 +(g52 +g2 +Ntp41318 +Rp41319 +(dp41320 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp41321 +g179 +tp41322 +Rp41323 +(I1 +(I1 +I1 +I1 +tp41324 +g38 +I00 +S'\xfa\xed\xeb\xc09\xefQ@' +p41325 +tp41326 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp41327 +g600 +asg113 +I11339 +sg280 +I01 +sbaatp41328 +Rp41329 +sg337 +I00 +sg338 +Nsbaa(lp41330 +g604 +ag0 +(g605 +g2 +Ntp41331 +Rp41332 +(dp41333 +g17 +g40973 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41334 +(lp41335 +g611 +ag0 +(g190 +g2 +Ntp41336 +Rp41337 +(dp41338 +g194 +I01 +sg195 +(lp41339 +g0 +(g197 +g2 +Ntp41340 +Rp41341 +(dp41342 +g201 +g176 +(g177 +(I0 +tp41343 +g179 +tp41344 +Rp41345 +(I1 +(I1 +tp41346 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41347 +tp41348 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41349 +Rp41350 +(dp41351 +g201 +g176 +(g177 +(I0 +tp41352 +g179 +tp41353 +Rp41354 +(I1 +(I2 +tp41355 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41356 +tp41357 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp41358 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41359 +g179 +tp41360 +Rp41361 +(I1 +(I1 +I1 +I1 +tp41362 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41363 +tp41364 +bsg238 +g176 +(g177 +(I0 +tp41365 +g179 +tp41366 +Rp41367 +(I1 +(I1 +I1 +I1 +tp41368 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41369 +tp41370 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41371 +g179 +tp41372 +Rp41373 +(I1 +(I1 +I1 +I1 +tp41374 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41375 +tp41376 +bsg252 +g513 +sg48 +(lp41377 +g0 +(g52 +g2 +Ntp41378 +Rp41379 +(dp41380 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp41381 +g179 +tp41382 +Rp41383 +(I1 +(I1 +I1 +I1 +tp41384 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41385 +tp41386 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp41387 +g664 +asg113 +I11342 +sg280 +I01 +sbaa(lp41388 +g666 +ag0 +(g190 +g2 +Ntp41389 +Rp41390 +(dp41391 +g194 +I01 +sg195 +(lp41392 +g0 +(g197 +g2 +Ntp41393 +Rp41394 +(dp41395 +g201 +g176 +(g177 +(I0 +tp41396 +g179 +tp41397 +Rp41398 +(I1 +(I1 +tp41399 +g208 +I00 +S"d'\x00\x00\x00\x00\x00\x00" +p41400 +tp41401 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41402 +Rp41403 +(dp41404 +g201 +g176 +(g177 +(I0 +tp41405 +g179 +tp41406 +Rp41407 +(I1 +(I2 +tp41408 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41409 +tp41410 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp41411 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41412 +g179 +tp41413 +Rp41414 +(I1 +(I1 +I1 +I1 +tp41415 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41416 +tp41417 +bsg238 +g176 +(g177 +(I0 +tp41418 +g179 +tp41419 +Rp41420 +(I1 +(I1 +I1 +I1 +tp41421 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41422 +tp41423 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41424 +g179 +tp41425 +Rp41426 +(I1 +(I1 +I1 +I1 +tp41427 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41428 +tp41429 +bsg252 +g713 +sg48 +(lp41430 +g0 +(g52 +g2 +Ntp41431 +Rp41432 +(dp41433 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp41434 +g179 +tp41435 +Rp41436 +(I1 +(I1 +I1 +I1 +tp41437 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p41438 +tp41439 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp41440 +g727 +asg113 +I11343 +sg280 +I01 +sbaatp41441 +Rp41442 +sg337 +I00 +sg338 +Nsbaatp41443 +Rp41444 +aa(lp41445 +I10085 +ag7 +((lp41446 +(lp41447 +g12 +ag0 +(g13 +g2 +Ntp41448 +Rp41449 +(dp41450 +g17 +g0 +(g18 +g2 +Ntp41451 +Rp41452 +(dp41453 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p41454 +sg116 +g0 +(g117 +g2 +Ntp41455 +Rp41456 +(dp41457 +g121 +(lp41458 +g0 +(g123 +g2 +Ntp41459 +Rp41460 +(dp41461 +g127 +g11731 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp41462 +Rp41463 +(dp41464 +g127 +g0 +(g128 +g2 +Ntp41465 +Rp41466 +(dp41467 +g23 +g132 +sg133 +(dp41468 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\xd0?' +p41469 +tp41470 +Rp41471 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p41472 +sg113 +I102 +sg146 +(lp41473 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10085 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41474 +(lp41475 +g189 +ag0 +(g190 +g2 +Ntp41476 +Rp41477 +(dp41478 +g194 +I01 +sg195 +(lp41479 +g0 +(g197 +g2 +Ntp41480 +Rp41481 +(dp41482 +g201 +g176 +(g177 +(I0 +tp41483 +g179 +tp41484 +Rp41485 +(I1 +(I1 +tp41486 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41487 +tp41488 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41489 +Rp41490 +(dp41491 +g201 +g176 +(g177 +(I0 +tp41492 +g179 +tp41493 +Rp41494 +(I1 +(I2 +tp41495 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41496 +tp41497 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41498 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41499 +g179 +tp41500 +Rp41501 +(I1 +(I1 +I1 +I1 +tp41502 +g38 +I00 +S'i\x80\xa3\x02\x08Y8@' +p41503 +tp41504 +bsg238 +g176 +(g177 +(I0 +tp41505 +g179 +tp41506 +Rp41507 +(I1 +(I1 +I1 +I1 +tp41508 +g38 +I00 +S'\xf4\x93\xb8\xad\x1diD?' +p41509 +tp41510 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41511 +g179 +tp41512 +Rp41513 +(I1 +(I1 +I1 +I1 +tp41514 +g38 +I00 +S'&CoK\x99\xa4\xe0?' +p41515 +tp41516 +bsg252 +g260 +sg48 +(lp41517 +g0 +(g52 +g2 +Ntp41518 +Rp41519 +(dp41520 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41521 +g179 +tp41522 +Rp41523 +(I1 +(I1 +I1 +I1 +tp41524 +g38 +I00 +S'nv\x14\x92wgG@' +p41525 +tp41526 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41527 +g279 +asg113 +I11346 +sg280 +I01 +sbaa(lp41528 +g12 +ag0 +(g190 +g2 +Ntp41529 +Rp41530 +(dp41531 +g194 +I01 +sg195 +(lp41532 +g0 +(g197 +g2 +Ntp41533 +Rp41534 +(dp41535 +g201 +g176 +(g177 +(I0 +tp41536 +g179 +tp41537 +Rp41538 +(I1 +(I1 +tp41539 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41540 +tp41541 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41542 +Rp41543 +(dp41544 +g201 +g176 +(g177 +(I0 +tp41545 +g179 +tp41546 +Rp41547 +(I1 +(I2 +tp41548 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41549 +tp41550 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41551 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41552 +g179 +tp41553 +Rp41554 +(I1 +(I1 +I1 +I1 +tp41555 +g38 +I00 +S'T\xd9\xe6\x17\n\xff\x0e@' +p41556 +tp41557 +bsg238 +g176 +(g177 +(I0 +tp41558 +g179 +tp41559 +Rp41560 +(I1 +(I1 +I1 +I1 +tp41561 +g38 +I00 +S'\xa2\xbcK\xe9\x97\x931?' +p41562 +tp41563 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41564 +g179 +tp41565 +Rp41566 +(I1 +(I1 +I1 +I1 +tp41567 +g38 +I00 +S'\rs\xbc\\c\x8e\xca?' +p41568 +tp41569 +bsg252 +g260 +sg48 +(lp41570 +g0 +(g52 +g2 +Ntp41571 +Rp41572 +(dp41573 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41574 +g179 +tp41575 +Rp41576 +(I1 +(I1 +I1 +I1 +tp41577 +g38 +I00 +S'\xe5\x804\xdd\x1d\xac2@' +p41578 +tp41579 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41580 +g334 +asg113 +I11347 +sg280 +I01 +sbaatp41581 +Rp41582 +sg337 +I00 +sg338 +Nsbaa(lp41583 +g340 +ag0 +(g341 +g2 +Ntp41584 +Rp41585 +(dp41586 +g17 +g41452 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41587 +(lp41588 +g189 +ag0 +(g190 +g2 +Ntp41589 +Rp41590 +(dp41591 +g194 +I01 +sg195 +(lp41592 +g0 +(g197 +g2 +Ntp41593 +Rp41594 +(dp41595 +g201 +g176 +(g177 +(I0 +tp41596 +g179 +tp41597 +Rp41598 +(I1 +(I1 +tp41599 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41600 +tp41601 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41602 +Rp41603 +(dp41604 +g201 +g176 +(g177 +(I0 +tp41605 +g179 +tp41606 +Rp41607 +(I1 +(I2 +tp41608 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41609 +tp41610 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41611 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41612 +g179 +tp41613 +Rp41614 +(I1 +(I1 +I1 +I1 +tp41615 +g38 +I00 +S'i\x80\xa3\x02\x08Y8@' +p41616 +tp41617 +bsg238 +g176 +(g177 +(I0 +tp41618 +g179 +tp41619 +Rp41620 +(I1 +(I1 +I1 +I1 +tp41621 +g38 +I00 +S'\xf4\x93\xb8\xad\x1diD?' +p41622 +tp41623 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41624 +g179 +tp41625 +Rp41626 +(I1 +(I1 +I1 +I1 +tp41627 +g38 +I00 +S'&CoK\x99\xa4\xe0?' +p41628 +tp41629 +bsg252 +g260 +sg48 +(lp41630 +g0 +(g52 +g2 +Ntp41631 +Rp41632 +(dp41633 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41634 +g179 +tp41635 +Rp41636 +(I1 +(I1 +I1 +I1 +tp41637 +g38 +I00 +S'nv\x14\x92wgG@' +p41638 +tp41639 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41640 +g279 +asg113 +I11350 +sg280 +I01 +sbaa(lp41641 +g401 +ag0 +(g190 +g2 +Ntp41642 +Rp41643 +(dp41644 +g194 +I01 +sg195 +(lp41645 +g0 +(g197 +g2 +Ntp41646 +Rp41647 +(dp41648 +g201 +g176 +(g177 +(I0 +tp41649 +g179 +tp41650 +Rp41651 +(I1 +(I1 +tp41652 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41653 +tp41654 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41655 +Rp41656 +(dp41657 +g201 +g176 +(g177 +(I0 +tp41658 +g179 +tp41659 +Rp41660 +(I1 +(I2 +tp41661 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41662 +tp41663 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41664 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41665 +g179 +tp41666 +Rp41667 +(I1 +(I1 +I1 +I1 +tp41668 +g38 +I00 +S'\x19\xf5\x0b\xa7$\xe7\x9e?' +p41669 +tp41670 +bsg238 +g176 +(g177 +(I0 +tp41671 +g179 +tp41672 +Rp41673 +(I1 +(I1 +I1 +I1 +tp41674 +g38 +I00 +S'`GX\xe9\x04\xae\t?' +p41675 +tp41676 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41677 +g179 +tp41678 +Rp41679 +(I1 +(I1 +I1 +I1 +tp41680 +g38 +I00 +S'\xc1\x11\xb3W\xc5\xbe\x92?' +p41681 +tp41682 +bsg252 +g260 +sg48 +(lp41683 +g0 +(g52 +g2 +Ntp41684 +Rp41685 +(dp41686 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp41687 +g179 +tp41688 +Rp41689 +(I1 +(I1 +I1 +I1 +tp41690 +g38 +I00 +S'\xf8\xd0S\x83E\\\xfa?' +p41691 +tp41692 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp41693 +g454 +asg113 +I11351 +sg280 +I01 +sbaatp41694 +Rp41695 +sg337 +I00 +sg338 +Nsbaa(lp41696 +g458 +ag0 +(g459 +g2 +Ntp41697 +Rp41698 +(dp41699 +g17 +g41452 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41700 +(lp41701 +g189 +ag0 +(g190 +g2 +Ntp41702 +Rp41703 +(dp41704 +g194 +I01 +sg195 +(lp41705 +g0 +(g197 +g2 +Ntp41706 +Rp41707 +(dp41708 +g201 +g176 +(g177 +(I0 +tp41709 +g179 +tp41710 +Rp41711 +(I1 +(I1 +tp41712 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41713 +tp41714 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41715 +Rp41716 +(dp41717 +g201 +g176 +(g177 +(I0 +tp41718 +g179 +tp41719 +Rp41720 +(I1 +(I2 +tp41721 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41722 +tp41723 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp41724 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41725 +g179 +tp41726 +Rp41727 +(I1 +(I1 +I1 +I1 +tp41728 +g38 +I00 +S'\xe0V??0V8@' +p41729 +tp41730 +bsg238 +g176 +(g177 +(I0 +tp41731 +g179 +tp41732 +Rp41733 +(I1 +(I1 +I1 +I1 +tp41734 +g38 +I00 +S'\xb4\xa1\xa5\xb8x+U?' +p41735 +tp41736 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41737 +g179 +tp41738 +Rp41739 +(I1 +(I1 +I1 +I1 +tp41740 +g38 +I00 +S'9\xa8ox\xba\xa2\xe0?' +p41741 +tp41742 +bsg252 +g513 +sg48 +(lp41743 +g0 +(g52 +g2 +Ntp41744 +Rp41745 +(dp41746 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp41747 +g179 +tp41748 +Rp41749 +(I1 +(I1 +I1 +I1 +tp41750 +g38 +I00 +S'\x90\x04]9\xd6dG@' +p41751 +tp41752 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp41753 +g527 +asg113 +I11354 +sg280 +I01 +sbaa(lp41754 +g529 +ag0 +(g190 +g2 +Ntp41755 +Rp41756 +(dp41757 +g194 +I01 +sg195 +(lp41758 +g0 +(g197 +g2 +Ntp41759 +Rp41760 +(dp41761 +g201 +g176 +(g177 +(I0 +tp41762 +g179 +tp41763 +Rp41764 +(I1 +(I1 +tp41765 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41766 +tp41767 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41768 +Rp41769 +(dp41770 +g201 +g176 +(g177 +(I0 +tp41771 +g179 +tp41772 +Rp41773 +(I1 +(I2 +tp41774 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41775 +tp41776 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41777 +Rp41778 +(dp41779 +g201 +g176 +(g177 +(I0 +tp41780 +g179 +tp41781 +Rp41782 +(I1 +(I2 +tp41783 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41784 +tp41785 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp41786 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41787 +g179 +tp41788 +Rp41789 +(I1 +(I1 +I1 +I1 +tp41790 +g38 +I00 +S')\x83\xd5\x1e\x171\x0b@' +p41791 +tp41792 +bsg238 +g176 +(g177 +(I0 +tp41793 +g179 +tp41794 +Rp41795 +(I1 +(I1 +I1 +I1 +tp41796 +g38 +I00 +S'\xcbK\xe2\xdc\x97\xfa>?' +p41797 +tp41798 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41799 +g179 +tp41800 +Rp41801 +(I1 +(I1 +I1 +I1 +tp41802 +g38 +I00 +S'_U\x81\x0bP\xde\xc8?' +p41803 +tp41804 +bsg252 +g586 +sg48 +(lp41805 +g0 +(g52 +g2 +Ntp41806 +Rp41807 +(dp41808 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp41809 +g179 +tp41810 +Rp41811 +(I1 +(I1 +I1 +I1 +tp41812 +g38 +I00 +S'\x07\xf0\x16HP|1@' +p41813 +tp41814 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp41815 +g600 +asg113 +I11355 +sg280 +I01 +sbaatp41816 +Rp41817 +sg337 +I00 +sg338 +Nsbaa(lp41818 +g604 +ag0 +(g605 +g2 +Ntp41819 +Rp41820 +(dp41821 +g17 +g41452 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41822 +(lp41823 +g611 +ag0 +(g190 +g2 +Ntp41824 +Rp41825 +(dp41826 +g194 +I01 +sg195 +(lp41827 +g0 +(g197 +g2 +Ntp41828 +Rp41829 +(dp41830 +g201 +g176 +(g177 +(I0 +tp41831 +g179 +tp41832 +Rp41833 +(I1 +(I1 +tp41834 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41835 +tp41836 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41837 +Rp41838 +(dp41839 +g201 +g176 +(g177 +(I0 +tp41840 +g179 +tp41841 +Rp41842 +(I1 +(I2 +tp41843 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41844 +tp41845 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp41846 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41847 +g179 +tp41848 +Rp41849 +(I1 +(I1 +I1 +I1 +tp41850 +g38 +I00 +S'[\xf8\x88\x7f\xae\xf3\x9f?' +p41851 +tp41852 +bsg238 +g176 +(g177 +(I0 +tp41853 +g179 +tp41854 +Rp41855 +(I1 +(I1 +I1 +I1 +tp41856 +g38 +I00 +S'\xdf\x831\xb3\t\xa2(?' +p41857 +tp41858 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41859 +g179 +tp41860 +Rp41861 +(I1 +(I1 +I1 +I1 +tp41862 +g38 +I00 +S'\x97\xb11\xb6\xe9\xfa\x92?' +p41863 +tp41864 +bsg252 +g513 +sg48 +(lp41865 +g0 +(g52 +g2 +Ntp41866 +Rp41867 +(dp41868 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp41869 +g179 +tp41870 +Rp41871 +(I1 +(I1 +I1 +I1 +tp41872 +g38 +I00 +S'\xbc\xe15\xa8\xd8\xb0\xfa?' +p41873 +tp41874 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp41875 +g664 +asg113 +I11358 +sg280 +I01 +sbaa(lp41876 +g666 +ag0 +(g190 +g2 +Ntp41877 +Rp41878 +(dp41879 +g194 +I01 +sg195 +(lp41880 +g0 +(g197 +g2 +Ntp41881 +Rp41882 +(dp41883 +g201 +g176 +(g177 +(I0 +tp41884 +g179 +tp41885 +Rp41886 +(I1 +(I1 +tp41887 +g208 +I00 +S"e'\x00\x00\x00\x00\x00\x00" +p41888 +tp41889 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41890 +Rp41891 +(dp41892 +g201 +g176 +(g177 +(I0 +tp41893 +g179 +tp41894 +Rp41895 +(I1 +(I2 +tp41896 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41897 +tp41898 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp41899 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41900 +g179 +tp41901 +Rp41902 +(I1 +(I1 +I1 +I1 +tp41903 +g38 +I00 +S'[\xf8\x88\x7f\xae\xf3\x9f?' +p41904 +tp41905 +bsg238 +g176 +(g177 +(I0 +tp41906 +g179 +tp41907 +Rp41908 +(I1 +(I1 +I1 +I1 +tp41909 +g38 +I00 +S'\xdf\x831\xb3\t\xa2(?' +p41910 +tp41911 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41912 +g179 +tp41913 +Rp41914 +(I1 +(I1 +I1 +I1 +tp41915 +g38 +I00 +S'\x97\xb11\xb6\xe9\xfa\x92?' +p41916 +tp41917 +bsg252 +g713 +sg48 +(lp41918 +g0 +(g52 +g2 +Ntp41919 +Rp41920 +(dp41921 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp41922 +g179 +tp41923 +Rp41924 +(I1 +(I1 +I1 +I1 +tp41925 +g38 +I00 +S'\xbc\xe15\xa8\xd8\xb0\xfa?' +p41926 +tp41927 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp41928 +g727 +asg113 +I11359 +sg280 +I01 +sbaatp41929 +Rp41930 +sg337 +I00 +sg338 +Nsbaatp41931 +Rp41932 +aa(lp41933 +I10086 +ag7 +((lp41934 +(lp41935 +g12 +ag0 +(g13 +g2 +Ntp41936 +Rp41937 +(dp41938 +g17 +g0 +(g18 +g2 +Ntp41939 +Rp41940 +(dp41941 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p41942 +sg116 +g0 +(g117 +g2 +Ntp41943 +Rp41944 +(dp41945 +g121 +(lp41946 +g0 +(g123 +g2 +Ntp41947 +Rp41948 +(dp41949 +g127 +g41466 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp41950 +Rp41951 +(dp41952 +g127 +g13713 +sg148 +g149 +sbasbsg163 +Nsg113 +I10086 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp41953 +(lp41954 +g189 +ag0 +(g190 +g2 +Ntp41955 +Rp41956 +(dp41957 +g194 +I01 +sg195 +(lp41958 +g0 +(g197 +g2 +Ntp41959 +Rp41960 +(dp41961 +g201 +g176 +(g177 +(I0 +tp41962 +g179 +tp41963 +Rp41964 +(I1 +(I1 +tp41965 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p41966 +tp41967 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp41968 +Rp41969 +(dp41970 +g201 +g176 +(g177 +(I0 +tp41971 +g179 +tp41972 +Rp41973 +(I1 +(I2 +tp41974 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p41975 +tp41976 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp41977 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp41978 +g179 +tp41979 +Rp41980 +(I1 +(I1 +I1 +I1 +tp41981 +g38 +I00 +S'X\xd9A\xc0\x98f8@' +p41982 +tp41983 +bsg238 +g176 +(g177 +(I0 +tp41984 +g179 +tp41985 +Rp41986 +(I1 +(I1 +I1 +I1 +tp41987 +g38 +I00 +S'T\xbf\xc0\x12wpD?' +p41988 +tp41989 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp41990 +g179 +tp41991 +Rp41992 +(I1 +(I1 +I1 +I1 +tp41993 +g38 +I00 +S'\xd2/\x05\x81;\xa9\xe0?' +p41994 +tp41995 +bsg252 +g260 +sg48 +(lp41996 +g0 +(g52 +g2 +Ntp41997 +Rp41998 +(dp41999 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42000 +g179 +tp42001 +Rp42002 +(I1 +(I1 +I1 +I1 +tp42003 +g38 +I00 +S'?Ko\xad\xfbmG@' +p42004 +tp42005 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42006 +g279 +asg113 +I11362 +sg280 +I01 +sbaa(lp42007 +g12 +ag0 +(g190 +g2 +Ntp42008 +Rp42009 +(dp42010 +g194 +I01 +sg195 +(lp42011 +g0 +(g197 +g2 +Ntp42012 +Rp42013 +(dp42014 +g201 +g176 +(g177 +(I0 +tp42015 +g179 +tp42016 +Rp42017 +(I1 +(I1 +tp42018 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42019 +tp42020 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42021 +Rp42022 +(dp42023 +g201 +g176 +(g177 +(I0 +tp42024 +g179 +tp42025 +Rp42026 +(I1 +(I2 +tp42027 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42028 +tp42029 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42030 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42031 +g179 +tp42032 +Rp42033 +(I1 +(I1 +I1 +I1 +tp42034 +g38 +I00 +S'V\xcf\x81\x06\xec\x13\x0f@' +p42035 +tp42036 +bsg238 +g176 +(g177 +(I0 +tp42037 +g179 +tp42038 +Rp42039 +(I1 +(I1 +I1 +I1 +tp42040 +g38 +I00 +S'd\x8a\xb7un~1?' +p42041 +tp42042 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42043 +g179 +tp42044 +Rp42045 +(I1 +(I1 +I1 +I1 +tp42046 +g38 +I00 +S'\xf2L\x1d}U\x97\xca?' +p42047 +tp42048 +bsg252 +g260 +sg48 +(lp42049 +g0 +(g52 +g2 +Ntp42050 +Rp42051 +(dp42052 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42053 +g179 +tp42054 +Rp42055 +(I1 +(I1 +I1 +I1 +tp42056 +g38 +I00 +S'\x1a\x9a\xf8\x1bh\xb22@' +p42057 +tp42058 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42059 +g334 +asg113 +I11363 +sg280 +I01 +sbaatp42060 +Rp42061 +sg337 +I00 +sg338 +Nsbaa(lp42062 +g340 +ag0 +(g341 +g2 +Ntp42063 +Rp42064 +(dp42065 +g17 +g41940 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42066 +(lp42067 +g189 +ag0 +(g190 +g2 +Ntp42068 +Rp42069 +(dp42070 +g194 +I01 +sg195 +(lp42071 +g0 +(g197 +g2 +Ntp42072 +Rp42073 +(dp42074 +g201 +g176 +(g177 +(I0 +tp42075 +g179 +tp42076 +Rp42077 +(I1 +(I1 +tp42078 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42079 +tp42080 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42081 +Rp42082 +(dp42083 +g201 +g176 +(g177 +(I0 +tp42084 +g179 +tp42085 +Rp42086 +(I1 +(I2 +tp42087 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42088 +tp42089 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42090 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42091 +g179 +tp42092 +Rp42093 +(I1 +(I1 +I1 +I1 +tp42094 +g38 +I00 +S'X\xd9A\xc0\x98f8@' +p42095 +tp42096 +bsg238 +g176 +(g177 +(I0 +tp42097 +g179 +tp42098 +Rp42099 +(I1 +(I1 +I1 +I1 +tp42100 +g38 +I00 +S'T\xbf\xc0\x12wpD?' +p42101 +tp42102 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42103 +g179 +tp42104 +Rp42105 +(I1 +(I1 +I1 +I1 +tp42106 +g38 +I00 +S'\xd2/\x05\x81;\xa9\xe0?' +p42107 +tp42108 +bsg252 +g260 +sg48 +(lp42109 +g0 +(g52 +g2 +Ntp42110 +Rp42111 +(dp42112 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42113 +g179 +tp42114 +Rp42115 +(I1 +(I1 +I1 +I1 +tp42116 +g38 +I00 +S'?Ko\xad\xfbmG@' +p42117 +tp42118 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42119 +g279 +asg113 +I11366 +sg280 +I01 +sbaa(lp42120 +g401 +ag0 +(g190 +g2 +Ntp42121 +Rp42122 +(dp42123 +g194 +I01 +sg195 +(lp42124 +g0 +(g197 +g2 +Ntp42125 +Rp42126 +(dp42127 +g201 +g176 +(g177 +(I0 +tp42128 +g179 +tp42129 +Rp42130 +(I1 +(I1 +tp42131 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42132 +tp42133 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42134 +Rp42135 +(dp42136 +g201 +g176 +(g177 +(I0 +tp42137 +g179 +tp42138 +Rp42139 +(I1 +(I2 +tp42140 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42141 +tp42142 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42143 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42144 +g179 +tp42145 +Rp42146 +(I1 +(I1 +I1 +I1 +tp42147 +g38 +I00 +S'\xda\x05f$q6\x9f?' +p42148 +tp42149 +bsg238 +g176 +(g177 +(I0 +tp42150 +g179 +tp42151 +Rp42152 +(I1 +(I1 +I1 +I1 +tp42153 +g38 +I00 +S'\xc5*I\x08\xa1^\n?' +p42154 +tp42155 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42156 +g179 +tp42157 +Rp42158 +(I1 +(I1 +I1 +I1 +tp42159 +g38 +I00 +S'\xe6\xec\xa0\xa9\xb1\xd6\x92?' +p42160 +tp42161 +bsg252 +g260 +sg48 +(lp42162 +g0 +(g52 +g2 +Ntp42163 +Rp42164 +(dp42165 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42166 +g179 +tp42167 +Rp42168 +(I1 +(I1 +I1 +I1 +tp42169 +g38 +I00 +S'$M\x8a\xd6\xe9}\xfa?' +p42170 +tp42171 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42172 +g454 +asg113 +I11367 +sg280 +I01 +sbaatp42173 +Rp42174 +sg337 +I00 +sg338 +Nsbaa(lp42175 +g458 +ag0 +(g459 +g2 +Ntp42176 +Rp42177 +(dp42178 +g17 +g41940 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42179 +(lp42180 +g189 +ag0 +(g190 +g2 +Ntp42181 +Rp42182 +(dp42183 +g194 +I01 +sg195 +(lp42184 +g0 +(g197 +g2 +Ntp42185 +Rp42186 +(dp42187 +g201 +g176 +(g177 +(I0 +tp42188 +g179 +tp42189 +Rp42190 +(I1 +(I1 +tp42191 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42192 +tp42193 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42194 +Rp42195 +(dp42196 +g201 +g176 +(g177 +(I0 +tp42197 +g179 +tp42198 +Rp42199 +(I1 +(I2 +tp42200 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42201 +tp42202 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp42203 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42204 +g179 +tp42205 +Rp42206 +(I1 +(I1 +I1 +I1 +tp42207 +g38 +I00 +S'V\xd6\x1d\xec\x05V8@' +p42208 +tp42209 +bsg238 +g176 +(g177 +(I0 +tp42210 +g179 +tp42211 +Rp42212 +(I1 +(I1 +I1 +I1 +tp42213 +g38 +I00 +S'zIZ\x87\xd4"U?' +p42214 +tp42215 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42216 +g179 +tp42217 +Rp42218 +(I1 +(I1 +I1 +I1 +tp42219 +g38 +I00 +S'3\x16\x9c\xf3\xac\xa2\xe0?' +p42220 +tp42221 +bsg252 +g513 +sg48 +(lp42222 +g0 +(g52 +g2 +Ntp42223 +Rp42224 +(dp42225 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp42226 +g179 +tp42227 +Rp42228 +(I1 +(I1 +I1 +I1 +tp42229 +g38 +I00 +S'8\x7f\x936\xc3dG@' +p42230 +tp42231 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp42232 +g527 +asg113 +I11370 +sg280 +I01 +sbaa(lp42233 +g529 +ag0 +(g190 +g2 +Ntp42234 +Rp42235 +(dp42236 +g194 +I01 +sg195 +(lp42237 +g0 +(g197 +g2 +Ntp42238 +Rp42239 +(dp42240 +g201 +g176 +(g177 +(I0 +tp42241 +g179 +tp42242 +Rp42243 +(I1 +(I1 +tp42244 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42245 +tp42246 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42247 +Rp42248 +(dp42249 +g201 +g176 +(g177 +(I0 +tp42250 +g179 +tp42251 +Rp42252 +(I1 +(I2 +tp42253 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42254 +tp42255 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42256 +Rp42257 +(dp42258 +g201 +g176 +(g177 +(I0 +tp42259 +g179 +tp42260 +Rp42261 +(I1 +(I2 +tp42262 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42263 +tp42264 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp42265 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42266 +g179 +tp42267 +Rp42268 +(I1 +(I1 +I1 +I1 +tp42269 +g38 +I00 +S'\xd9\xfc\xcf\xccY0\x0b@' +p42270 +tp42271 +bsg238 +g176 +(g177 +(I0 +tp42272 +g179 +tp42273 +Rp42274 +(I1 +(I1 +I1 +I1 +tp42275 +g38 +I00 +S'9\xfe\xe8\xa3&\x94@?' +p42276 +tp42277 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42278 +g179 +tp42279 +Rp42280 +(I1 +(I1 +I1 +I1 +tp42281 +g38 +I00 +S'f\xa4\x04\xea\xba\xdd\xc8?' +p42282 +tp42283 +bsg252 +g586 +sg48 +(lp42284 +g0 +(g52 +g2 +Ntp42285 +Rp42286 +(dp42287 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp42288 +g179 +tp42289 +Rp42290 +(I1 +(I1 +I1 +I1 +tp42291 +g38 +I00 +S'\x98C\x8bl\xe7{1@' +p42292 +tp42293 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp42294 +g600 +asg113 +I11371 +sg280 +I01 +sbaatp42295 +Rp42296 +sg337 +I00 +sg338 +Nsbaa(lp42297 +g604 +ag0 +(g605 +g2 +Ntp42298 +Rp42299 +(dp42300 +g17 +g41940 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42301 +(lp42302 +g611 +ag0 +(g190 +g2 +Ntp42303 +Rp42304 +(dp42305 +g194 +I01 +sg195 +(lp42306 +g0 +(g197 +g2 +Ntp42307 +Rp42308 +(dp42309 +g201 +g176 +(g177 +(I0 +tp42310 +g179 +tp42311 +Rp42312 +(I1 +(I1 +tp42313 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42314 +tp42315 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42316 +Rp42317 +(dp42318 +g201 +g176 +(g177 +(I0 +tp42319 +g179 +tp42320 +Rp42321 +(I1 +(I2 +tp42322 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42323 +tp42324 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp42325 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42326 +g179 +tp42327 +Rp42328 +(I1 +(I1 +I1 +I1 +tp42329 +g38 +I00 +S'\x1c&\xdd.6r\x9f?' +p42330 +tp42331 +bsg238 +g176 +(g177 +(I0 +tp42332 +g179 +tp42333 +Rp42334 +(I1 +(I1 +I1 +I1 +tp42335 +g38 +I00 +S'2\xfb\x99\xc2\xb9L&?' +p42336 +tp42337 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42338 +g179 +tp42339 +Rp42340 +(I1 +(I1 +I1 +I1 +tp42341 +g38 +I00 +S'h>\xb8A\xfe\xd7\x92?' +p42342 +tp42343 +bsg252 +g513 +sg48 +(lp42344 +g0 +(g52 +g2 +Ntp42345 +Rp42346 +(dp42347 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp42348 +g179 +tp42349 +Rp42350 +(I1 +(I1 +I1 +I1 +tp42351 +g38 +I00 +S'\xc2\x17k\x8c\xbd\x7f\xfa?' +p42352 +tp42353 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp42354 +g664 +asg113 +I11374 +sg280 +I01 +sbaa(lp42355 +g666 +ag0 +(g190 +g2 +Ntp42356 +Rp42357 +(dp42358 +g194 +I01 +sg195 +(lp42359 +g0 +(g197 +g2 +Ntp42360 +Rp42361 +(dp42362 +g201 +g176 +(g177 +(I0 +tp42363 +g179 +tp42364 +Rp42365 +(I1 +(I1 +tp42366 +g208 +I00 +S"f'\x00\x00\x00\x00\x00\x00" +p42367 +tp42368 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42369 +Rp42370 +(dp42371 +g201 +g176 +(g177 +(I0 +tp42372 +g179 +tp42373 +Rp42374 +(I1 +(I2 +tp42375 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42376 +tp42377 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp42378 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42379 +g179 +tp42380 +Rp42381 +(I1 +(I1 +I1 +I1 +tp42382 +g38 +I00 +S'\x19&\xdd.6r\x9f?' +p42383 +tp42384 +bsg238 +g176 +(g177 +(I0 +tp42385 +g179 +tp42386 +Rp42387 +(I1 +(I1 +I1 +I1 +tp42388 +g38 +I00 +S'\xae\xfa\x99\xc2\xb9L&?' +p42389 +tp42390 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42391 +g179 +tp42392 +Rp42393 +(I1 +(I1 +I1 +I1 +tp42394 +g38 +I00 +S'h>\xb8A\xfe\xd7\x92?' +p42395 +tp42396 +bsg252 +g713 +sg48 +(lp42397 +g0 +(g52 +g2 +Ntp42398 +Rp42399 +(dp42400 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp42401 +g179 +tp42402 +Rp42403 +(I1 +(I1 +I1 +I1 +tp42404 +g38 +I00 +S'\xc2\x17k\x8c\xbd\x7f\xfa?' +p42405 +tp42406 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp42407 +g727 +asg113 +I11375 +sg280 +I01 +sbaatp42408 +Rp42409 +sg337 +I00 +sg338 +Nsbaatp42410 +Rp42411 +aa(lp42412 +I10087 +ag7 +((lp42413 +(lp42414 +g12 +ag0 +(g13 +g2 +Ntp42415 +Rp42416 +(dp42417 +g17 +g0 +(g18 +g2 +Ntp42418 +Rp42419 +(dp42420 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p42421 +sg116 +g0 +(g117 +g2 +Ntp42422 +Rp42423 +(dp42424 +g121 +(lp42425 +g0 +(g123 +g2 +Ntp42426 +Rp42427 +(dp42428 +g127 +g17156 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp42429 +Rp42430 +(dp42431 +g127 +g5824 +sg148 +g162 +sbasbsg163 +Nsg113 +I10087 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42432 +(lp42433 +g189 +ag0 +(g190 +g2 +Ntp42434 +Rp42435 +(dp42436 +g194 +I01 +sg195 +(lp42437 +g0 +(g197 +g2 +Ntp42438 +Rp42439 +(dp42440 +g201 +g176 +(g177 +(I0 +tp42441 +g179 +tp42442 +Rp42443 +(I1 +(I1 +tp42444 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42445 +tp42446 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42447 +Rp42448 +(dp42449 +g201 +g176 +(g177 +(I0 +tp42450 +g179 +tp42451 +Rp42452 +(I1 +(I2 +tp42453 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42454 +tp42455 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42456 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42457 +g179 +tp42458 +Rp42459 +(I1 +(I1 +I1 +I1 +tp42460 +g38 +I00 +S'\x92\xcb\xc5\x81~\x818@' +p42461 +tp42462 +bsg238 +g176 +(g177 +(I0 +tp42463 +g179 +tp42464 +Rp42465 +(I1 +(I1 +I1 +I1 +tp42466 +g38 +I00 +S'\x1a\xe4W\xee\xd5\xeeA?' +p42467 +tp42468 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42469 +g179 +tp42470 +Rp42471 +(I1 +(I1 +I1 +I1 +tp42472 +g38 +I00 +S'=9b x\xb2\xe0?' +p42473 +tp42474 +bsg252 +g260 +sg48 +(lp42475 +g0 +(g52 +g2 +Ntp42476 +Rp42477 +(dp42478 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42479 +g179 +tp42480 +Rp42481 +(I1 +(I1 +I1 +I1 +tp42482 +g38 +I00 +S'~ \x8a\xed\xf8zG@' +p42483 +tp42484 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42485 +g279 +asg113 +I11378 +sg280 +I01 +sbaa(lp42486 +g12 +ag0 +(g190 +g2 +Ntp42487 +Rp42488 +(dp42489 +g194 +I01 +sg195 +(lp42490 +g0 +(g197 +g2 +Ntp42491 +Rp42492 +(dp42493 +g201 +g176 +(g177 +(I0 +tp42494 +g179 +tp42495 +Rp42496 +(I1 +(I1 +tp42497 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42498 +tp42499 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42500 +Rp42501 +(dp42502 +g201 +g176 +(g177 +(I0 +tp42503 +g179 +tp42504 +Rp42505 +(I1 +(I2 +tp42506 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42507 +tp42508 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42509 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42510 +g179 +tp42511 +Rp42512 +(I1 +(I1 +I1 +I1 +tp42513 +g38 +I00 +S'[\xc3\x8d\xb0c<\x10@' +p42514 +tp42515 +bsg238 +g176 +(g177 +(I0 +tp42516 +g179 +tp42517 +Rp42518 +(I1 +(I1 +I1 +I1 +tp42519 +g38 +I00 +S'\xd0\xf5\x826\xae\x92/?' +p42520 +tp42521 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42522 +g179 +tp42523 +Rp42524 +(I1 +(I1 +I1 +I1 +tp42525 +g38 +I00 +S'Jt\r\xe7p.\xcb?' +p42526 +tp42527 +bsg252 +g260 +sg48 +(lp42528 +g0 +(g52 +g2 +Ntp42529 +Rp42530 +(dp42531 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42532 +g179 +tp42533 +Rp42534 +(I1 +(I1 +I1 +I1 +tp42535 +g38 +I00 +S'\xc4uub\xa7\x1c3@' +p42536 +tp42537 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42538 +g334 +asg113 +I11379 +sg280 +I01 +sbaatp42539 +Rp42540 +sg337 +I00 +sg338 +Nsbaa(lp42541 +g340 +ag0 +(g341 +g2 +Ntp42542 +Rp42543 +(dp42544 +g17 +g42419 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42545 +(lp42546 +g189 +ag0 +(g190 +g2 +Ntp42547 +Rp42548 +(dp42549 +g194 +I01 +sg195 +(lp42550 +g0 +(g197 +g2 +Ntp42551 +Rp42552 +(dp42553 +g201 +g176 +(g177 +(I0 +tp42554 +g179 +tp42555 +Rp42556 +(I1 +(I1 +tp42557 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42558 +tp42559 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42560 +Rp42561 +(dp42562 +g201 +g176 +(g177 +(I0 +tp42563 +g179 +tp42564 +Rp42565 +(I1 +(I2 +tp42566 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42567 +tp42568 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42569 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42570 +g179 +tp42571 +Rp42572 +(I1 +(I1 +I1 +I1 +tp42573 +g38 +I00 +S'\x92\xcb\xc5\x81~\x818@' +p42574 +tp42575 +bsg238 +g176 +(g177 +(I0 +tp42576 +g179 +tp42577 +Rp42578 +(I1 +(I1 +I1 +I1 +tp42579 +g38 +I00 +S'\x1a\xe4W\xee\xd5\xeeA?' +p42580 +tp42581 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42582 +g179 +tp42583 +Rp42584 +(I1 +(I1 +I1 +I1 +tp42585 +g38 +I00 +S'=9b x\xb2\xe0?' +p42586 +tp42587 +bsg252 +g260 +sg48 +(lp42588 +g0 +(g52 +g2 +Ntp42589 +Rp42590 +(dp42591 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42592 +g179 +tp42593 +Rp42594 +(I1 +(I1 +I1 +I1 +tp42595 +g38 +I00 +S'~ \x8a\xed\xf8zG@' +p42596 +tp42597 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42598 +g279 +asg113 +I11382 +sg280 +I01 +sbaa(lp42599 +g401 +ag0 +(g190 +g2 +Ntp42600 +Rp42601 +(dp42602 +g194 +I01 +sg195 +(lp42603 +g0 +(g197 +g2 +Ntp42604 +Rp42605 +(dp42606 +g201 +g176 +(g177 +(I0 +tp42607 +g179 +tp42608 +Rp42609 +(I1 +(I1 +tp42610 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42611 +tp42612 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42613 +Rp42614 +(dp42615 +g201 +g176 +(g177 +(I0 +tp42616 +g179 +tp42617 +Rp42618 +(I1 +(I2 +tp42619 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42620 +tp42621 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42622 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42623 +g179 +tp42624 +Rp42625 +(I1 +(I1 +I1 +I1 +tp42626 +g38 +I00 +S'\xf3\x07\xa1E\xdc\x84\xaa?' +p42627 +tp42628 +bsg238 +g176 +(g177 +(I0 +tp42629 +g179 +tp42630 +Rp42631 +(I1 +(I1 +I1 +I1 +tp42632 +g38 +I00 +S'\xb6\xbeWN\x8b\xa3\x0b?' +p42633 +tp42634 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42635 +g179 +tp42636 +Rp42637 +(I1 +(I1 +I1 +I1 +tp42638 +g38 +I00 +S',\xf5\n\xe8]\x8f\x98?' +p42639 +tp42640 +bsg252 +g260 +sg48 +(lp42641 +g0 +(g52 +g2 +Ntp42642 +Rp42643 +(dp42644 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42645 +g179 +tp42646 +Rp42647 +(I1 +(I1 +I1 +I1 +tp42648 +g38 +I00 +S"c\xb4'\x07\xceD\x01@" +p42649 +tp42650 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42651 +g454 +asg113 +I11383 +sg280 +I01 +sbaatp42652 +Rp42653 +sg337 +I00 +sg338 +Nsbaa(lp42654 +g458 +ag0 +(g459 +g2 +Ntp42655 +Rp42656 +(dp42657 +g17 +g42419 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42658 +(lp42659 +g189 +ag0 +(g190 +g2 +Ntp42660 +Rp42661 +(dp42662 +g194 +I01 +sg195 +(lp42663 +g0 +(g197 +g2 +Ntp42664 +Rp42665 +(dp42666 +g201 +g176 +(g177 +(I0 +tp42667 +g179 +tp42668 +Rp42669 +(I1 +(I1 +tp42670 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42671 +tp42672 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42673 +Rp42674 +(dp42675 +g201 +g176 +(g177 +(I0 +tp42676 +g179 +tp42677 +Rp42678 +(I1 +(I2 +tp42679 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42680 +tp42681 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp42682 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42683 +g179 +tp42684 +Rp42685 +(I1 +(I1 +I1 +I1 +tp42686 +g38 +I00 +S'\xf8\x1eJ\x95lF8@' +p42687 +tp42688 +bsg238 +g176 +(g177 +(I0 +tp42689 +g179 +tp42690 +Rp42691 +(I1 +(I1 +I1 +I1 +tp42692 +g38 +I00 +S'\x08\t\xca\x9a\x85\x96W?' +p42693 +tp42694 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42695 +g179 +tp42696 +Rp42697 +(I1 +(I1 +I1 +I1 +tp42698 +g38 +I00 +S'\xd8\xabK\x0c\r\x9d\xe0?' +p42699 +tp42700 +bsg252 +g513 +sg48 +(lp42701 +g0 +(g52 +g2 +Ntp42702 +Rp42703 +(dp42704 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp42705 +g179 +tp42706 +Rp42707 +(I1 +(I1 +I1 +I1 +tp42708 +g38 +I00 +S'\xa8iJY\xda\\G@' +p42709 +tp42710 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp42711 +g527 +asg113 +I11386 +sg280 +I01 +sbaa(lp42712 +g529 +ag0 +(g190 +g2 +Ntp42713 +Rp42714 +(dp42715 +g194 +I01 +sg195 +(lp42716 +g0 +(g197 +g2 +Ntp42717 +Rp42718 +(dp42719 +g201 +g176 +(g177 +(I0 +tp42720 +g179 +tp42721 +Rp42722 +(I1 +(I1 +tp42723 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42724 +tp42725 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42726 +Rp42727 +(dp42728 +g201 +g176 +(g177 +(I0 +tp42729 +g179 +tp42730 +Rp42731 +(I1 +(I2 +tp42732 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42733 +tp42734 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42735 +Rp42736 +(dp42737 +g201 +g176 +(g177 +(I0 +tp42738 +g179 +tp42739 +Rp42740 +(I1 +(I2 +tp42741 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42742 +tp42743 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp42744 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42745 +g179 +tp42746 +Rp42747 +(I1 +(I1 +I1 +I1 +tp42748 +g38 +I00 +S'>G\xb3\xcb\x1ai\x0b@' +p42749 +tp42750 +bsg238 +g176 +(g177 +(I0 +tp42751 +g179 +tp42752 +Rp42753 +(I1 +(I1 +I1 +I1 +tp42754 +g38 +I00 +S'.\x18P\x01>XB?' +p42755 +tp42756 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42757 +g179 +tp42758 +Rp42759 +(I1 +(I1 +I1 +I1 +tp42760 +g38 +I00 +S'k\xe3\x13c7\xf7\xc8?' +p42761 +tp42762 +bsg252 +g586 +sg48 +(lp42763 +g0 +(g52 +g2 +Ntp42764 +Rp42765 +(dp42766 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp42767 +g179 +tp42768 +Rp42769 +(I1 +(I1 +I1 +I1 +tp42770 +g38 +I00 +S'\xe7\xfb\xa9\xf1\xd2\x8d1@' +p42771 +tp42772 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp42773 +g600 +asg113 +I11387 +sg280 +I01 +sbaatp42774 +Rp42775 +sg337 +I00 +sg338 +Nsbaa(lp42776 +g604 +ag0 +(g605 +g2 +Ntp42777 +Rp42778 +(dp42779 +g17 +g42419 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42780 +(lp42781 +g611 +ag0 +(g190 +g2 +Ntp42782 +Rp42783 +(dp42784 +g194 +I01 +sg195 +(lp42785 +g0 +(g197 +g2 +Ntp42786 +Rp42787 +(dp42788 +g201 +g176 +(g177 +(I0 +tp42789 +g179 +tp42790 +Rp42791 +(I1 +(I1 +tp42792 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42793 +tp42794 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42795 +Rp42796 +(dp42797 +g201 +g176 +(g177 +(I0 +tp42798 +g179 +tp42799 +Rp42800 +(I1 +(I2 +tp42801 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42802 +tp42803 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp42804 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42805 +g179 +tp42806 +Rp42807 +(I1 +(I1 +I1 +I1 +tp42808 +g38 +I00 +S'\x94\x9c]\x8dV\xcf\xaa?' +p42809 +tp42810 +bsg238 +g176 +(g177 +(I0 +tp42811 +g179 +tp42812 +Rp42813 +(I1 +(I1 +I1 +I1 +tp42814 +g38 +I00 +S'\x14\x94\x90\xc4\x07Y,?' +p42815 +tp42816 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42817 +g179 +tp42818 +Rp42819 +(I1 +(I1 +I1 +I1 +tp42820 +g38 +I00 +S'l-k\x10u\x9c\x98?' +p42821 +tp42822 +bsg252 +g513 +sg48 +(lp42823 +g0 +(g52 +g2 +Ntp42824 +Rp42825 +(dp42826 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp42827 +g179 +tp42828 +Rp42829 +(I1 +(I1 +I1 +I1 +tp42830 +g38 +I00 +S'\xf0[\x8bO\x02N\x01@' +p42831 +tp42832 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp42833 +g664 +asg113 +I11390 +sg280 +I01 +sbaa(lp42834 +g666 +ag0 +(g190 +g2 +Ntp42835 +Rp42836 +(dp42837 +g194 +I01 +sg195 +(lp42838 +g0 +(g197 +g2 +Ntp42839 +Rp42840 +(dp42841 +g201 +g176 +(g177 +(I0 +tp42842 +g179 +tp42843 +Rp42844 +(I1 +(I1 +tp42845 +g208 +I00 +S"g'\x00\x00\x00\x00\x00\x00" +p42846 +tp42847 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42848 +Rp42849 +(dp42850 +g201 +g176 +(g177 +(I0 +tp42851 +g179 +tp42852 +Rp42853 +(I1 +(I2 +tp42854 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42855 +tp42856 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp42857 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42858 +g179 +tp42859 +Rp42860 +(I1 +(I1 +I1 +I1 +tp42861 +g38 +I00 +S'\x98\x9c]\x8dV\xcf\xaa?' +p42862 +tp42863 +bsg238 +g176 +(g177 +(I0 +tp42864 +g179 +tp42865 +Rp42866 +(I1 +(I1 +I1 +I1 +tp42867 +g38 +I00 +S'L\x95\x90\xc4\x07Y,?' +p42868 +tp42869 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42870 +g179 +tp42871 +Rp42872 +(I1 +(I1 +I1 +I1 +tp42873 +g38 +I00 +S'l-k\x10u\x9c\x98?' +p42874 +tp42875 +bsg252 +g713 +sg48 +(lp42876 +g0 +(g52 +g2 +Ntp42877 +Rp42878 +(dp42879 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp42880 +g179 +tp42881 +Rp42882 +(I1 +(I1 +I1 +I1 +tp42883 +g38 +I00 +S'\xf0[\x8bO\x02N\x01@' +p42884 +tp42885 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp42886 +g727 +asg113 +I11391 +sg280 +I01 +sbaatp42887 +Rp42888 +sg337 +I00 +sg338 +Nsbaatp42889 +Rp42890 +aa(lp42891 +I10088 +ag7 +((lp42892 +(lp42893 +g12 +ag0 +(g13 +g2 +Ntp42894 +Rp42895 +(dp42896 +g17 +g0 +(g18 +g2 +Ntp42897 +Rp42898 +(dp42899 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1239 +sg114 +Nsg46 +Vfuel +p42900 +sg116 +g0 +(g117 +g2 +Ntp42901 +Rp42902 +(dp42903 +g121 +(lp42904 +g0 +(g123 +g2 +Ntp42905 +Rp42906 +(dp42907 +g127 +g23030 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp42908 +Rp42909 +(dp42910 +g127 +g26931 +sg148 +g162 +sbasbsg163 +Nsg113 +I10088 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp42911 +(lp42912 +g189 +ag0 +(g190 +g2 +Ntp42913 +Rp42914 +(dp42915 +g194 +I01 +sg195 +(lp42916 +g0 +(g197 +g2 +Ntp42917 +Rp42918 +(dp42919 +g201 +g176 +(g177 +(I0 +tp42920 +g179 +tp42921 +Rp42922 +(I1 +(I1 +tp42923 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p42924 +tp42925 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42926 +Rp42927 +(dp42928 +g201 +g176 +(g177 +(I0 +tp42929 +g179 +tp42930 +Rp42931 +(I1 +(I2 +tp42932 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42933 +tp42934 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42935 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42936 +g179 +tp42937 +Rp42938 +(I1 +(I1 +I1 +I1 +tp42939 +g38 +I00 +S'\x80\x02\x0b0\xb3\x978@' +p42940 +tp42941 +bsg238 +g176 +(g177 +(I0 +tp42942 +g179 +tp42943 +Rp42944 +(I1 +(I1 +I1 +I1 +tp42945 +g38 +I00 +S'*l\xb9\x17\x067@?' +p42946 +tp42947 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp42948 +g179 +tp42949 +Rp42950 +(I1 +(I1 +I1 +I1 +tp42951 +g38 +I00 +S'\xc54\xd6\xff\x10\xba\xe0?' +p42952 +tp42953 +bsg252 +g260 +sg48 +(lp42954 +g0 +(g52 +g2 +Ntp42955 +Rp42956 +(dp42957 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp42958 +g179 +tp42959 +Rp42960 +(I1 +(I1 +I1 +I1 +tp42961 +g38 +I00 +S'5:\xc5\xe7\xa7\x85G@' +p42962 +tp42963 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp42964 +g279 +asg113 +I11394 +sg280 +I01 +sbaa(lp42965 +g12 +ag0 +(g190 +g2 +Ntp42966 +Rp42967 +(dp42968 +g194 +I01 +sg195 +(lp42969 +g0 +(g197 +g2 +Ntp42970 +Rp42971 +(dp42972 +g201 +g176 +(g177 +(I0 +tp42973 +g179 +tp42974 +Rp42975 +(I1 +(I1 +tp42976 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p42977 +tp42978 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp42979 +Rp42980 +(dp42981 +g201 +g176 +(g177 +(I0 +tp42982 +g179 +tp42983 +Rp42984 +(I1 +(I2 +tp42985 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p42986 +tp42987 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp42988 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp42989 +g179 +tp42990 +Rp42991 +(I1 +(I1 +I1 +I1 +tp42992 +g38 +I00 +S'\xc3D\xa6\x84\x8f\x1e\x11@' +p42993 +tp42994 +bsg238 +g176 +(g177 +(I0 +tp42995 +g179 +tp42996 +Rp42997 +(I1 +(I1 +I1 +I1 +tp42998 +g38 +I00 +S';\xc5r\xcfWr0?' +p42999 +tp43000 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43001 +g179 +tp43002 +Rp43003 +(I1 +(I1 +I1 +I1 +tp43004 +g38 +I00 +S'\xfa:\xd1~>\xe9\xcb?' +p43005 +tp43006 +bsg252 +g260 +sg48 +(lp43007 +g0 +(g52 +g2 +Ntp43008 +Rp43009 +(dp43010 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43011 +g179 +tp43012 +Rp43013 +(I1 +(I1 +I1 +I1 +tp43014 +g38 +I00 +S'x\x1d+\xf1\xff\x9f3@' +p43015 +tp43016 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43017 +g334 +asg113 +I11395 +sg280 +I01 +sbaatp43018 +Rp43019 +sg337 +I00 +sg338 +Nsbaa(lp43020 +g340 +ag0 +(g341 +g2 +Ntp43021 +Rp43022 +(dp43023 +g17 +g42898 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43024 +(lp43025 +g189 +ag0 +(g190 +g2 +Ntp43026 +Rp43027 +(dp43028 +g194 +I01 +sg195 +(lp43029 +g0 +(g197 +g2 +Ntp43030 +Rp43031 +(dp43032 +g201 +g176 +(g177 +(I0 +tp43033 +g179 +tp43034 +Rp43035 +(I1 +(I1 +tp43036 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43037 +tp43038 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43039 +Rp43040 +(dp43041 +g201 +g176 +(g177 +(I0 +tp43042 +g179 +tp43043 +Rp43044 +(I1 +(I2 +tp43045 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43046 +tp43047 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43048 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43049 +g179 +tp43050 +Rp43051 +(I1 +(I1 +I1 +I1 +tp43052 +g38 +I00 +S'\x80\x02\x0b0\xb3\x978@' +p43053 +tp43054 +bsg238 +g176 +(g177 +(I0 +tp43055 +g179 +tp43056 +Rp43057 +(I1 +(I1 +I1 +I1 +tp43058 +g38 +I00 +S'*l\xb9\x17\x067@?' +p43059 +tp43060 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43061 +g179 +tp43062 +Rp43063 +(I1 +(I1 +I1 +I1 +tp43064 +g38 +I00 +S'\xc54\xd6\xff\x10\xba\xe0?' +p43065 +tp43066 +bsg252 +g260 +sg48 +(lp43067 +g0 +(g52 +g2 +Ntp43068 +Rp43069 +(dp43070 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43071 +g179 +tp43072 +Rp43073 +(I1 +(I1 +I1 +I1 +tp43074 +g38 +I00 +S'5:\xc5\xe7\xa7\x85G@' +p43075 +tp43076 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43077 +g279 +asg113 +I11398 +sg280 +I01 +sbaa(lp43078 +g401 +ag0 +(g190 +g2 +Ntp43079 +Rp43080 +(dp43081 +g194 +I01 +sg195 +(lp43082 +g0 +(g197 +g2 +Ntp43083 +Rp43084 +(dp43085 +g201 +g176 +(g177 +(I0 +tp43086 +g179 +tp43087 +Rp43088 +(I1 +(I1 +tp43089 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43090 +tp43091 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43092 +Rp43093 +(dp43094 +g201 +g176 +(g177 +(I0 +tp43095 +g179 +tp43096 +Rp43097 +(I1 +(I2 +tp43098 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43099 +tp43100 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43101 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43102 +g179 +tp43103 +Rp43104 +(I1 +(I1 +I1 +I1 +tp43105 +g38 +I00 +S'}\x8c)\x12O\xde\xb4?' +p43106 +tp43107 +bsg238 +g176 +(g177 +(I0 +tp43108 +g179 +tp43109 +Rp43110 +(I1 +(I1 +I1 +I1 +tp43111 +g38 +I00 +S'$2N\x00\x1cZ\x11?' +p43112 +tp43113 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43114 +g179 +tp43115 +Rp43116 +(I1 +(I1 +I1 +I1 +tp43117 +g38 +I00 +S'\x1e\xb0H\xf9\xaf\xcf\x9e?' +p43118 +tp43119 +bsg252 +g260 +sg48 +(lp43120 +g0 +(g52 +g2 +Ntp43121 +Rp43122 +(dp43123 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43124 +g179 +tp43125 +Rp43126 +(I1 +(I1 +I1 +I1 +tp43127 +g38 +I00 +S'\xd5\x1bG\xbb\x07\xaa\x05@' +p43128 +tp43129 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43130 +g454 +asg113 +I11399 +sg280 +I01 +sbaatp43131 +Rp43132 +sg337 +I00 +sg338 +Nsbaa(lp43133 +g458 +ag0 +(g459 +g2 +Ntp43134 +Rp43135 +(dp43136 +g17 +g42898 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43137 +(lp43138 +g189 +ag0 +(g190 +g2 +Ntp43139 +Rp43140 +(dp43141 +g194 +I01 +sg195 +(lp43142 +g0 +(g197 +g2 +Ntp43143 +Rp43144 +(dp43145 +g201 +g176 +(g177 +(I0 +tp43146 +g179 +tp43147 +Rp43148 +(I1 +(I1 +tp43149 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43150 +tp43151 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43152 +Rp43153 +(dp43154 +g201 +g176 +(g177 +(I0 +tp43155 +g179 +tp43156 +Rp43157 +(I1 +(I2 +tp43158 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43159 +tp43160 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp43161 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43162 +g179 +tp43163 +Rp43164 +(I1 +(I1 +I1 +I1 +tp43165 +g38 +I00 +S'\xd3\x80t\x89-\x868@' +p43166 +tp43167 +bsg238 +g176 +(g177 +(I0 +tp43168 +g179 +tp43169 +Rp43170 +(I1 +(I1 +I1 +I1 +tp43171 +g38 +I00 +S'\xe24\x18\x87\xae1U?' +p43172 +tp43173 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43174 +g179 +tp43175 +Rp43176 +(I1 +(I1 +I1 +I1 +tp43177 +g38 +I00 +S'\xf2\xd7\xeb\xea\x1a\xb3\xe0?' +p43178 +tp43179 +bsg252 +g513 +sg48 +(lp43180 +g0 +(g52 +g2 +Ntp43181 +Rp43182 +(dp43183 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp43184 +g179 +tp43185 +Rp43186 +(I1 +(I1 +I1 +I1 +tp43187 +g38 +I00 +S'\xad\xa7[\xda\xdd{G@' +p43188 +tp43189 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp43190 +g527 +asg113 +I11402 +sg280 +I01 +sbaa(lp43191 +g529 +ag0 +(g190 +g2 +Ntp43192 +Rp43193 +(dp43194 +g194 +I01 +sg195 +(lp43195 +g0 +(g197 +g2 +Ntp43196 +Rp43197 +(dp43198 +g201 +g176 +(g177 +(I0 +tp43199 +g179 +tp43200 +Rp43201 +(I1 +(I1 +tp43202 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43203 +tp43204 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43205 +Rp43206 +(dp43207 +g201 +g176 +(g177 +(I0 +tp43208 +g179 +tp43209 +Rp43210 +(I1 +(I2 +tp43211 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43212 +tp43213 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43214 +Rp43215 +(dp43216 +g201 +g176 +(g177 +(I0 +tp43217 +g179 +tp43218 +Rp43219 +(I1 +(I2 +tp43220 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43221 +tp43222 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp43223 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43224 +g179 +tp43225 +Rp43226 +(I1 +(I1 +I1 +I1 +tp43227 +g38 +I00 +S'\x01\xec\x054K\x19\x0c@' +p43228 +tp43229 +bsg238 +g176 +(g177 +(I0 +tp43230 +g179 +tp43231 +Rp43232 +(I1 +(I1 +I1 +I1 +tp43233 +g38 +I00 +S'(a\xa5+\xff\xf8??' +p43234 +tp43235 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43236 +g179 +tp43237 +Rp43238 +(I1 +(I1 +I1 +I1 +tp43239 +g38 +I00 +S'\x1a\x803\x1e\x92G\xc9?' +p43240 +tp43241 +bsg252 +g586 +sg48 +(lp43242 +g0 +(g52 +g2 +Ntp43243 +Rp43244 +(dp43245 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp43246 +g179 +tp43247 +Rp43248 +(I1 +(I1 +I1 +I1 +tp43249 +g38 +I00 +S'\x126<\xbdR\xc61@' +p43250 +tp43251 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp43252 +g600 +asg113 +I11403 +sg280 +I01 +sbaatp43253 +Rp43254 +sg337 +I00 +sg338 +Nsbaa(lp43255 +g604 +ag0 +(g605 +g2 +Ntp43256 +Rp43257 +(dp43258 +g17 +g42898 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43259 +(lp43260 +g611 +ag0 +(g190 +g2 +Ntp43261 +Rp43262 +(dp43263 +g194 +I01 +sg195 +(lp43264 +g0 +(g197 +g2 +Ntp43265 +Rp43266 +(dp43267 +g201 +g176 +(g177 +(I0 +tp43268 +g179 +tp43269 +Rp43270 +(I1 +(I1 +tp43271 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43272 +tp43273 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43274 +Rp43275 +(dp43276 +g201 +g176 +(g177 +(I0 +tp43277 +g179 +tp43278 +Rp43279 +(I1 +(I2 +tp43280 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43281 +tp43282 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp43283 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43284 +g179 +tp43285 +Rp43286 +(I1 +(I1 +I1 +I1 +tp43287 +g38 +I00 +S';V\x00\xa7\xdb\x81\xb4?' +p43288 +tp43289 +bsg238 +g176 +(g177 +(I0 +tp43290 +g179 +tp43291 +Rp43292 +(I1 +(I1 +I1 +I1 +tp43293 +g38 +I00 +S'\x8e?Pi\x98"-?' +p43294 +tp43295 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43296 +g179 +tp43297 +Rp43298 +(I1 +(I1 +I1 +I1 +tp43299 +g38 +I00 +S'\x9a\x0e\xd9\xd0zy\x9e?' +p43300 +tp43301 +bsg252 +g513 +sg48 +(lp43302 +g0 +(g52 +g2 +Ntp43303 +Rp43304 +(dp43305 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp43306 +g179 +tp43307 +Rp43308 +(I1 +(I1 +I1 +I1 +tp43309 +g38 +I00 +S'D\x9e\xd8Zjm\x05@' +p43310 +tp43311 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp43312 +g664 +asg113 +I11406 +sg280 +I01 +sbaa(lp43313 +g666 +ag0 +(g190 +g2 +Ntp43314 +Rp43315 +(dp43316 +g194 +I01 +sg195 +(lp43317 +g0 +(g197 +g2 +Ntp43318 +Rp43319 +(dp43320 +g201 +g176 +(g177 +(I0 +tp43321 +g179 +tp43322 +Rp43323 +(I1 +(I1 +tp43324 +g208 +I00 +S"h'\x00\x00\x00\x00\x00\x00" +p43325 +tp43326 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43327 +Rp43328 +(dp43329 +g201 +g176 +(g177 +(I0 +tp43330 +g179 +tp43331 +Rp43332 +(I1 +(I2 +tp43333 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43334 +tp43335 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp43336 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43337 +g179 +tp43338 +Rp43339 +(I1 +(I1 +I1 +I1 +tp43340 +g38 +I00 +S'9V\x00\xa7\xdb\x81\xb4?' +p43341 +tp43342 +bsg238 +g176 +(g177 +(I0 +tp43343 +g179 +tp43344 +Rp43345 +(I1 +(I1 +I1 +I1 +tp43346 +g38 +I00 +S'\xfa=Pi\x98"-?' +p43347 +tp43348 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43349 +g179 +tp43350 +Rp43351 +(I1 +(I1 +I1 +I1 +tp43352 +g38 +I00 +S'\x9b\x0e\xd9\xd0zy\x9e?' +p43353 +tp43354 +bsg252 +g713 +sg48 +(lp43355 +g0 +(g52 +g2 +Ntp43356 +Rp43357 +(dp43358 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp43359 +g179 +tp43360 +Rp43361 +(I1 +(I1 +I1 +I1 +tp43362 +g38 +I00 +S'E\x9e\xd8Zjm\x05@' +p43363 +tp43364 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp43365 +g727 +asg113 +I11407 +sg280 +I01 +sbaatp43366 +Rp43367 +sg337 +I00 +sg338 +Nsbaatp43368 +Rp43369 +aa(lp43370 +I10089 +ag7 +((lp43371 +(lp43372 +g12 +ag0 +(g13 +g2 +Ntp43373 +Rp43374 +(dp43375 +g17 +g0 +(g18 +g2 +Ntp43376 +Rp43377 +(dp43378 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p43379 +sg116 +g0 +(g117 +g2 +Ntp43380 +Rp43381 +(dp43382 +g121 +(lp43383 +g0 +(g123 +g2 +Ntp43384 +Rp43385 +(dp43386 +g127 +g39529 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp43387 +Rp43388 +(dp43389 +g127 +g0 +(g128 +g2 +Ntp43390 +Rp43391 +(dp43392 +g23 +g132 +sg133 +(dp43393 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xf6(\\\x8f\xc2\xf5\t@' +p43394 +tp43395 +Rp43396 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p43397 +sg113 +I103 +sg146 +(lp43398 +g138 +asbsg148 +g149 +sbasbsg163 +Nsg113 +I10089 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43399 +(lp43400 +g189 +ag0 +(g190 +g2 +Ntp43401 +Rp43402 +(dp43403 +g194 +I01 +sg195 +(lp43404 +g0 +(g197 +g2 +Ntp43405 +Rp43406 +(dp43407 +g201 +g176 +(g177 +(I0 +tp43408 +g179 +tp43409 +Rp43410 +(I1 +(I1 +tp43411 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43412 +tp43413 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43414 +Rp43415 +(dp43416 +g201 +g176 +(g177 +(I0 +tp43417 +g179 +tp43418 +Rp43419 +(I1 +(I2 +tp43420 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43421 +tp43422 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43423 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43424 +g179 +tp43425 +Rp43426 +(I1 +(I1 +I1 +I1 +tp43427 +g38 +I00 +S'dH\xab\xcc\xa0\x8fF@' +p43428 +tp43429 +bsg238 +g176 +(g177 +(I0 +tp43430 +g179 +tp43431 +Rp43432 +(I1 +(I1 +I1 +I1 +tp43433 +g38 +I00 +S'\x03i\xf4\x89\xb0KD?' +p43434 +tp43435 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43436 +g179 +tp43437 +Rp43438 +(I1 +(I1 +I1 +I1 +tp43439 +g38 +I00 +S'\xf3\xe6\xf03F\xa8\xe6?' +p43440 +tp43441 +bsg252 +g260 +sg48 +(lp43442 +g0 +(g52 +g2 +Ntp43443 +Rp43444 +(dp43445 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43446 +g179 +tp43447 +Rp43448 +(I1 +(I1 +I1 +I1 +tp43449 +g38 +I00 +S'\xc6\xc4\n\xb9\xa2\xdcO@' +p43450 +tp43451 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43452 +g279 +asg113 +I11410 +sg280 +I01 +sbaa(lp43453 +g12 +ag0 +(g190 +g2 +Ntp43454 +Rp43455 +(dp43456 +g194 +I01 +sg195 +(lp43457 +g0 +(g197 +g2 +Ntp43458 +Rp43459 +(dp43460 +g201 +g176 +(g177 +(I0 +tp43461 +g179 +tp43462 +Rp43463 +(I1 +(I1 +tp43464 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43465 +tp43466 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43467 +Rp43468 +(dp43469 +g201 +g176 +(g177 +(I0 +tp43470 +g179 +tp43471 +Rp43472 +(I1 +(I2 +tp43473 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43474 +tp43475 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43476 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43477 +g179 +tp43478 +Rp43479 +(I1 +(I1 +I1 +I1 +tp43480 +g38 +I00 +S'\xc8\xd0;\x82\xa4\xd9D@' +p43481 +tp43482 +bsg238 +g176 +(g177 +(I0 +tp43483 +g179 +tp43484 +Rp43485 +(I1 +(I1 +I1 +I1 +tp43486 +g38 +I00 +S'\xee\x86\x87Kw\xd9K?' +p43487 +tp43488 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43489 +g179 +tp43490 +Rp43491 +(I1 +(I1 +I1 +I1 +tp43492 +g38 +I00 +S'\x1ce\xe6\x84\xd0\xc7\xe5?' +p43493 +tp43494 +bsg252 +g260 +sg48 +(lp43495 +g0 +(g52 +g2 +Ntp43496 +Rp43497 +(dp43498 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43499 +g179 +tp43500 +Rp43501 +(I1 +(I1 +I1 +I1 +tp43502 +g38 +I00 +S'/\xfe\xe3:\xfd\xa0N@' +p43503 +tp43504 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43505 +g334 +asg113 +I11411 +sg280 +I01 +sbaatp43506 +Rp43507 +sg337 +I00 +sg338 +Nsbaa(lp43508 +g340 +ag0 +(g341 +g2 +Ntp43509 +Rp43510 +(dp43511 +g17 +g43377 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43512 +(lp43513 +g189 +ag0 +(g190 +g2 +Ntp43514 +Rp43515 +(dp43516 +g194 +I01 +sg195 +(lp43517 +g0 +(g197 +g2 +Ntp43518 +Rp43519 +(dp43520 +g201 +g176 +(g177 +(I0 +tp43521 +g179 +tp43522 +Rp43523 +(I1 +(I1 +tp43524 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43525 +tp43526 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43527 +Rp43528 +(dp43529 +g201 +g176 +(g177 +(I0 +tp43530 +g179 +tp43531 +Rp43532 +(I1 +(I2 +tp43533 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43534 +tp43535 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43536 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43537 +g179 +tp43538 +Rp43539 +(I1 +(I1 +I1 +I1 +tp43540 +g38 +I00 +S'dH\xab\xcc\xa0\x8fF@' +p43541 +tp43542 +bsg238 +g176 +(g177 +(I0 +tp43543 +g179 +tp43544 +Rp43545 +(I1 +(I1 +I1 +I1 +tp43546 +g38 +I00 +S'\x03i\xf4\x89\xb0KD?' +p43547 +tp43548 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43549 +g179 +tp43550 +Rp43551 +(I1 +(I1 +I1 +I1 +tp43552 +g38 +I00 +S'\xf3\xe6\xf03F\xa8\xe6?' +p43553 +tp43554 +bsg252 +g260 +sg48 +(lp43555 +g0 +(g52 +g2 +Ntp43556 +Rp43557 +(dp43558 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43559 +g179 +tp43560 +Rp43561 +(I1 +(I1 +I1 +I1 +tp43562 +g38 +I00 +S'\xc6\xc4\n\xb9\xa2\xdcO@' +p43563 +tp43564 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43565 +g279 +asg113 +I11414 +sg280 +I01 +sbaa(lp43566 +g401 +ag0 +(g190 +g2 +Ntp43567 +Rp43568 +(dp43569 +g194 +I01 +sg195 +(lp43570 +g0 +(g197 +g2 +Ntp43571 +Rp43572 +(dp43573 +g201 +g176 +(g177 +(I0 +tp43574 +g179 +tp43575 +Rp43576 +(I1 +(I1 +tp43577 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43578 +tp43579 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43580 +Rp43581 +(dp43582 +g201 +g176 +(g177 +(I0 +tp43583 +g179 +tp43584 +Rp43585 +(I1 +(I2 +tp43586 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43587 +tp43588 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43589 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43590 +g179 +tp43591 +Rp43592 +(I1 +(I1 +I1 +I1 +tp43593 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43594 +tp43595 +bsg238 +g176 +(g177 +(I0 +tp43596 +g179 +tp43597 +Rp43598 +(I1 +(I1 +I1 +I1 +tp43599 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43600 +tp43601 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43602 +g179 +tp43603 +Rp43604 +(I1 +(I1 +I1 +I1 +tp43605 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43606 +tp43607 +bsg252 +g260 +sg48 +(lp43608 +g0 +(g52 +g2 +Ntp43609 +Rp43610 +(dp43611 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43612 +g179 +tp43613 +Rp43614 +(I1 +(I1 +I1 +I1 +tp43615 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43616 +tp43617 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43618 +g454 +asg113 +I11415 +sg280 +I01 +sbaatp43619 +Rp43620 +sg337 +I00 +sg338 +Nsbaa(lp43621 +g458 +ag0 +(g459 +g2 +Ntp43622 +Rp43623 +(dp43624 +g17 +g43377 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43625 +(lp43626 +g189 +ag0 +(g190 +g2 +Ntp43627 +Rp43628 +(dp43629 +g194 +I01 +sg195 +(lp43630 +g0 +(g197 +g2 +Ntp43631 +Rp43632 +(dp43633 +g201 +g176 +(g177 +(I0 +tp43634 +g179 +tp43635 +Rp43636 +(I1 +(I1 +tp43637 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43638 +tp43639 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43640 +Rp43641 +(dp43642 +g201 +g176 +(g177 +(I0 +tp43643 +g179 +tp43644 +Rp43645 +(I1 +(I2 +tp43646 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43647 +tp43648 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp43649 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43650 +g179 +tp43651 +Rp43652 +(I1 +(I1 +I1 +I1 +tp43653 +g38 +I00 +S'\xb2d5\x97G\xb2F@' +p43654 +tp43655 +bsg238 +g176 +(g177 +(I0 +tp43656 +g179 +tp43657 +Rp43658 +(I1 +(I1 +I1 +I1 +tp43659 +g38 +I00 +S'\xd9\x151Y\xe03Z?' +p43660 +tp43661 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43662 +g179 +tp43663 +Rp43664 +(I1 +(I1 +I1 +I1 +tp43665 +g38 +I00 +S'\x16\xe1\xeap\x88\xb8\xe6?' +p43666 +tp43667 +bsg252 +g513 +sg48 +(lp43668 +g0 +(g52 +g2 +Ntp43669 +Rp43670 +(dp43671 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp43672 +g179 +tp43673 +Rp43674 +(I1 +(I1 +I1 +I1 +tp43675 +g38 +I00 +S'\x87L\xca\xde\x7f\xf3O@' +p43676 +tp43677 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp43678 +g527 +asg113 +I11418 +sg280 +I01 +sbaa(lp43679 +g529 +ag0 +(g190 +g2 +Ntp43680 +Rp43681 +(dp43682 +g194 +I01 +sg195 +(lp43683 +g0 +(g197 +g2 +Ntp43684 +Rp43685 +(dp43686 +g201 +g176 +(g177 +(I0 +tp43687 +g179 +tp43688 +Rp43689 +(I1 +(I1 +tp43690 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43691 +tp43692 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43693 +Rp43694 +(dp43695 +g201 +g176 +(g177 +(I0 +tp43696 +g179 +tp43697 +Rp43698 +(I1 +(I2 +tp43699 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43700 +tp43701 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43702 +Rp43703 +(dp43704 +g201 +g176 +(g177 +(I0 +tp43705 +g179 +tp43706 +Rp43707 +(I1 +(I2 +tp43708 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43709 +tp43710 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp43711 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43712 +g179 +tp43713 +Rp43714 +(I1 +(I1 +I1 +I1 +tp43715 +g38 +I00 +S'\xebd6\xe92\x85D@' +p43716 +tp43717 +bsg238 +g176 +(g177 +(I0 +tp43718 +g179 +tp43719 +Rp43720 +(I1 +(I1 +I1 +I1 +tp43721 +g38 +I00 +S'xl\x83\x17\xc2\x9bR?' +p43722 +tp43723 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43724 +g179 +tp43725 +Rp43726 +(I1 +(I1 +I1 +I1 +tp43727 +g38 +I00 +S'\xd5e\xbc^8\x9b\xe5?' +p43728 +tp43729 +bsg252 +g586 +sg48 +(lp43730 +g0 +(g52 +g2 +Ntp43731 +Rp43732 +(dp43733 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp43734 +g179 +tp43735 +Rp43736 +(I1 +(I1 +I1 +I1 +tp43737 +g38 +I00 +S'3\xef8EGbN@' +p43738 +tp43739 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp43740 +g600 +asg113 +I11419 +sg280 +I01 +sbaatp43741 +Rp43742 +sg337 +I00 +sg338 +Nsbaa(lp43743 +g604 +ag0 +(g605 +g2 +Ntp43744 +Rp43745 +(dp43746 +g17 +g43377 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43747 +(lp43748 +g611 +ag0 +(g190 +g2 +Ntp43749 +Rp43750 +(dp43751 +g194 +I01 +sg195 +(lp43752 +g0 +(g197 +g2 +Ntp43753 +Rp43754 +(dp43755 +g201 +g176 +(g177 +(I0 +tp43756 +g179 +tp43757 +Rp43758 +(I1 +(I1 +tp43759 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43760 +tp43761 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43762 +Rp43763 +(dp43764 +g201 +g176 +(g177 +(I0 +tp43765 +g179 +tp43766 +Rp43767 +(I1 +(I2 +tp43768 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43769 +tp43770 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp43771 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43772 +g179 +tp43773 +Rp43774 +(I1 +(I1 +I1 +I1 +tp43775 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43776 +tp43777 +bsg238 +g176 +(g177 +(I0 +tp43778 +g179 +tp43779 +Rp43780 +(I1 +(I1 +I1 +I1 +tp43781 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43782 +tp43783 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43784 +g179 +tp43785 +Rp43786 +(I1 +(I1 +I1 +I1 +tp43787 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43788 +tp43789 +bsg252 +g513 +sg48 +(lp43790 +g0 +(g52 +g2 +Ntp43791 +Rp43792 +(dp43793 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp43794 +g179 +tp43795 +Rp43796 +(I1 +(I1 +I1 +I1 +tp43797 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43798 +tp43799 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp43800 +g664 +asg113 +I11422 +sg280 +I01 +sbaa(lp43801 +g666 +ag0 +(g190 +g2 +Ntp43802 +Rp43803 +(dp43804 +g194 +I01 +sg195 +(lp43805 +g0 +(g197 +g2 +Ntp43806 +Rp43807 +(dp43808 +g201 +g176 +(g177 +(I0 +tp43809 +g179 +tp43810 +Rp43811 +(I1 +(I1 +tp43812 +g208 +I00 +S"i'\x00\x00\x00\x00\x00\x00" +p43813 +tp43814 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43815 +Rp43816 +(dp43817 +g201 +g176 +(g177 +(I0 +tp43818 +g179 +tp43819 +Rp43820 +(I1 +(I2 +tp43821 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43822 +tp43823 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp43824 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43825 +g179 +tp43826 +Rp43827 +(I1 +(I1 +I1 +I1 +tp43828 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43829 +tp43830 +bsg238 +g176 +(g177 +(I0 +tp43831 +g179 +tp43832 +Rp43833 +(I1 +(I1 +I1 +I1 +tp43834 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43835 +tp43836 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43837 +g179 +tp43838 +Rp43839 +(I1 +(I1 +I1 +I1 +tp43840 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43841 +tp43842 +bsg252 +g713 +sg48 +(lp43843 +g0 +(g52 +g2 +Ntp43844 +Rp43845 +(dp43846 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp43847 +g179 +tp43848 +Rp43849 +(I1 +(I1 +I1 +I1 +tp43850 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p43851 +tp43852 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp43853 +g727 +asg113 +I11423 +sg280 +I01 +sbaatp43854 +Rp43855 +sg337 +I00 +sg338 +Nsbaatp43856 +Rp43857 +aa(lp43858 +I10090 +ag7 +((lp43859 +(lp43860 +g12 +ag0 +(g13 +g2 +Ntp43861 +Rp43862 +(dp43863 +g17 +g0 +(g18 +g2 +Ntp43864 +Rp43865 +(dp43866 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p43867 +sg116 +g0 +(g117 +g2 +Ntp43868 +Rp43869 +(dp43870 +g121 +(lp43871 +g0 +(g123 +g2 +Ntp43872 +Rp43873 +(dp43874 +g127 +g31287 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp43875 +Rp43876 +(dp43877 +g127 +g17641 +sg148 +g149 +sbasbsg163 +Nsg113 +I10090 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43878 +(lp43879 +g189 +ag0 +(g190 +g2 +Ntp43880 +Rp43881 +(dp43882 +g194 +I01 +sg195 +(lp43883 +g0 +(g197 +g2 +Ntp43884 +Rp43885 +(dp43886 +g201 +g176 +(g177 +(I0 +tp43887 +g179 +tp43888 +Rp43889 +(I1 +(I1 +tp43890 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p43891 +tp43892 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43893 +Rp43894 +(dp43895 +g201 +g176 +(g177 +(I0 +tp43896 +g179 +tp43897 +Rp43898 +(I1 +(I2 +tp43899 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43900 +tp43901 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43902 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43903 +g179 +tp43904 +Rp43905 +(I1 +(I1 +I1 +I1 +tp43906 +g38 +I00 +S"\x9cQ'\xc1=\x1b\r@" +p43907 +tp43908 +bsg238 +g176 +(g177 +(I0 +tp43909 +g179 +tp43910 +Rp43911 +(I1 +(I1 +I1 +I1 +tp43912 +g38 +I00 +S'\x0c)\x95\xbay\xde-?' +p43913 +tp43914 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43915 +g179 +tp43916 +Rp43917 +(I1 +(I1 +I1 +I1 +tp43918 +g38 +I00 +S'\x80)\x15p\xfe\xbb\xc9?' +p43919 +tp43920 +bsg252 +g260 +sg48 +(lp43921 +g0 +(g52 +g2 +Ntp43922 +Rp43923 +(dp43924 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43925 +g179 +tp43926 +Rp43927 +(I1 +(I1 +I1 +I1 +tp43928 +g38 +I00 +S'.\xe1\xce\xe6.\x182@' +p43929 +tp43930 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43931 +g279 +asg113 +I11426 +sg280 +I01 +sbaa(lp43932 +g12 +ag0 +(g190 +g2 +Ntp43933 +Rp43934 +(dp43935 +g194 +I01 +sg195 +(lp43936 +g0 +(g197 +g2 +Ntp43937 +Rp43938 +(dp43939 +g201 +g176 +(g177 +(I0 +tp43940 +g179 +tp43941 +Rp43942 +(I1 +(I1 +tp43943 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p43944 +tp43945 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp43946 +Rp43947 +(dp43948 +g201 +g176 +(g177 +(I0 +tp43949 +g179 +tp43950 +Rp43951 +(I1 +(I2 +tp43952 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p43953 +tp43954 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp43955 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp43956 +g179 +tp43957 +Rp43958 +(I1 +(I1 +I1 +I1 +tp43959 +g38 +I00 +S'\x08\x04Zy\xa8\xee\xd6?' +p43960 +tp43961 +bsg238 +g176 +(g177 +(I0 +tp43962 +g179 +tp43963 +Rp43964 +(I1 +(I1 +I1 +I1 +tp43965 +g38 +I00 +S'\xa61\xd0\xeb\x94A\x14?' +p43966 +tp43967 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp43968 +g179 +tp43969 +Rp43970 +(I1 +(I1 +I1 +I1 +tp43971 +g38 +I00 +S'\xab\x1fK\xc7\xe1&\xb0?' +p43972 +tp43973 +bsg252 +g260 +sg48 +(lp43974 +g0 +(g52 +g2 +Ntp43975 +Rp43976 +(dp43977 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp43978 +g179 +tp43979 +Rp43980 +(I1 +(I1 +I1 +I1 +tp43981 +g38 +I00 +S'\x88\xa4A\x80\xad\xb6\x16@' +p43982 +tp43983 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp43984 +g334 +asg113 +I11427 +sg280 +I01 +sbaatp43985 +Rp43986 +sg337 +I00 +sg338 +Nsbaa(lp43987 +g340 +ag0 +(g341 +g2 +Ntp43988 +Rp43989 +(dp43990 +g17 +g43865 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp43991 +(lp43992 +g189 +ag0 +(g190 +g2 +Ntp43993 +Rp43994 +(dp43995 +g194 +I01 +sg195 +(lp43996 +g0 +(g197 +g2 +Ntp43997 +Rp43998 +(dp43999 +g201 +g176 +(g177 +(I0 +tp44000 +g179 +tp44001 +Rp44002 +(I1 +(I1 +tp44003 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44004 +tp44005 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44006 +Rp44007 +(dp44008 +g201 +g176 +(g177 +(I0 +tp44009 +g179 +tp44010 +Rp44011 +(I1 +(I2 +tp44012 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44013 +tp44014 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44015 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44016 +g179 +tp44017 +Rp44018 +(I1 +(I1 +I1 +I1 +tp44019 +g38 +I00 +S"\x9cQ'\xc1=\x1b\r@" +p44020 +tp44021 +bsg238 +g176 +(g177 +(I0 +tp44022 +g179 +tp44023 +Rp44024 +(I1 +(I1 +I1 +I1 +tp44025 +g38 +I00 +S'\x0c)\x95\xbay\xde-?' +p44026 +tp44027 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44028 +g179 +tp44029 +Rp44030 +(I1 +(I1 +I1 +I1 +tp44031 +g38 +I00 +S'\x80)\x15p\xfe\xbb\xc9?' +p44032 +tp44033 +bsg252 +g260 +sg48 +(lp44034 +g0 +(g52 +g2 +Ntp44035 +Rp44036 +(dp44037 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44038 +g179 +tp44039 +Rp44040 +(I1 +(I1 +I1 +I1 +tp44041 +g38 +I00 +S'.\xe1\xce\xe6.\x182@' +p44042 +tp44043 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44044 +g279 +asg113 +I11430 +sg280 +I01 +sbaa(lp44045 +g401 +ag0 +(g190 +g2 +Ntp44046 +Rp44047 +(dp44048 +g194 +I01 +sg195 +(lp44049 +g0 +(g197 +g2 +Ntp44050 +Rp44051 +(dp44052 +g201 +g176 +(g177 +(I0 +tp44053 +g179 +tp44054 +Rp44055 +(I1 +(I1 +tp44056 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44057 +tp44058 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44059 +Rp44060 +(dp44061 +g201 +g176 +(g177 +(I0 +tp44062 +g179 +tp44063 +Rp44064 +(I1 +(I2 +tp44065 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44066 +tp44067 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44068 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44069 +g179 +tp44070 +Rp44071 +(I1 +(I1 +I1 +I1 +tp44072 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44073 +tp44074 +bsg238 +g176 +(g177 +(I0 +tp44075 +g179 +tp44076 +Rp44077 +(I1 +(I1 +I1 +I1 +tp44078 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44079 +tp44080 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44081 +g179 +tp44082 +Rp44083 +(I1 +(I1 +I1 +I1 +tp44084 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44085 +tp44086 +bsg252 +g260 +sg48 +(lp44087 +g0 +(g52 +g2 +Ntp44088 +Rp44089 +(dp44090 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44091 +g179 +tp44092 +Rp44093 +(I1 +(I1 +I1 +I1 +tp44094 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44095 +tp44096 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44097 +g454 +asg113 +I11431 +sg280 +I01 +sbaatp44098 +Rp44099 +sg337 +I00 +sg338 +Nsbaa(lp44100 +g458 +ag0 +(g459 +g2 +Ntp44101 +Rp44102 +(dp44103 +g17 +g43865 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44104 +(lp44105 +g189 +ag0 +(g190 +g2 +Ntp44106 +Rp44107 +(dp44108 +g194 +I01 +sg195 +(lp44109 +g0 +(g197 +g2 +Ntp44110 +Rp44111 +(dp44112 +g201 +g176 +(g177 +(I0 +tp44113 +g179 +tp44114 +Rp44115 +(I1 +(I1 +tp44116 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44117 +tp44118 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44119 +Rp44120 +(dp44121 +g201 +g176 +(g177 +(I0 +tp44122 +g179 +tp44123 +Rp44124 +(I1 +(I2 +tp44125 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44126 +tp44127 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp44128 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44129 +g179 +tp44130 +Rp44131 +(I1 +(I1 +I1 +I1 +tp44132 +g38 +I00 +S'\x04\xe8\xf3\xbcA\xf5\x0c@' +p44133 +tp44134 +bsg238 +g176 +(g177 +(I0 +tp44135 +g179 +tp44136 +Rp44137 +(I1 +(I1 +I1 +I1 +tp44138 +g38 +I00 +S']i\xcf\xbf\xcb\xf7K?' +p44139 +tp44140 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44141 +g179 +tp44142 +Rp44143 +(I1 +(I1 +I1 +I1 +tp44144 +g38 +I00 +S'st!\xdcA\xa6\xc9?' +p44145 +tp44146 +bsg252 +g513 +sg48 +(lp44147 +g0 +(g52 +g2 +Ntp44148 +Rp44149 +(dp44150 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp44151 +g179 +tp44152 +Rp44153 +(I1 +(I1 +I1 +I1 +tp44154 +g38 +I00 +S'\xe1\x85\xc7N\xe6\x082@' +p44155 +tp44156 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp44157 +g527 +asg113 +I11434 +sg280 +I01 +sbaa(lp44158 +g529 +ag0 +(g190 +g2 +Ntp44159 +Rp44160 +(dp44161 +g194 +I01 +sg195 +(lp44162 +g0 +(g197 +g2 +Ntp44163 +Rp44164 +(dp44165 +g201 +g176 +(g177 +(I0 +tp44166 +g179 +tp44167 +Rp44168 +(I1 +(I1 +tp44169 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44170 +tp44171 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44172 +Rp44173 +(dp44174 +g201 +g176 +(g177 +(I0 +tp44175 +g179 +tp44176 +Rp44177 +(I1 +(I2 +tp44178 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44179 +tp44180 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44181 +Rp44182 +(dp44183 +g201 +g176 +(g177 +(I0 +tp44184 +g179 +tp44185 +Rp44186 +(I1 +(I2 +tp44187 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44188 +tp44189 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp44190 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44191 +g179 +tp44192 +Rp44193 +(I1 +(I1 +I1 +I1 +tp44194 +g38 +I00 +S'\xb7\xc5O%\xfb\x8e\xd6?' +p44195 +tp44196 +bsg238 +g176 +(g177 +(I0 +tp44197 +g179 +tp44198 +Rp44199 +(I1 +(I1 +I1 +I1 +tp44200 +g38 +I00 +S'\xb9C">\xa5\xf61?' +p44201 +tp44202 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44203 +g179 +tp44204 +Rp44205 +(I1 +(I1 +I1 +I1 +tp44206 +g38 +I00 +S'\x11\xa9\xa5\x08\xd2\x01\xb0?' +p44207 +tp44208 +bsg252 +g586 +sg48 +(lp44209 +g0 +(g52 +g2 +Ntp44210 +Rp44211 +(dp44212 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp44213 +g179 +tp44214 +Rp44215 +(I1 +(I1 +I1 +I1 +tp44216 +g38 +I00 +S'\xc0\xf5(\\\x8f\x82\x16@' +p44217 +tp44218 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp44219 +g600 +asg113 +I11435 +sg280 +I01 +sbaatp44220 +Rp44221 +sg337 +I00 +sg338 +Nsbaa(lp44222 +g604 +ag0 +(g605 +g2 +Ntp44223 +Rp44224 +(dp44225 +g17 +g43865 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44226 +(lp44227 +g611 +ag0 +(g190 +g2 +Ntp44228 +Rp44229 +(dp44230 +g194 +I01 +sg195 +(lp44231 +g0 +(g197 +g2 +Ntp44232 +Rp44233 +(dp44234 +g201 +g176 +(g177 +(I0 +tp44235 +g179 +tp44236 +Rp44237 +(I1 +(I1 +tp44238 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44239 +tp44240 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44241 +Rp44242 +(dp44243 +g201 +g176 +(g177 +(I0 +tp44244 +g179 +tp44245 +Rp44246 +(I1 +(I2 +tp44247 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44248 +tp44249 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp44250 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44251 +g179 +tp44252 +Rp44253 +(I1 +(I1 +I1 +I1 +tp44254 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44255 +tp44256 +bsg238 +g176 +(g177 +(I0 +tp44257 +g179 +tp44258 +Rp44259 +(I1 +(I1 +I1 +I1 +tp44260 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44261 +tp44262 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44263 +g179 +tp44264 +Rp44265 +(I1 +(I1 +I1 +I1 +tp44266 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44267 +tp44268 +bsg252 +g513 +sg48 +(lp44269 +g0 +(g52 +g2 +Ntp44270 +Rp44271 +(dp44272 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp44273 +g179 +tp44274 +Rp44275 +(I1 +(I1 +I1 +I1 +tp44276 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44277 +tp44278 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp44279 +g664 +asg113 +I11438 +sg280 +I01 +sbaa(lp44280 +g666 +ag0 +(g190 +g2 +Ntp44281 +Rp44282 +(dp44283 +g194 +I01 +sg195 +(lp44284 +g0 +(g197 +g2 +Ntp44285 +Rp44286 +(dp44287 +g201 +g176 +(g177 +(I0 +tp44288 +g179 +tp44289 +Rp44290 +(I1 +(I1 +tp44291 +g208 +I00 +S"j'\x00\x00\x00\x00\x00\x00" +p44292 +tp44293 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44294 +Rp44295 +(dp44296 +g201 +g176 +(g177 +(I0 +tp44297 +g179 +tp44298 +Rp44299 +(I1 +(I2 +tp44300 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44301 +tp44302 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp44303 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44304 +g179 +tp44305 +Rp44306 +(I1 +(I1 +I1 +I1 +tp44307 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44308 +tp44309 +bsg238 +g176 +(g177 +(I0 +tp44310 +g179 +tp44311 +Rp44312 +(I1 +(I1 +I1 +I1 +tp44313 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44314 +tp44315 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44316 +g179 +tp44317 +Rp44318 +(I1 +(I1 +I1 +I1 +tp44319 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44320 +tp44321 +bsg252 +g713 +sg48 +(lp44322 +g0 +(g52 +g2 +Ntp44323 +Rp44324 +(dp44325 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp44326 +g179 +tp44327 +Rp44328 +(I1 +(I1 +I1 +I1 +tp44329 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44330 +tp44331 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp44332 +g727 +asg113 +I11439 +sg280 +I01 +sbaatp44333 +Rp44334 +sg337 +I00 +sg338 +Nsbaatp44335 +Rp44336 +aa(lp44337 +I10091 +ag7 +((lp44338 +(lp44339 +g12 +ag0 +(g13 +g2 +Ntp44340 +Rp44341 +(dp44342 +g17 +g0 +(g18 +g2 +Ntp44343 +Rp44344 +(dp44345 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p44346 +sg116 +g0 +(g117 +g2 +Ntp44347 +Rp44348 +(dp44349 +g121 +(lp44350 +g0 +(g123 +g2 +Ntp44351 +Rp44352 +(dp44353 +g127 +g0 +(g128 +g2 +Ntp44354 +Rp44355 +(dp44356 +g23 +g132 +sg133 +(dp44357 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\n\xd7\xa3p=\n\x0c@' +p44358 +tp44359 +Rp44360 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p44361 +sg113 +I104 +sg146 +(lp44362 +g138 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp44363 +Rp44364 +(dp44365 +g127 +g16162 +sg148 +g149 +sbasbsg163 +Nsg113 +I10091 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44366 +(lp44367 +g189 +ag0 +(g190 +g2 +Ntp44368 +Rp44369 +(dp44370 +g194 +I01 +sg195 +(lp44371 +g0 +(g197 +g2 +Ntp44372 +Rp44373 +(dp44374 +g201 +g176 +(g177 +(I0 +tp44375 +g179 +tp44376 +Rp44377 +(I1 +(I1 +tp44378 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44379 +tp44380 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44381 +Rp44382 +(dp44383 +g201 +g176 +(g177 +(I0 +tp44384 +g179 +tp44385 +Rp44386 +(I1 +(I2 +tp44387 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44388 +tp44389 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44390 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44391 +g179 +tp44392 +Rp44393 +(I1 +(I1 +I1 +I1 +tp44394 +g38 +I00 +S'\xc6Q\x90\xba\x92\x9eG@' +p44395 +tp44396 +bsg238 +g176 +(g177 +(I0 +tp44397 +g179 +tp44398 +Rp44399 +(I1 +(I1 +I1 +I1 +tp44400 +g38 +I00 +S'\xd97J\xa8\x19fE?' +p44401 +tp44402 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44403 +g179 +tp44404 +Rp44405 +(I1 +(I1 +I1 +I1 +tp44406 +g38 +I00 +S'\x97p\x17\xcc\xc0.\xe7?' +p44407 +tp44408 +bsg252 +g260 +sg48 +(lp44409 +g0 +(g52 +g2 +Ntp44410 +Rp44411 +(dp44412 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44413 +g179 +tp44414 +Rp44415 +(I1 +(I1 +I1 +I1 +tp44416 +g38 +I00 +S'*{\x80\x8f\xdfLP@' +p44417 +tp44418 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44419 +g279 +asg113 +I11442 +sg280 +I01 +sbaa(lp44420 +g12 +ag0 +(g190 +g2 +Ntp44421 +Rp44422 +(dp44423 +g194 +I01 +sg195 +(lp44424 +g0 +(g197 +g2 +Ntp44425 +Rp44426 +(dp44427 +g201 +g176 +(g177 +(I0 +tp44428 +g179 +tp44429 +Rp44430 +(I1 +(I1 +tp44431 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44432 +tp44433 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44434 +Rp44435 +(dp44436 +g201 +g176 +(g177 +(I0 +tp44437 +g179 +tp44438 +Rp44439 +(I1 +(I2 +tp44440 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44441 +tp44442 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44443 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44444 +g179 +tp44445 +Rp44446 +(I1 +(I1 +I1 +I1 +tp44447 +g38 +I00 +S'\x00\xde \x94\x83\x1eH@' +p44448 +tp44449 +bsg238 +g176 +(g177 +(I0 +tp44450 +g179 +tp44451 +Rp44452 +(I1 +(I1 +I1 +I1 +tp44453 +g38 +I00 +S'F<\xdf\x92:\xb0O?' +p44454 +tp44455 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44456 +g179 +tp44457 +Rp44458 +(I1 +(I1 +I1 +I1 +tp44459 +g38 +I00 +S'\xc31\xc9\x87\xf6l\xe7?' +p44460 +tp44461 +bsg252 +g260 +sg48 +(lp44462 +g0 +(g52 +g2 +Ntp44463 +Rp44464 +(dp44465 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44466 +g179 +tp44467 +Rp44468 +(I1 +(I1 +I1 +I1 +tp44469 +g38 +I00 +S'\xfdvyW\x9dxP@' +p44470 +tp44471 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44472 +g334 +asg113 +I11443 +sg280 +I01 +sbaatp44473 +Rp44474 +sg337 +I00 +sg338 +Nsbaa(lp44475 +g340 +ag0 +(g341 +g2 +Ntp44476 +Rp44477 +(dp44478 +g17 +g44344 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44479 +(lp44480 +g189 +ag0 +(g190 +g2 +Ntp44481 +Rp44482 +(dp44483 +g194 +I01 +sg195 +(lp44484 +g0 +(g197 +g2 +Ntp44485 +Rp44486 +(dp44487 +g201 +g176 +(g177 +(I0 +tp44488 +g179 +tp44489 +Rp44490 +(I1 +(I1 +tp44491 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44492 +tp44493 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44494 +Rp44495 +(dp44496 +g201 +g176 +(g177 +(I0 +tp44497 +g179 +tp44498 +Rp44499 +(I1 +(I2 +tp44500 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44501 +tp44502 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44503 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44504 +g179 +tp44505 +Rp44506 +(I1 +(I1 +I1 +I1 +tp44507 +g38 +I00 +S'\xc6Q\x90\xba\x92\x9eG@' +p44508 +tp44509 +bsg238 +g176 +(g177 +(I0 +tp44510 +g179 +tp44511 +Rp44512 +(I1 +(I1 +I1 +I1 +tp44513 +g38 +I00 +S'\xd97J\xa8\x19fE?' +p44514 +tp44515 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44516 +g179 +tp44517 +Rp44518 +(I1 +(I1 +I1 +I1 +tp44519 +g38 +I00 +S'\x97p\x17\xcc\xc0.\xe7?' +p44520 +tp44521 +bsg252 +g260 +sg48 +(lp44522 +g0 +(g52 +g2 +Ntp44523 +Rp44524 +(dp44525 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44526 +g179 +tp44527 +Rp44528 +(I1 +(I1 +I1 +I1 +tp44529 +g38 +I00 +S'*{\x80\x8f\xdfLP@' +p44530 +tp44531 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44532 +g279 +asg113 +I11446 +sg280 +I01 +sbaa(lp44533 +g401 +ag0 +(g190 +g2 +Ntp44534 +Rp44535 +(dp44536 +g194 +I01 +sg195 +(lp44537 +g0 +(g197 +g2 +Ntp44538 +Rp44539 +(dp44540 +g201 +g176 +(g177 +(I0 +tp44541 +g179 +tp44542 +Rp44543 +(I1 +(I1 +tp44544 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44545 +tp44546 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44547 +Rp44548 +(dp44549 +g201 +g176 +(g177 +(I0 +tp44550 +g179 +tp44551 +Rp44552 +(I1 +(I2 +tp44553 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44554 +tp44555 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44556 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44557 +g179 +tp44558 +Rp44559 +(I1 +(I1 +I1 +I1 +tp44560 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44561 +tp44562 +bsg238 +g176 +(g177 +(I0 +tp44563 +g179 +tp44564 +Rp44565 +(I1 +(I1 +I1 +I1 +tp44566 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44567 +tp44568 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44569 +g179 +tp44570 +Rp44571 +(I1 +(I1 +I1 +I1 +tp44572 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44573 +tp44574 +bsg252 +g260 +sg48 +(lp44575 +g0 +(g52 +g2 +Ntp44576 +Rp44577 +(dp44578 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44579 +g179 +tp44580 +Rp44581 +(I1 +(I1 +I1 +I1 +tp44582 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44583 +tp44584 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44585 +g454 +asg113 +I11447 +sg280 +I01 +sbaatp44586 +Rp44587 +sg337 +I00 +sg338 +Nsbaa(lp44588 +g458 +ag0 +(g459 +g2 +Ntp44589 +Rp44590 +(dp44591 +g17 +g44344 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44592 +(lp44593 +g189 +ag0 +(g190 +g2 +Ntp44594 +Rp44595 +(dp44596 +g194 +I01 +sg195 +(lp44597 +g0 +(g197 +g2 +Ntp44598 +Rp44599 +(dp44600 +g201 +g176 +(g177 +(I0 +tp44601 +g179 +tp44602 +Rp44603 +(I1 +(I1 +tp44604 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44605 +tp44606 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44607 +Rp44608 +(dp44609 +g201 +g176 +(g177 +(I0 +tp44610 +g179 +tp44611 +Rp44612 +(I1 +(I2 +tp44613 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44614 +tp44615 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp44616 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44617 +g179 +tp44618 +Rp44619 +(I1 +(I1 +I1 +I1 +tp44620 +g38 +I00 +S'D\xa2\xd6\xeb\x91\x91G@' +p44621 +tp44622 +bsg238 +g176 +(g177 +(I0 +tp44623 +g179 +tp44624 +Rp44625 +(I1 +(I1 +I1 +I1 +tp44626 +g38 +I00 +S'"8\xfd\xab\xf1\x84Y?' +p44627 +tp44628 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44629 +g179 +tp44630 +Rp44631 +(I1 +(I1 +I1 +I1 +tp44632 +g38 +I00 +S"\xae\x04gK\\'\xe7?" +p44633 +tp44634 +bsg252 +g513 +sg48 +(lp44635 +g0 +(g52 +g2 +Ntp44636 +Rp44637 +(dp44638 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp44639 +g179 +tp44640 +Rp44641 +(I1 +(I1 +I1 +I1 +tp44642 +g38 +I00 +S'Jo\x04\xe5\xacGP@' +p44643 +tp44644 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp44645 +g527 +asg113 +I11450 +sg280 +I01 +sbaa(lp44646 +g529 +ag0 +(g190 +g2 +Ntp44647 +Rp44648 +(dp44649 +g194 +I01 +sg195 +(lp44650 +g0 +(g197 +g2 +Ntp44651 +Rp44652 +(dp44653 +g201 +g176 +(g177 +(I0 +tp44654 +g179 +tp44655 +Rp44656 +(I1 +(I1 +tp44657 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44658 +tp44659 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44660 +Rp44661 +(dp44662 +g201 +g176 +(g177 +(I0 +tp44663 +g179 +tp44664 +Rp44665 +(I1 +(I2 +tp44666 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44667 +tp44668 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44669 +Rp44670 +(dp44671 +g201 +g176 +(g177 +(I0 +tp44672 +g179 +tp44673 +Rp44674 +(I1 +(I2 +tp44675 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44676 +tp44677 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp44678 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44679 +g179 +tp44680 +Rp44681 +(I1 +(I1 +I1 +I1 +tp44682 +g38 +I00 +S'\xcbO\x81\xfe\x08\xa9G@' +p44683 +tp44684 +bsg238 +g176 +(g177 +(I0 +tp44685 +g179 +tp44686 +Rp44687 +(I1 +(I1 +I1 +I1 +tp44688 +g38 +I00 +S'\x8d\xc3].*\x93V?' +p44689 +tp44690 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44691 +g179 +tp44692 +Rp44693 +(I1 +(I1 +I1 +I1 +tp44694 +g38 +I00 +S'\x9e\x82\x0f8%3\xe7?' +p44695 +tp44696 +bsg252 +g586 +sg48 +(lp44697 +g0 +(g52 +g2 +Ntp44698 +Rp44699 +(dp44700 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp44701 +g179 +tp44702 +Rp44703 +(I1 +(I1 +I1 +I1 +tp44704 +g38 +I00 +S'\xd7\xe7j+\xf6OP@' +p44705 +tp44706 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp44707 +g600 +asg113 +I11451 +sg280 +I01 +sbaatp44708 +Rp44709 +sg337 +I00 +sg338 +Nsbaa(lp44710 +g604 +ag0 +(g605 +g2 +Ntp44711 +Rp44712 +(dp44713 +g17 +g44344 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44714 +(lp44715 +g611 +ag0 +(g190 +g2 +Ntp44716 +Rp44717 +(dp44718 +g194 +I01 +sg195 +(lp44719 +g0 +(g197 +g2 +Ntp44720 +Rp44721 +(dp44722 +g201 +g176 +(g177 +(I0 +tp44723 +g179 +tp44724 +Rp44725 +(I1 +(I1 +tp44726 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44727 +tp44728 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44729 +Rp44730 +(dp44731 +g201 +g176 +(g177 +(I0 +tp44732 +g179 +tp44733 +Rp44734 +(I1 +(I2 +tp44735 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44736 +tp44737 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp44738 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44739 +g179 +tp44740 +Rp44741 +(I1 +(I1 +I1 +I1 +tp44742 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44743 +tp44744 +bsg238 +g176 +(g177 +(I0 +tp44745 +g179 +tp44746 +Rp44747 +(I1 +(I1 +I1 +I1 +tp44748 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44749 +tp44750 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44751 +g179 +tp44752 +Rp44753 +(I1 +(I1 +I1 +I1 +tp44754 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44755 +tp44756 +bsg252 +g513 +sg48 +(lp44757 +g0 +(g52 +g2 +Ntp44758 +Rp44759 +(dp44760 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp44761 +g179 +tp44762 +Rp44763 +(I1 +(I1 +I1 +I1 +tp44764 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44765 +tp44766 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp44767 +g664 +asg113 +I11454 +sg280 +I01 +sbaa(lp44768 +g666 +ag0 +(g190 +g2 +Ntp44769 +Rp44770 +(dp44771 +g194 +I01 +sg195 +(lp44772 +g0 +(g197 +g2 +Ntp44773 +Rp44774 +(dp44775 +g201 +g176 +(g177 +(I0 +tp44776 +g179 +tp44777 +Rp44778 +(I1 +(I1 +tp44779 +g208 +I00 +S"k'\x00\x00\x00\x00\x00\x00" +p44780 +tp44781 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44782 +Rp44783 +(dp44784 +g201 +g176 +(g177 +(I0 +tp44785 +g179 +tp44786 +Rp44787 +(I1 +(I2 +tp44788 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44789 +tp44790 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp44791 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44792 +g179 +tp44793 +Rp44794 +(I1 +(I1 +I1 +I1 +tp44795 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44796 +tp44797 +bsg238 +g176 +(g177 +(I0 +tp44798 +g179 +tp44799 +Rp44800 +(I1 +(I1 +I1 +I1 +tp44801 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44802 +tp44803 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44804 +g179 +tp44805 +Rp44806 +(I1 +(I1 +I1 +I1 +tp44807 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44808 +tp44809 +bsg252 +g713 +sg48 +(lp44810 +g0 +(g52 +g2 +Ntp44811 +Rp44812 +(dp44813 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp44814 +g179 +tp44815 +Rp44816 +(I1 +(I1 +I1 +I1 +tp44817 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p44818 +tp44819 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp44820 +g727 +asg113 +I11455 +sg280 +I01 +sbaatp44821 +Rp44822 +sg337 +I00 +sg338 +Nsbaatp44823 +Rp44824 +aa(lp44825 +I10092 +ag7 +((lp44826 +(lp44827 +g12 +ag0 +(g13 +g2 +Ntp44828 +Rp44829 +(dp44830 +g17 +g0 +(g18 +g2 +Ntp44831 +Rp44832 +(dp44833 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p44834 +sg116 +g0 +(g117 +g2 +Ntp44835 +Rp44836 +(dp44837 +g121 +(lp44838 +g0 +(g123 +g2 +Ntp44839 +Rp44840 +(dp44841 +g127 +g38565 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp44842 +Rp44843 +(dp44844 +g127 +g11234 +sg148 +g162 +sbasbsg163 +Nsg113 +I10092 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44845 +(lp44846 +g189 +ag0 +(g190 +g2 +Ntp44847 +Rp44848 +(dp44849 +g194 +I01 +sg195 +(lp44850 +g0 +(g197 +g2 +Ntp44851 +Rp44852 +(dp44853 +g201 +g176 +(g177 +(I0 +tp44854 +g179 +tp44855 +Rp44856 +(I1 +(I1 +tp44857 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p44858 +tp44859 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44860 +Rp44861 +(dp44862 +g201 +g176 +(g177 +(I0 +tp44863 +g179 +tp44864 +Rp44865 +(I1 +(I2 +tp44866 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44867 +tp44868 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44869 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44870 +g179 +tp44871 +Rp44872 +(I1 +(I1 +I1 +I1 +tp44873 +g38 +I00 +S'\xa7\xe8K\xc5\xcc\xab\x0e@' +p44874 +tp44875 +bsg238 +g176 +(g177 +(I0 +tp44876 +g179 +tp44877 +Rp44878 +(I1 +(I1 +I1 +I1 +tp44879 +g38 +I00 +S'f\x7f0\xf8\x9a\xdf-?' +p44880 +tp44881 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44882 +g179 +tp44883 +Rp44884 +(I1 +(I1 +I1 +I1 +tp44885 +g38 +I00 +S'\x9bdH\xa3\xc5j\xca?' +p44886 +tp44887 +bsg252 +g260 +sg48 +(lp44888 +g0 +(g52 +g2 +Ntp44889 +Rp44890 +(dp44891 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44892 +g179 +tp44893 +Rp44894 +(I1 +(I1 +I1 +I1 +tp44895 +g38 +I00 +S'\xbd\xe6\xce\xf6\x12\x932@' +p44896 +tp44897 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44898 +g279 +asg113 +I11458 +sg280 +I01 +sbaa(lp44899 +g12 +ag0 +(g190 +g2 +Ntp44900 +Rp44901 +(dp44902 +g194 +I01 +sg195 +(lp44903 +g0 +(g197 +g2 +Ntp44904 +Rp44905 +(dp44906 +g201 +g176 +(g177 +(I0 +tp44907 +g179 +tp44908 +Rp44909 +(I1 +(I1 +tp44910 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p44911 +tp44912 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44913 +Rp44914 +(dp44915 +g201 +g176 +(g177 +(I0 +tp44916 +g179 +tp44917 +Rp44918 +(I1 +(I2 +tp44919 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44920 +tp44921 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44922 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44923 +g179 +tp44924 +Rp44925 +(I1 +(I1 +I1 +I1 +tp44926 +g38 +I00 +S'\xbe\x89\xfeQ\x03t\xd7?' +p44927 +tp44928 +bsg238 +g176 +(g177 +(I0 +tp44929 +g179 +tp44930 +Rp44931 +(I1 +(I1 +I1 +I1 +tp44932 +g38 +I00 +S'\xe4\n\x04[8|\x12?' +p44933 +tp44934 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44935 +g179 +tp44936 +Rp44937 +(I1 +(I1 +I1 +I1 +tp44938 +g38 +I00 +S'\xe2\xb4e\x0c\xa2U\xb0?' +p44939 +tp44940 +bsg252 +g260 +sg48 +(lp44941 +g0 +(g52 +g2 +Ntp44942 +Rp44943 +(dp44944 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp44945 +g179 +tp44946 +Rp44947 +(I1 +(I1 +I1 +I1 +tp44948 +g38 +I00 +S'^\x06o\xe1k\xf8\x16@' +p44949 +tp44950 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp44951 +g334 +asg113 +I11459 +sg280 +I01 +sbaatp44952 +Rp44953 +sg337 +I00 +sg338 +Nsbaa(lp44954 +g340 +ag0 +(g341 +g2 +Ntp44955 +Rp44956 +(dp44957 +g17 +g44832 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp44958 +(lp44959 +g189 +ag0 +(g190 +g2 +Ntp44960 +Rp44961 +(dp44962 +g194 +I01 +sg195 +(lp44963 +g0 +(g197 +g2 +Ntp44964 +Rp44965 +(dp44966 +g201 +g176 +(g177 +(I0 +tp44967 +g179 +tp44968 +Rp44969 +(I1 +(I1 +tp44970 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p44971 +tp44972 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp44973 +Rp44974 +(dp44975 +g201 +g176 +(g177 +(I0 +tp44976 +g179 +tp44977 +Rp44978 +(I1 +(I2 +tp44979 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p44980 +tp44981 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp44982 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp44983 +g179 +tp44984 +Rp44985 +(I1 +(I1 +I1 +I1 +tp44986 +g38 +I00 +S'\xa7\xe8K\xc5\xcc\xab\x0e@' +p44987 +tp44988 +bsg238 +g176 +(g177 +(I0 +tp44989 +g179 +tp44990 +Rp44991 +(I1 +(I1 +I1 +I1 +tp44992 +g38 +I00 +S'f\x7f0\xf8\x9a\xdf-?' +p44993 +tp44994 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp44995 +g179 +tp44996 +Rp44997 +(I1 +(I1 +I1 +I1 +tp44998 +g38 +I00 +S'\x9bdH\xa3\xc5j\xca?' +p44999 +tp45000 +bsg252 +g260 +sg48 +(lp45001 +g0 +(g52 +g2 +Ntp45002 +Rp45003 +(dp45004 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45005 +g179 +tp45006 +Rp45007 +(I1 +(I1 +I1 +I1 +tp45008 +g38 +I00 +S'\xbd\xe6\xce\xf6\x12\x932@' +p45009 +tp45010 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45011 +g279 +asg113 +I11462 +sg280 +I01 +sbaa(lp45012 +g401 +ag0 +(g190 +g2 +Ntp45013 +Rp45014 +(dp45015 +g194 +I01 +sg195 +(lp45016 +g0 +(g197 +g2 +Ntp45017 +Rp45018 +(dp45019 +g201 +g176 +(g177 +(I0 +tp45020 +g179 +tp45021 +Rp45022 +(I1 +(I1 +tp45023 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p45024 +tp45025 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45026 +Rp45027 +(dp45028 +g201 +g176 +(g177 +(I0 +tp45029 +g179 +tp45030 +Rp45031 +(I1 +(I2 +tp45032 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45033 +tp45034 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45035 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45036 +g179 +tp45037 +Rp45038 +(I1 +(I1 +I1 +I1 +tp45039 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45040 +tp45041 +bsg238 +g176 +(g177 +(I0 +tp45042 +g179 +tp45043 +Rp45044 +(I1 +(I1 +I1 +I1 +tp45045 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45046 +tp45047 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45048 +g179 +tp45049 +Rp45050 +(I1 +(I1 +I1 +I1 +tp45051 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45052 +tp45053 +bsg252 +g260 +sg48 +(lp45054 +g0 +(g52 +g2 +Ntp45055 +Rp45056 +(dp45057 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45058 +g179 +tp45059 +Rp45060 +(I1 +(I1 +I1 +I1 +tp45061 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45062 +tp45063 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45064 +g454 +asg113 +I11463 +sg280 +I01 +sbaatp45065 +Rp45066 +sg337 +I00 +sg338 +Nsbaa(lp45067 +g458 +ag0 +(g459 +g2 +Ntp45068 +Rp45069 +(dp45070 +g17 +g44832 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45071 +(lp45072 +g189 +ag0 +(g190 +g2 +Ntp45073 +Rp45074 +(dp45075 +g194 +I01 +sg195 +(lp45076 +g0 +(g197 +g2 +Ntp45077 +Rp45078 +(dp45079 +g201 +g176 +(g177 +(I0 +tp45080 +g179 +tp45081 +Rp45082 +(I1 +(I1 +tp45083 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p45084 +tp45085 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45086 +Rp45087 +(dp45088 +g201 +g176 +(g177 +(I0 +tp45089 +g179 +tp45090 +Rp45091 +(I1 +(I2 +tp45092 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45093 +tp45094 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp45095 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45096 +g179 +tp45097 +Rp45098 +(I1 +(I1 +I1 +I1 +tp45099 +g38 +I00 +S'\xf9\xfe~v\xfe\xbe\x0e@' +p45100 +tp45101 +bsg238 +g176 +(g177 +(I0 +tp45102 +g179 +tp45103 +Rp45104 +(I1 +(I1 +I1 +I1 +tp45105 +g38 +I00 +S'\xb9\xc2\x90\xb9\xa0`P?' +p45106 +tp45107 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45108 +g179 +tp45109 +Rp45110 +(I1 +(I1 +I1 +I1 +tp45111 +g38 +I00 +S'd1\xd0\x92Xl\xca?' +p45112 +tp45113 +bsg252 +g513 +sg48 +(lp45114 +g0 +(g52 +g2 +Ntp45115 +Rp45116 +(dp45117 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp45118 +g179 +tp45119 +Rp45120 +(I1 +(I1 +I1 +I1 +tp45121 +g38 +I00 +S'\xbab:G.\x942@' +p45122 +tp45123 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp45124 +g527 +asg113 +I11466 +sg280 +I01 +sbaa(lp45125 +g529 +ag0 +(g190 +g2 +Ntp45126 +Rp45127 +(dp45128 +g194 +I01 +sg195 +(lp45129 +g0 +(g197 +g2 +Ntp45130 +Rp45131 +(dp45132 +g201 +g176 +(g177 +(I0 +tp45133 +g179 +tp45134 +Rp45135 +(I1 +(I1 +tp45136 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p45137 +tp45138 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45139 +Rp45140 +(dp45141 +g201 +g176 +(g177 +(I0 +tp45142 +g179 +tp45143 +Rp45144 +(I1 +(I2 +tp45145 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45146 +tp45147 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45148 +Rp45149 +(dp45150 +g201 +g176 +(g177 +(I0 +tp45151 +g179 +tp45152 +Rp45153 +(I1 +(I2 +tp45154 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45155 +tp45156 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp45157 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45158 +g179 +tp45159 +Rp45160 +(I1 +(I1 +I1 +I1 +tp45161 +g38 +I00 +S'E\x8a;\xbd\xd6N\xd7?' +p45162 +tp45163 +bsg238 +g176 +(g177 +(I0 +tp45164 +g179 +tp45165 +Rp45166 +(I1 +(I1 +I1 +I1 +tp45167 +g38 +I00 +S'\xba\x8d\x15\x98\xaf_3?' +p45168 +tp45169 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45170 +g179 +tp45171 +Rp45172 +(I1 +(I1 +I1 +I1 +tp45173 +g38 +I00 +S'P\xc0\xd8\xb7\xe2D\xb0?' +p45174 +tp45175 +bsg252 +g586 +sg48 +(lp45176 +g0 +(g52 +g2 +Ntp45177 +Rp45178 +(dp45179 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp45180 +g179 +tp45181 +Rp45182 +(I1 +(I1 +I1 +I1 +tp45183 +g38 +I00 +S'q\xce\x88\xd2\xde\xe0\x16@' +p45184 +tp45185 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp45186 +g600 +asg113 +I11467 +sg280 +I01 +sbaatp45187 +Rp45188 +sg337 +I00 +sg338 +Nsbaa(lp45189 +g604 +ag0 +(g605 +g2 +Ntp45190 +Rp45191 +(dp45192 +g17 +g44832 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45193 +(lp45194 +g611 +ag0 +(g190 +g2 +Ntp45195 +Rp45196 +(dp45197 +g194 +I01 +sg195 +(lp45198 +g0 +(g197 +g2 +Ntp45199 +Rp45200 +(dp45201 +g201 +g176 +(g177 +(I0 +tp45202 +g179 +tp45203 +Rp45204 +(I1 +(I1 +tp45205 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p45206 +tp45207 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45208 +Rp45209 +(dp45210 +g201 +g176 +(g177 +(I0 +tp45211 +g179 +tp45212 +Rp45213 +(I1 +(I2 +tp45214 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45215 +tp45216 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp45217 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45218 +g179 +tp45219 +Rp45220 +(I1 +(I1 +I1 +I1 +tp45221 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45222 +tp45223 +bsg238 +g176 +(g177 +(I0 +tp45224 +g179 +tp45225 +Rp45226 +(I1 +(I1 +I1 +I1 +tp45227 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45228 +tp45229 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45230 +g179 +tp45231 +Rp45232 +(I1 +(I1 +I1 +I1 +tp45233 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45234 +tp45235 +bsg252 +g513 +sg48 +(lp45236 +g0 +(g52 +g2 +Ntp45237 +Rp45238 +(dp45239 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp45240 +g179 +tp45241 +Rp45242 +(I1 +(I1 +I1 +I1 +tp45243 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45244 +tp45245 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp45246 +g664 +asg113 +I11470 +sg280 +I01 +sbaa(lp45247 +g666 +ag0 +(g190 +g2 +Ntp45248 +Rp45249 +(dp45250 +g194 +I01 +sg195 +(lp45251 +g0 +(g197 +g2 +Ntp45252 +Rp45253 +(dp45254 +g201 +g176 +(g177 +(I0 +tp45255 +g179 +tp45256 +Rp45257 +(I1 +(I1 +tp45258 +g208 +I00 +S"l'\x00\x00\x00\x00\x00\x00" +p45259 +tp45260 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45261 +Rp45262 +(dp45263 +g201 +g176 +(g177 +(I0 +tp45264 +g179 +tp45265 +Rp45266 +(I1 +(I2 +tp45267 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45268 +tp45269 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp45270 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45271 +g179 +tp45272 +Rp45273 +(I1 +(I1 +I1 +I1 +tp45274 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45275 +tp45276 +bsg238 +g176 +(g177 +(I0 +tp45277 +g179 +tp45278 +Rp45279 +(I1 +(I1 +I1 +I1 +tp45280 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45281 +tp45282 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45283 +g179 +tp45284 +Rp45285 +(I1 +(I1 +I1 +I1 +tp45286 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45287 +tp45288 +bsg252 +g713 +sg48 +(lp45289 +g0 +(g52 +g2 +Ntp45290 +Rp45291 +(dp45292 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp45293 +g179 +tp45294 +Rp45295 +(I1 +(I1 +I1 +I1 +tp45296 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45297 +tp45298 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp45299 +g727 +asg113 +I11471 +sg280 +I01 +sbaatp45300 +Rp45301 +sg337 +I00 +sg338 +Nsbaatp45302 +Rp45303 +aa(lp45304 +I10093 +ag7 +((lp45305 +(lp45306 +g12 +ag0 +(g13 +g2 +Ntp45307 +Rp45308 +(dp45309 +g17 +g0 +(g18 +g2 +Ntp45310 +Rp45311 +(dp45312 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p45313 +sg116 +g0 +(g117 +g2 +Ntp45314 +Rp45315 +(dp45316 +g121 +(lp45317 +g0 +(g123 +g2 +Ntp45318 +Rp45319 +(dp45320 +g127 +g44355 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp45321 +Rp45322 +(dp45323 +g127 +g33260 +sg148 +g162 +sbasbsg163 +Nsg113 +I10093 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45324 +(lp45325 +g189 +ag0 +(g190 +g2 +Ntp45326 +Rp45327 +(dp45328 +g194 +I01 +sg195 +(lp45329 +g0 +(g197 +g2 +Ntp45330 +Rp45331 +(dp45332 +g201 +g176 +(g177 +(I0 +tp45333 +g179 +tp45334 +Rp45335 +(I1 +(I1 +tp45336 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45337 +tp45338 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45339 +Rp45340 +(dp45341 +g201 +g176 +(g177 +(I0 +tp45342 +g179 +tp45343 +Rp45344 +(I1 +(I2 +tp45345 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45346 +tp45347 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45348 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45349 +g179 +tp45350 +Rp45351 +(I1 +(I1 +I1 +I1 +tp45352 +g38 +I00 +S'\xc2\x01\xfa\x81[kG@' +p45353 +tp45354 +bsg238 +g176 +(g177 +(I0 +tp45355 +g179 +tp45356 +Rp45357 +(I1 +(I1 +I1 +I1 +tp45358 +g38 +I00 +S'0\xc2d\x93a\x12E?' +p45359 +tp45360 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45361 +g179 +tp45362 +Rp45363 +(I1 +(I1 +I1 +I1 +tp45364 +g38 +I00 +S'&\xfe\x82\xf1\x91\x15\xe7?' +p45365 +tp45366 +bsg252 +g260 +sg48 +(lp45367 +g0 +(g52 +g2 +Ntp45368 +Rp45369 +(dp45370 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45371 +g179 +tp45372 +Rp45373 +(I1 +(I1 +I1 +I1 +tp45374 +g38 +I00 +S'\xb3\x1a\xd0\x9d*;P@' +p45375 +tp45376 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45377 +g279 +asg113 +I11474 +sg280 +I01 +sbaa(lp45378 +g12 +ag0 +(g190 +g2 +Ntp45379 +Rp45380 +(dp45381 +g194 +I01 +sg195 +(lp45382 +g0 +(g197 +g2 +Ntp45383 +Rp45384 +(dp45385 +g201 +g176 +(g177 +(I0 +tp45386 +g179 +tp45387 +Rp45388 +(I1 +(I1 +tp45389 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45390 +tp45391 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45392 +Rp45393 +(dp45394 +g201 +g176 +(g177 +(I0 +tp45395 +g179 +tp45396 +Rp45397 +(I1 +(I2 +tp45398 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45399 +tp45400 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45401 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45402 +g179 +tp45403 +Rp45404 +(I1 +(I1 +I1 +I1 +tp45405 +g38 +I00 +S'\x00ja5m|G@' +p45406 +tp45407 +bsg238 +g176 +(g177 +(I0 +tp45408 +g179 +tp45409 +Rp45410 +(I1 +(I1 +I1 +I1 +tp45411 +g38 +I00 +S'\x92\x9dt\xfb\xca0O?' +p45412 +tp45413 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45414 +g179 +tp45415 +Rp45416 +(I1 +(I1 +I1 +I1 +tp45417 +g38 +I00 +S'\x18\x0c\xc0\x86\xba\x1d\xe7?' +p45418 +tp45419 +bsg252 +g260 +sg48 +(lp45420 +g0 +(g52 +g2 +Ntp45421 +Rp45422 +(dp45423 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45424 +g179 +tp45425 +Rp45426 +(I1 +(I1 +I1 +I1 +tp45427 +g38 +I00 +S'\x81\x08\xbf&\xe7@P@' +p45428 +tp45429 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45430 +g334 +asg113 +I11475 +sg280 +I01 +sbaatp45431 +Rp45432 +sg337 +I00 +sg338 +Nsbaa(lp45433 +g340 +ag0 +(g341 +g2 +Ntp45434 +Rp45435 +(dp45436 +g17 +g45311 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45437 +(lp45438 +g189 +ag0 +(g190 +g2 +Ntp45439 +Rp45440 +(dp45441 +g194 +I01 +sg195 +(lp45442 +g0 +(g197 +g2 +Ntp45443 +Rp45444 +(dp45445 +g201 +g176 +(g177 +(I0 +tp45446 +g179 +tp45447 +Rp45448 +(I1 +(I1 +tp45449 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45450 +tp45451 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45452 +Rp45453 +(dp45454 +g201 +g176 +(g177 +(I0 +tp45455 +g179 +tp45456 +Rp45457 +(I1 +(I2 +tp45458 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45459 +tp45460 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45461 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45462 +g179 +tp45463 +Rp45464 +(I1 +(I1 +I1 +I1 +tp45465 +g38 +I00 +S'\xc2\x01\xfa\x81[kG@' +p45466 +tp45467 +bsg238 +g176 +(g177 +(I0 +tp45468 +g179 +tp45469 +Rp45470 +(I1 +(I1 +I1 +I1 +tp45471 +g38 +I00 +S'0\xc2d\x93a\x12E?' +p45472 +tp45473 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45474 +g179 +tp45475 +Rp45476 +(I1 +(I1 +I1 +I1 +tp45477 +g38 +I00 +S'&\xfe\x82\xf1\x91\x15\xe7?' +p45478 +tp45479 +bsg252 +g260 +sg48 +(lp45480 +g0 +(g52 +g2 +Ntp45481 +Rp45482 +(dp45483 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45484 +g179 +tp45485 +Rp45486 +(I1 +(I1 +I1 +I1 +tp45487 +g38 +I00 +S'\xb3\x1a\xd0\x9d*;P@' +p45488 +tp45489 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45490 +g279 +asg113 +I11478 +sg280 +I01 +sbaa(lp45491 +g401 +ag0 +(g190 +g2 +Ntp45492 +Rp45493 +(dp45494 +g194 +I01 +sg195 +(lp45495 +g0 +(g197 +g2 +Ntp45496 +Rp45497 +(dp45498 +g201 +g176 +(g177 +(I0 +tp45499 +g179 +tp45500 +Rp45501 +(I1 +(I1 +tp45502 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45503 +tp45504 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45505 +Rp45506 +(dp45507 +g201 +g176 +(g177 +(I0 +tp45508 +g179 +tp45509 +Rp45510 +(I1 +(I2 +tp45511 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45512 +tp45513 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45514 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45515 +g179 +tp45516 +Rp45517 +(I1 +(I1 +I1 +I1 +tp45518 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45519 +tp45520 +bsg238 +g176 +(g177 +(I0 +tp45521 +g179 +tp45522 +Rp45523 +(I1 +(I1 +I1 +I1 +tp45524 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45525 +tp45526 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45527 +g179 +tp45528 +Rp45529 +(I1 +(I1 +I1 +I1 +tp45530 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45531 +tp45532 +bsg252 +g260 +sg48 +(lp45533 +g0 +(g52 +g2 +Ntp45534 +Rp45535 +(dp45536 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45537 +g179 +tp45538 +Rp45539 +(I1 +(I1 +I1 +I1 +tp45540 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45541 +tp45542 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45543 +g454 +asg113 +I11479 +sg280 +I01 +sbaatp45544 +Rp45545 +sg337 +I00 +sg338 +Nsbaa(lp45546 +g458 +ag0 +(g459 +g2 +Ntp45547 +Rp45548 +(dp45549 +g17 +g45311 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45550 +(lp45551 +g189 +ag0 +(g190 +g2 +Ntp45552 +Rp45553 +(dp45554 +g194 +I01 +sg195 +(lp45555 +g0 +(g197 +g2 +Ntp45556 +Rp45557 +(dp45558 +g201 +g176 +(g177 +(I0 +tp45559 +g179 +tp45560 +Rp45561 +(I1 +(I1 +tp45562 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45563 +tp45564 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45565 +Rp45566 +(dp45567 +g201 +g176 +(g177 +(I0 +tp45568 +g179 +tp45569 +Rp45570 +(I1 +(I2 +tp45571 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45572 +tp45573 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp45574 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45575 +g179 +tp45576 +Rp45577 +(I1 +(I1 +I1 +I1 +tp45578 +g38 +I00 +S'=#?\xaaQ\x8dG@' +p45579 +tp45580 +bsg238 +g176 +(g177 +(I0 +tp45581 +g179 +tp45582 +Rp45583 +(I1 +(I1 +I1 +I1 +tp45584 +g38 +I00 +S'\xf5w\x81\xdez\xadW?' +p45585 +tp45586 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45587 +g179 +tp45588 +Rp45589 +(I1 +(I1 +I1 +I1 +tp45590 +g38 +I00 +S'\xb9\xfe|\xfap%\xe7?' +p45591 +tp45592 +bsg252 +g513 +sg48 +(lp45593 +g0 +(g52 +g2 +Ntp45594 +Rp45595 +(dp45596 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp45597 +g179 +tp45598 +Rp45599 +(I1 +(I1 +I1 +I1 +tp45600 +g38 +I00 +S'\x1a\xe3\x1fpSFP@' +p45601 +tp45602 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp45603 +g527 +asg113 +I11482 +sg280 +I01 +sbaa(lp45604 +g529 +ag0 +(g190 +g2 +Ntp45605 +Rp45606 +(dp45607 +g194 +I01 +sg195 +(lp45608 +g0 +(g197 +g2 +Ntp45609 +Rp45610 +(dp45611 +g201 +g176 +(g177 +(I0 +tp45612 +g179 +tp45613 +Rp45614 +(I1 +(I1 +tp45615 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45616 +tp45617 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45618 +Rp45619 +(dp45620 +g201 +g176 +(g177 +(I0 +tp45621 +g179 +tp45622 +Rp45623 +(I1 +(I2 +tp45624 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45625 +tp45626 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45627 +Rp45628 +(dp45629 +g201 +g176 +(g177 +(I0 +tp45630 +g179 +tp45631 +Rp45632 +(I1 +(I2 +tp45633 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45634 +tp45635 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp45636 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45637 +g179 +tp45638 +Rp45639 +(I1 +(I1 +I1 +I1 +tp45640 +g38 +I00 +S'w\xa5<%-\x04G@' +p45641 +tp45642 +bsg238 +g176 +(g177 +(I0 +tp45643 +g179 +tp45644 +Rp45645 +(I1 +(I1 +I1 +I1 +tp45646 +g38 +I00 +S'\x94\x93w\xa5%\xb2V?' +p45647 +tp45648 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45649 +g179 +tp45650 +Rp45651 +(I1 +(I1 +I1 +I1 +tp45652 +g38 +I00 +S'b\xf2\xb7\xdb\xb9\xe1\xe6?' +p45653 +tp45654 +bsg252 +g586 +sg48 +(lp45655 +g0 +(g52 +g2 +Ntp45656 +Rp45657 +(dp45658 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp45659 +g179 +tp45660 +Rp45661 +(I1 +(I1 +I1 +I1 +tp45662 +g38 +I00 +S'mV}\xae\xb6\x16P@' +p45663 +tp45664 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp45665 +g600 +asg113 +I11483 +sg280 +I01 +sbaatp45666 +Rp45667 +sg337 +I00 +sg338 +Nsbaa(lp45668 +g604 +ag0 +(g605 +g2 +Ntp45669 +Rp45670 +(dp45671 +g17 +g45311 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45672 +(lp45673 +g611 +ag0 +(g190 +g2 +Ntp45674 +Rp45675 +(dp45676 +g194 +I01 +sg195 +(lp45677 +g0 +(g197 +g2 +Ntp45678 +Rp45679 +(dp45680 +g201 +g176 +(g177 +(I0 +tp45681 +g179 +tp45682 +Rp45683 +(I1 +(I1 +tp45684 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45685 +tp45686 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45687 +Rp45688 +(dp45689 +g201 +g176 +(g177 +(I0 +tp45690 +g179 +tp45691 +Rp45692 +(I1 +(I2 +tp45693 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45694 +tp45695 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp45696 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45697 +g179 +tp45698 +Rp45699 +(I1 +(I1 +I1 +I1 +tp45700 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45701 +tp45702 +bsg238 +g176 +(g177 +(I0 +tp45703 +g179 +tp45704 +Rp45705 +(I1 +(I1 +I1 +I1 +tp45706 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45707 +tp45708 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45709 +g179 +tp45710 +Rp45711 +(I1 +(I1 +I1 +I1 +tp45712 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45713 +tp45714 +bsg252 +g513 +sg48 +(lp45715 +g0 +(g52 +g2 +Ntp45716 +Rp45717 +(dp45718 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp45719 +g179 +tp45720 +Rp45721 +(I1 +(I1 +I1 +I1 +tp45722 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45723 +tp45724 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp45725 +g664 +asg113 +I11486 +sg280 +I01 +sbaa(lp45726 +g666 +ag0 +(g190 +g2 +Ntp45727 +Rp45728 +(dp45729 +g194 +I01 +sg195 +(lp45730 +g0 +(g197 +g2 +Ntp45731 +Rp45732 +(dp45733 +g201 +g176 +(g177 +(I0 +tp45734 +g179 +tp45735 +Rp45736 +(I1 +(I1 +tp45737 +g208 +I00 +S"m'\x00\x00\x00\x00\x00\x00" +p45738 +tp45739 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45740 +Rp45741 +(dp45742 +g201 +g176 +(g177 +(I0 +tp45743 +g179 +tp45744 +Rp45745 +(I1 +(I2 +tp45746 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45747 +tp45748 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp45749 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45750 +g179 +tp45751 +Rp45752 +(I1 +(I1 +I1 +I1 +tp45753 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45754 +tp45755 +bsg238 +g176 +(g177 +(I0 +tp45756 +g179 +tp45757 +Rp45758 +(I1 +(I1 +I1 +I1 +tp45759 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45760 +tp45761 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45762 +g179 +tp45763 +Rp45764 +(I1 +(I1 +I1 +I1 +tp45765 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45766 +tp45767 +bsg252 +g713 +sg48 +(lp45768 +g0 +(g52 +g2 +Ntp45769 +Rp45770 +(dp45771 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp45772 +g179 +tp45773 +Rp45774 +(I1 +(I1 +I1 +I1 +tp45775 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p45776 +tp45777 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp45778 +g727 +asg113 +I11487 +sg280 +I01 +sbaatp45779 +Rp45780 +sg337 +I00 +sg338 +Nsbaatp45781 +Rp45782 +aa(lp45783 +I10094 +ag7 +((lp45784 +(lp45785 +g12 +ag0 +(g13 +g2 +Ntp45786 +Rp45787 +(dp45788 +g17 +g0 +(g18 +g2 +Ntp45789 +Rp45790 +(dp45791 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p45792 +sg116 +g0 +(g117 +g2 +Ntp45793 +Rp45794 +(dp45795 +g121 +(lp45796 +g0 +(g123 +g2 +Ntp45797 +Rp45798 +(dp45799 +g127 +g0 +(g128 +g2 +Ntp45800 +Rp45801 +(dp45802 +g23 +g132 +sg133 +(dp45803 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg138 +g34 +(g38 +S'\xd7\xa3p=\n\xd7\x06@' +p45804 +tp45805 +Rp45806 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vtransmission +p45807 +sg113 +I105 +sg146 +(lp45808 +g138 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp45809 +Rp45810 +(dp45811 +g127 +g13216 +sg148 +g162 +sbasbsg163 +Nsg113 +I10094 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45812 +(lp45813 +g189 +ag0 +(g190 +g2 +Ntp45814 +Rp45815 +(dp45816 +g194 +I01 +sg195 +(lp45817 +g0 +(g197 +g2 +Ntp45818 +Rp45819 +(dp45820 +g201 +g176 +(g177 +(I0 +tp45821 +g179 +tp45822 +Rp45823 +(I1 +(I1 +tp45824 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p45825 +tp45826 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45827 +Rp45828 +(dp45829 +g201 +g176 +(g177 +(I0 +tp45830 +g179 +tp45831 +Rp45832 +(I1 +(I2 +tp45833 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45834 +tp45835 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45836 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45837 +g179 +tp45838 +Rp45839 +(I1 +(I1 +I1 +I1 +tp45840 +g38 +I00 +S'\xa2\xee\xad\x89\xd5.E@' +p45841 +tp45842 +bsg238 +g176 +(g177 +(I0 +tp45843 +g179 +tp45844 +Rp45845 +(I1 +(I1 +I1 +I1 +tp45846 +g38 +I00 +S'\x1a\xc3l\xadQ\x8bD?' +p45847 +tp45848 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45849 +g179 +tp45850 +Rp45851 +(I1 +(I1 +I1 +I1 +tp45852 +g38 +I00 +S'V+K\xdeP\xf4\xe5?' +p45853 +tp45854 +bsg252 +g260 +sg48 +(lp45855 +g0 +(g52 +g2 +Ntp45856 +Rp45857 +(dp45858 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45859 +g179 +tp45860 +Rp45861 +(I1 +(I1 +I1 +I1 +tp45862 +g38 +I00 +S'\xf1\xb4\x99\xb8\x91\xdfN@' +p45863 +tp45864 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45865 +g279 +asg113 +I11490 +sg280 +I01 +sbaa(lp45866 +g12 +ag0 +(g190 +g2 +Ntp45867 +Rp45868 +(dp45869 +g194 +I01 +sg195 +(lp45870 +g0 +(g197 +g2 +Ntp45871 +Rp45872 +(dp45873 +g201 +g176 +(g177 +(I0 +tp45874 +g179 +tp45875 +Rp45876 +(I1 +(I1 +tp45877 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p45878 +tp45879 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45880 +Rp45881 +(dp45882 +g201 +g176 +(g177 +(I0 +tp45883 +g179 +tp45884 +Rp45885 +(I1 +(I2 +tp45886 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45887 +tp45888 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45889 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45890 +g179 +tp45891 +Rp45892 +(I1 +(I1 +I1 +I1 +tp45893 +g38 +I00 +S'7s\xae\xaf\x06d@@' +p45894 +tp45895 +bsg238 +g176 +(g177 +(I0 +tp45896 +g179 +tp45897 +Rp45898 +(I1 +(I1 +I1 +I1 +tp45899 +g38 +I00 +S'\x82\x00Iz\xf3\tH?' +p45900 +tp45901 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45902 +g179 +tp45903 +Rp45904 +(I1 +(I1 +I1 +I1 +tp45905 +g38 +I00 +S'\xc3g\x18h\xb9O\xe3?' +p45906 +tp45907 +bsg252 +g260 +sg48 +(lp45908 +g0 +(g52 +g2 +Ntp45909 +Rp45910 +(dp45911 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45912 +g179 +tp45913 +Rp45914 +(I1 +(I1 +I1 +I1 +tp45915 +g38 +I00 +S'\xeaQb\xba\x1c(K@' +p45916 +tp45917 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45918 +g334 +asg113 +I11491 +sg280 +I01 +sbaatp45919 +Rp45920 +sg337 +I00 +sg338 +Nsbaa(lp45921 +g340 +ag0 +(g341 +g2 +Ntp45922 +Rp45923 +(dp45924 +g17 +g45790 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp45925 +(lp45926 +g189 +ag0 +(g190 +g2 +Ntp45927 +Rp45928 +(dp45929 +g194 +I01 +sg195 +(lp45930 +g0 +(g197 +g2 +Ntp45931 +Rp45932 +(dp45933 +g201 +g176 +(g177 +(I0 +tp45934 +g179 +tp45935 +Rp45936 +(I1 +(I1 +tp45937 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p45938 +tp45939 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45940 +Rp45941 +(dp45942 +g201 +g176 +(g177 +(I0 +tp45943 +g179 +tp45944 +Rp45945 +(I1 +(I2 +tp45946 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p45947 +tp45948 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp45949 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp45950 +g179 +tp45951 +Rp45952 +(I1 +(I1 +I1 +I1 +tp45953 +g38 +I00 +S'\xa2\xee\xad\x89\xd5.E@' +p45954 +tp45955 +bsg238 +g176 +(g177 +(I0 +tp45956 +g179 +tp45957 +Rp45958 +(I1 +(I1 +I1 +I1 +tp45959 +g38 +I00 +S'\x1a\xc3l\xadQ\x8bD?' +p45960 +tp45961 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp45962 +g179 +tp45963 +Rp45964 +(I1 +(I1 +I1 +I1 +tp45965 +g38 +I00 +S'V+K\xdeP\xf4\xe5?' +p45966 +tp45967 +bsg252 +g260 +sg48 +(lp45968 +g0 +(g52 +g2 +Ntp45969 +Rp45970 +(dp45971 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp45972 +g179 +tp45973 +Rp45974 +(I1 +(I1 +I1 +I1 +tp45975 +g38 +I00 +S'\xf1\xb4\x99\xb8\x91\xdfN@' +p45976 +tp45977 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp45978 +g279 +asg113 +I11494 +sg280 +I01 +sbaa(lp45979 +g401 +ag0 +(g190 +g2 +Ntp45980 +Rp45981 +(dp45982 +g194 +I01 +sg195 +(lp45983 +g0 +(g197 +g2 +Ntp45984 +Rp45985 +(dp45986 +g201 +g176 +(g177 +(I0 +tp45987 +g179 +tp45988 +Rp45989 +(I1 +(I1 +tp45990 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p45991 +tp45992 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp45993 +Rp45994 +(dp45995 +g201 +g176 +(g177 +(I0 +tp45996 +g179 +tp45997 +Rp45998 +(I1 +(I2 +tp45999 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46000 +tp46001 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46002 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46003 +g179 +tp46004 +Rp46005 +(I1 +(I1 +I1 +I1 +tp46006 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46007 +tp46008 +bsg238 +g176 +(g177 +(I0 +tp46009 +g179 +tp46010 +Rp46011 +(I1 +(I1 +I1 +I1 +tp46012 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46013 +tp46014 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46015 +g179 +tp46016 +Rp46017 +(I1 +(I1 +I1 +I1 +tp46018 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46019 +tp46020 +bsg252 +g260 +sg48 +(lp46021 +g0 +(g52 +g2 +Ntp46022 +Rp46023 +(dp46024 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46025 +g179 +tp46026 +Rp46027 +(I1 +(I1 +I1 +I1 +tp46028 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46029 +tp46030 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46031 +g454 +asg113 +I11495 +sg280 +I01 +sbaatp46032 +Rp46033 +sg337 +I00 +sg338 +Nsbaa(lp46034 +g458 +ag0 +(g459 +g2 +Ntp46035 +Rp46036 +(dp46037 +g17 +g45790 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46038 +(lp46039 +g189 +ag0 +(g190 +g2 +Ntp46040 +Rp46041 +(dp46042 +g194 +I01 +sg195 +(lp46043 +g0 +(g197 +g2 +Ntp46044 +Rp46045 +(dp46046 +g201 +g176 +(g177 +(I0 +tp46047 +g179 +tp46048 +Rp46049 +(I1 +(I1 +tp46050 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p46051 +tp46052 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46053 +Rp46054 +(dp46055 +g201 +g176 +(g177 +(I0 +tp46056 +g179 +tp46057 +Rp46058 +(I1 +(I2 +tp46059 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46060 +tp46061 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp46062 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46063 +g179 +tp46064 +Rp46065 +(I1 +(I1 +I1 +I1 +tp46066 +g38 +I00 +S'\xc8\xe2\x9e\x9a\x8d)E@' +p46067 +tp46068 +bsg238 +g176 +(g177 +(I0 +tp46069 +g179 +tp46070 +Rp46071 +(I1 +(I1 +I1 +I1 +tp46072 +g38 +I00 +S'\xf0\xc7D\x9e\xac\xf1T?' +p46073 +tp46074 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46075 +g179 +tp46076 +Rp46077 +(I1 +(I1 +I1 +I1 +tp46078 +g38 +I00 +S'\xbd\xd1\x9d(\xeb\xf0\xe5?' +p46079 +tp46080 +bsg252 +g513 +sg48 +(lp46081 +g0 +(g52 +g2 +Ntp46082 +Rp46083 +(dp46084 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp46085 +g179 +tp46086 +Rp46087 +(I1 +(I1 +I1 +I1 +tp46088 +g38 +I00 +S'\xf2\xee\x1d\xb1\xca\xdaN@' +p46089 +tp46090 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp46091 +g527 +asg113 +I11498 +sg280 +I01 +sbaa(lp46092 +g529 +ag0 +(g190 +g2 +Ntp46093 +Rp46094 +(dp46095 +g194 +I01 +sg195 +(lp46096 +g0 +(g197 +g2 +Ntp46097 +Rp46098 +(dp46099 +g201 +g176 +(g177 +(I0 +tp46100 +g179 +tp46101 +Rp46102 +(I1 +(I1 +tp46103 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p46104 +tp46105 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46106 +Rp46107 +(dp46108 +g201 +g176 +(g177 +(I0 +tp46109 +g179 +tp46110 +Rp46111 +(I1 +(I2 +tp46112 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46113 +tp46114 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46115 +Rp46116 +(dp46117 +g201 +g176 +(g177 +(I0 +tp46118 +g179 +tp46119 +Rp46120 +(I1 +(I2 +tp46121 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46122 +tp46123 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp46124 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46125 +g179 +tp46126 +Rp46127 +(I1 +(I1 +I1 +I1 +tp46128 +g38 +I00 +S'\xf6\x11[\xee\n\x1a@@' +p46129 +tp46130 +bsg238 +g176 +(g177 +(I0 +tp46131 +g179 +tp46132 +Rp46133 +(I1 +(I1 +I1 +I1 +tp46134 +g38 +I00 +S'\xec\xe6\x13\xab\x12MQ?' +p46135 +tp46136 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46137 +g179 +tp46138 +Rp46139 +(I1 +(I1 +I1 +I1 +tp46140 +g38 +I00 +S'\x95\xdc\xd9\xf5\x96#\xe3?' +p46141 +tp46142 +bsg252 +g586 +sg48 +(lp46143 +g0 +(g52 +g2 +Ntp46144 +Rp46145 +(dp46146 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp46147 +g179 +tp46148 +Rp46149 +(I1 +(I1 +I1 +I1 +tp46150 +g38 +I00 +S'2^\xbaI\x0c\xeaJ@' +p46151 +tp46152 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp46153 +g600 +asg113 +I11499 +sg280 +I01 +sbaatp46154 +Rp46155 +sg337 +I00 +sg338 +Nsbaa(lp46156 +g604 +ag0 +(g605 +g2 +Ntp46157 +Rp46158 +(dp46159 +g17 +g45790 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46160 +(lp46161 +g611 +ag0 +(g190 +g2 +Ntp46162 +Rp46163 +(dp46164 +g194 +I01 +sg195 +(lp46165 +g0 +(g197 +g2 +Ntp46166 +Rp46167 +(dp46168 +g201 +g176 +(g177 +(I0 +tp46169 +g179 +tp46170 +Rp46171 +(I1 +(I1 +tp46172 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p46173 +tp46174 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46175 +Rp46176 +(dp46177 +g201 +g176 +(g177 +(I0 +tp46178 +g179 +tp46179 +Rp46180 +(I1 +(I2 +tp46181 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46182 +tp46183 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp46184 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46185 +g179 +tp46186 +Rp46187 +(I1 +(I1 +I1 +I1 +tp46188 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46189 +tp46190 +bsg238 +g176 +(g177 +(I0 +tp46191 +g179 +tp46192 +Rp46193 +(I1 +(I1 +I1 +I1 +tp46194 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46195 +tp46196 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46197 +g179 +tp46198 +Rp46199 +(I1 +(I1 +I1 +I1 +tp46200 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46201 +tp46202 +bsg252 +g513 +sg48 +(lp46203 +g0 +(g52 +g2 +Ntp46204 +Rp46205 +(dp46206 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp46207 +g179 +tp46208 +Rp46209 +(I1 +(I1 +I1 +I1 +tp46210 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46211 +tp46212 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp46213 +g664 +asg113 +I11502 +sg280 +I01 +sbaa(lp46214 +g666 +ag0 +(g190 +g2 +Ntp46215 +Rp46216 +(dp46217 +g194 +I01 +sg195 +(lp46218 +g0 +(g197 +g2 +Ntp46219 +Rp46220 +(dp46221 +g201 +g176 +(g177 +(I0 +tp46222 +g179 +tp46223 +Rp46224 +(I1 +(I1 +tp46225 +g208 +I00 +S"n'\x00\x00\x00\x00\x00\x00" +p46226 +tp46227 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46228 +Rp46229 +(dp46230 +g201 +g176 +(g177 +(I0 +tp46231 +g179 +tp46232 +Rp46233 +(I1 +(I2 +tp46234 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46235 +tp46236 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp46237 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46238 +g179 +tp46239 +Rp46240 +(I1 +(I1 +I1 +I1 +tp46241 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46242 +tp46243 +bsg238 +g176 +(g177 +(I0 +tp46244 +g179 +tp46245 +Rp46246 +(I1 +(I1 +I1 +I1 +tp46247 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46248 +tp46249 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46250 +g179 +tp46251 +Rp46252 +(I1 +(I1 +I1 +I1 +tp46253 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46254 +tp46255 +bsg252 +g713 +sg48 +(lp46256 +g0 +(g52 +g2 +Ntp46257 +Rp46258 +(dp46259 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp46260 +g179 +tp46261 +Rp46262 +(I1 +(I1 +I1 +I1 +tp46263 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46264 +tp46265 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp46266 +g727 +asg113 +I11503 +sg280 +I01 +sbaatp46267 +Rp46268 +sg337 +I00 +sg338 +Nsbaatp46269 +Rp46270 +aa(lp46271 +I10095 +ag7 +((lp46272 +(lp46273 +g12 +ag0 +(g13 +g2 +Ntp46274 +Rp46275 +(dp46276 +g17 +g0 +(g18 +g2 +Ntp46277 +Rp46278 +(dp46279 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p46280 +sg116 +g0 +(g117 +g2 +Ntp46281 +Rp46282 +(dp46283 +g121 +(lp46284 +g0 +(g123 +g2 +Ntp46285 +Rp46286 +(dp46287 +g127 +g40017 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp46288 +Rp46289 +(dp46290 +g127 +g43391 +sg148 +g162 +sbasbsg163 +Nsg113 +I10095 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46291 +(lp46292 +g189 +ag0 +(g190 +g2 +Ntp46293 +Rp46294 +(dp46295 +g194 +I01 +sg195 +(lp46296 +g0 +(g197 +g2 +Ntp46297 +Rp46298 +(dp46299 +g201 +g176 +(g177 +(I0 +tp46300 +g179 +tp46301 +Rp46302 +(I1 +(I1 +tp46303 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46304 +tp46305 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46306 +Rp46307 +(dp46308 +g201 +g176 +(g177 +(I0 +tp46309 +g179 +tp46310 +Rp46311 +(I1 +(I2 +tp46312 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46313 +tp46314 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46315 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46316 +g179 +tp46317 +Rp46318 +(I1 +(I1 +I1 +I1 +tp46319 +g38 +I00 +S'\x831\xc3\xde\xaf\xcaF@' +p46320 +tp46321 +bsg238 +g176 +(g177 +(I0 +tp46322 +g179 +tp46323 +Rp46324 +(I1 +(I1 +I1 +I1 +tp46325 +g38 +I00 +S'o*XH\xb0\xa9E?' +p46326 +tp46327 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46328 +g179 +tp46329 +Rp46330 +(I1 +(I1 +I1 +I1 +tp46331 +g38 +I00 +S'dT;2\xd4\xc5\xe6?' +p46332 +tp46333 +bsg252 +g260 +sg48 +(lp46334 +g0 +(g52 +g2 +Ntp46335 +Rp46336 +(dp46337 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46338 +g179 +tp46339 +Rp46340 +(I1 +(I1 +I1 +I1 +tp46341 +g38 +I00 +S'V\xb7Q3\x19\x03P@' +p46342 +tp46343 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46344 +g279 +asg113 +I11506 +sg280 +I01 +sbaa(lp46345 +g12 +ag0 +(g190 +g2 +Ntp46346 +Rp46347 +(dp46348 +g194 +I01 +sg195 +(lp46349 +g0 +(g197 +g2 +Ntp46350 +Rp46351 +(dp46352 +g201 +g176 +(g177 +(I0 +tp46353 +g179 +tp46354 +Rp46355 +(I1 +(I1 +tp46356 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46357 +tp46358 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46359 +Rp46360 +(dp46361 +g201 +g176 +(g177 +(I0 +tp46362 +g179 +tp46363 +Rp46364 +(I1 +(I2 +tp46365 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46366 +tp46367 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46368 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46369 +g179 +tp46370 +Rp46371 +(I1 +(I1 +I1 +I1 +tp46372 +g38 +I00 +S'][.\x8d\x98\x87E@' +p46373 +tp46374 +bsg238 +g176 +(g177 +(I0 +tp46375 +g179 +tp46376 +Rp46377 +(I1 +(I1 +I1 +I1 +tp46378 +g38 +I00 +S'\x81V\xc4/\x10\x02N?' +p46379 +tp46380 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46381 +g179 +tp46382 +Rp46383 +(I1 +(I1 +I1 +I1 +tp46384 +g38 +I00 +S'V\xe3!\x14\xe5!\xe6?' +p46385 +tp46386 +bsg252 +g260 +sg48 +(lp46387 +g0 +(g52 +g2 +Ntp46388 +Rp46389 +(dp46390 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46391 +g179 +tp46392 +Rp46393 +(I1 +(I1 +I1 +I1 +tp46394 +g38 +I00 +S'\xb1\xa7O$\xaa\x1fO@' +p46395 +tp46396 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46397 +g334 +asg113 +I11507 +sg280 +I01 +sbaatp46398 +Rp46399 +sg337 +I00 +sg338 +Nsbaa(lp46400 +g340 +ag0 +(g341 +g2 +Ntp46401 +Rp46402 +(dp46403 +g17 +g46278 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46404 +(lp46405 +g189 +ag0 +(g190 +g2 +Ntp46406 +Rp46407 +(dp46408 +g194 +I01 +sg195 +(lp46409 +g0 +(g197 +g2 +Ntp46410 +Rp46411 +(dp46412 +g201 +g176 +(g177 +(I0 +tp46413 +g179 +tp46414 +Rp46415 +(I1 +(I1 +tp46416 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46417 +tp46418 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46419 +Rp46420 +(dp46421 +g201 +g176 +(g177 +(I0 +tp46422 +g179 +tp46423 +Rp46424 +(I1 +(I2 +tp46425 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46426 +tp46427 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46428 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46429 +g179 +tp46430 +Rp46431 +(I1 +(I1 +I1 +I1 +tp46432 +g38 +I00 +S'\x831\xc3\xde\xaf\xcaF@' +p46433 +tp46434 +bsg238 +g176 +(g177 +(I0 +tp46435 +g179 +tp46436 +Rp46437 +(I1 +(I1 +I1 +I1 +tp46438 +g38 +I00 +S'o*XH\xb0\xa9E?' +p46439 +tp46440 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46441 +g179 +tp46442 +Rp46443 +(I1 +(I1 +I1 +I1 +tp46444 +g38 +I00 +S'dT;2\xd4\xc5\xe6?' +p46445 +tp46446 +bsg252 +g260 +sg48 +(lp46447 +g0 +(g52 +g2 +Ntp46448 +Rp46449 +(dp46450 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46451 +g179 +tp46452 +Rp46453 +(I1 +(I1 +I1 +I1 +tp46454 +g38 +I00 +S'V\xb7Q3\x19\x03P@' +p46455 +tp46456 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46457 +g279 +asg113 +I11510 +sg280 +I01 +sbaa(lp46458 +g401 +ag0 +(g190 +g2 +Ntp46459 +Rp46460 +(dp46461 +g194 +I01 +sg195 +(lp46462 +g0 +(g197 +g2 +Ntp46463 +Rp46464 +(dp46465 +g201 +g176 +(g177 +(I0 +tp46466 +g179 +tp46467 +Rp46468 +(I1 +(I1 +tp46469 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46470 +tp46471 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46472 +Rp46473 +(dp46474 +g201 +g176 +(g177 +(I0 +tp46475 +g179 +tp46476 +Rp46477 +(I1 +(I2 +tp46478 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46479 +tp46480 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46481 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46482 +g179 +tp46483 +Rp46484 +(I1 +(I1 +I1 +I1 +tp46485 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46486 +tp46487 +bsg238 +g176 +(g177 +(I0 +tp46488 +g179 +tp46489 +Rp46490 +(I1 +(I1 +I1 +I1 +tp46491 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46492 +tp46493 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46494 +g179 +tp46495 +Rp46496 +(I1 +(I1 +I1 +I1 +tp46497 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46498 +tp46499 +bsg252 +g260 +sg48 +(lp46500 +g0 +(g52 +g2 +Ntp46501 +Rp46502 +(dp46503 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46504 +g179 +tp46505 +Rp46506 +(I1 +(I1 +I1 +I1 +tp46507 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46508 +tp46509 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46510 +g454 +asg113 +I11511 +sg280 +I01 +sbaatp46511 +Rp46512 +sg337 +I00 +sg338 +Nsbaa(lp46513 +g458 +ag0 +(g459 +g2 +Ntp46514 +Rp46515 +(dp46516 +g17 +g46278 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46517 +(lp46518 +g189 +ag0 +(g190 +g2 +Ntp46519 +Rp46520 +(dp46521 +g194 +I01 +sg195 +(lp46522 +g0 +(g197 +g2 +Ntp46523 +Rp46524 +(dp46525 +g201 +g176 +(g177 +(I0 +tp46526 +g179 +tp46527 +Rp46528 +(I1 +(I1 +tp46529 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46530 +tp46531 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46532 +Rp46533 +(dp46534 +g201 +g176 +(g177 +(I0 +tp46535 +g179 +tp46536 +Rp46537 +(I1 +(I2 +tp46538 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46539 +tp46540 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp46541 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46542 +g179 +tp46543 +Rp46544 +(I1 +(I1 +I1 +I1 +tp46545 +g38 +I00 +S'\x06\x01\x0e\x80\xc3\xd8F@' +p46546 +tp46547 +bsg238 +g176 +(g177 +(I0 +tp46548 +g179 +tp46549 +Rp46550 +(I1 +(I1 +I1 +I1 +tp46551 +g38 +I00 +S'\x91\x1a\ruH\x1cV?' +p46552 +tp46553 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46554 +g179 +tp46555 +Rp46556 +(I1 +(I1 +I1 +I1 +tp46557 +g38 +I00 +S'\x86\xac\x8fB&\xcc\xe6?' +p46558 +tp46559 +bsg252 +g513 +sg48 +(lp46560 +g0 +(g52 +g2 +Ntp46561 +Rp46562 +(dp46563 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp46564 +g179 +tp46565 +Rp46566 +(I1 +(I1 +I1 +I1 +tp46567 +g38 +I00 +S'N\x05\xcd\xe6\x8a\x07P@' +p46568 +tp46569 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp46570 +g527 +asg113 +I11514 +sg280 +I01 +sbaa(lp46571 +g529 +ag0 +(g190 +g2 +Ntp46572 +Rp46573 +(dp46574 +g194 +I01 +sg195 +(lp46575 +g0 +(g197 +g2 +Ntp46576 +Rp46577 +(dp46578 +g201 +g176 +(g177 +(I0 +tp46579 +g179 +tp46580 +Rp46581 +(I1 +(I1 +tp46582 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46583 +tp46584 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46585 +Rp46586 +(dp46587 +g201 +g176 +(g177 +(I0 +tp46588 +g179 +tp46589 +Rp46590 +(I1 +(I2 +tp46591 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46592 +tp46593 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46594 +Rp46595 +(dp46596 +g201 +g176 +(g177 +(I0 +tp46597 +g179 +tp46598 +Rp46599 +(I1 +(I2 +tp46600 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46601 +tp46602 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp46603 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46604 +g179 +tp46605 +Rp46606 +(I1 +(I1 +I1 +I1 +tp46607 +g38 +I00 +S'\xcf\x11;Kw!E@' +p46608 +tp46609 +bsg238 +g176 +(g177 +(I0 +tp46610 +g179 +tp46611 +Rp46612 +(I1 +(I1 +I1 +I1 +tp46613 +g38 +I00 +S'\xce\xaai\x7f\xb2\x9bS?' +p46614 +tp46615 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46616 +g179 +tp46617 +Rp46618 +(I1 +(I1 +I1 +I1 +tp46619 +g38 +I00 +S'#\xe0\x10\xaa\xd4\xec\xe5?' +p46620 +tp46621 +bsg252 +g586 +sg48 +(lp46622 +g0 +(g52 +g2 +Ntp46623 +Rp46624 +(dp46625 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp46626 +g179 +tp46627 +Rp46628 +(I1 +(I1 +I1 +I1 +tp46629 +g38 +I00 +S"1\xbb'\x0f\x0b\xd5N@" +p46630 +tp46631 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp46632 +g600 +asg113 +I11515 +sg280 +I01 +sbaatp46633 +Rp46634 +sg337 +I00 +sg338 +Nsbaa(lp46635 +g604 +ag0 +(g605 +g2 +Ntp46636 +Rp46637 +(dp46638 +g17 +g46278 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46639 +(lp46640 +g611 +ag0 +(g190 +g2 +Ntp46641 +Rp46642 +(dp46643 +g194 +I01 +sg195 +(lp46644 +g0 +(g197 +g2 +Ntp46645 +Rp46646 +(dp46647 +g201 +g176 +(g177 +(I0 +tp46648 +g179 +tp46649 +Rp46650 +(I1 +(I1 +tp46651 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46652 +tp46653 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46654 +Rp46655 +(dp46656 +g201 +g176 +(g177 +(I0 +tp46657 +g179 +tp46658 +Rp46659 +(I1 +(I2 +tp46660 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46661 +tp46662 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp46663 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46664 +g179 +tp46665 +Rp46666 +(I1 +(I1 +I1 +I1 +tp46667 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46668 +tp46669 +bsg238 +g176 +(g177 +(I0 +tp46670 +g179 +tp46671 +Rp46672 +(I1 +(I1 +I1 +I1 +tp46673 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46674 +tp46675 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46676 +g179 +tp46677 +Rp46678 +(I1 +(I1 +I1 +I1 +tp46679 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46680 +tp46681 +bsg252 +g513 +sg48 +(lp46682 +g0 +(g52 +g2 +Ntp46683 +Rp46684 +(dp46685 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp46686 +g179 +tp46687 +Rp46688 +(I1 +(I1 +I1 +I1 +tp46689 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46690 +tp46691 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp46692 +g664 +asg113 +I11518 +sg280 +I01 +sbaa(lp46693 +g666 +ag0 +(g190 +g2 +Ntp46694 +Rp46695 +(dp46696 +g194 +I01 +sg195 +(lp46697 +g0 +(g197 +g2 +Ntp46698 +Rp46699 +(dp46700 +g201 +g176 +(g177 +(I0 +tp46701 +g179 +tp46702 +Rp46703 +(I1 +(I1 +tp46704 +g208 +I00 +S"o'\x00\x00\x00\x00\x00\x00" +p46705 +tp46706 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46707 +Rp46708 +(dp46709 +g201 +g176 +(g177 +(I0 +tp46710 +g179 +tp46711 +Rp46712 +(I1 +(I2 +tp46713 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46714 +tp46715 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp46716 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46717 +g179 +tp46718 +Rp46719 +(I1 +(I1 +I1 +I1 +tp46720 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46721 +tp46722 +bsg238 +g176 +(g177 +(I0 +tp46723 +g179 +tp46724 +Rp46725 +(I1 +(I1 +I1 +I1 +tp46726 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46727 +tp46728 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46729 +g179 +tp46730 +Rp46731 +(I1 +(I1 +I1 +I1 +tp46732 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46733 +tp46734 +bsg252 +g713 +sg48 +(lp46735 +g0 +(g52 +g2 +Ntp46736 +Rp46737 +(dp46738 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp46739 +g179 +tp46740 +Rp46741 +(I1 +(I1 +I1 +I1 +tp46742 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46743 +tp46744 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp46745 +g727 +asg113 +I11519 +sg280 +I01 +sbaatp46746 +Rp46747 +sg337 +I00 +sg338 +Nsbaatp46748 +Rp46749 +aa(lp46750 +I10096 +ag7 +((lp46751 +(lp46752 +g12 +ag0 +(g13 +g2 +Ntp46753 +Rp46754 +(dp46755 +g17 +g0 +(g18 +g2 +Ntp46756 +Rp46757 +(dp46758 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g1780 +sg114 +Nsg46 +Vwater +p46759 +sg116 +g0 +(g117 +g2 +Ntp46760 +Rp46761 +(dp46762 +g121 +(lp46763 +g0 +(g123 +g2 +Ntp46764 +Rp46765 +(dp46766 +g127 +g12231 +sg148 +g162 +sbag0 +(g123 +g2 +Ntp46767 +Rp46768 +(dp46769 +g127 +g31784 +sg148 +g149 +sbasbsg163 +Nsg113 +I10096 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46770 +(lp46771 +g189 +ag0 +(g190 +g2 +Ntp46772 +Rp46773 +(dp46774 +g194 +I01 +sg195 +(lp46775 +g0 +(g197 +g2 +Ntp46776 +Rp46777 +(dp46778 +g201 +g176 +(g177 +(I0 +tp46779 +g179 +tp46780 +Rp46781 +(I1 +(I1 +tp46782 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p46783 +tp46784 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46785 +Rp46786 +(dp46787 +g201 +g176 +(g177 +(I0 +tp46788 +g179 +tp46789 +Rp46790 +(I1 +(I2 +tp46791 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46792 +tp46793 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46794 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46795 +g179 +tp46796 +Rp46797 +(I1 +(I1 +I1 +I1 +tp46798 +g38 +I00 +S'\x99O\xd8!\xdd\x1eH@' +p46799 +tp46800 +bsg238 +g176 +(g177 +(I0 +tp46801 +g179 +tp46802 +Rp46803 +(I1 +(I1 +I1 +I1 +tp46804 +g38 +I00 +S'$\\\x8e\x93\r\xeeD?' +p46805 +tp46806 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46807 +g179 +tp46808 +Rp46809 +(I1 +(I1 +I1 +I1 +tp46810 +g38 +I00 +S'7\xb1\x9d;em\xe7?' +p46811 +tp46812 +bsg252 +g260 +sg48 +(lp46813 +g0 +(g52 +g2 +Ntp46814 +Rp46815 +(dp46816 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46817 +g179 +tp46818 +Rp46819 +(I1 +(I1 +I1 +I1 +tp46820 +g38 +I00 +S'\x9b\xe0\xea-\xebxP@' +p46821 +tp46822 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46823 +g279 +asg113 +I11522 +sg280 +I01 +sbaa(lp46824 +g12 +ag0 +(g190 +g2 +Ntp46825 +Rp46826 +(dp46827 +g194 +I01 +sg195 +(lp46828 +g0 +(g197 +g2 +Ntp46829 +Rp46830 +(dp46831 +g201 +g176 +(g177 +(I0 +tp46832 +g179 +tp46833 +Rp46834 +(I1 +(I1 +tp46835 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p46836 +tp46837 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46838 +Rp46839 +(dp46840 +g201 +g176 +(g177 +(I0 +tp46841 +g179 +tp46842 +Rp46843 +(I1 +(I2 +tp46844 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46845 +tp46846 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46847 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46848 +g179 +tp46849 +Rp46850 +(I1 +(I1 +I1 +I1 +tp46851 +g38 +I00 +S'WJ7*1\xc6I@' +p46852 +tp46853 +bsg238 +g176 +(g177 +(I0 +tp46854 +g179 +tp46855 +Rp46856 +(I1 +(I1 +I1 +I1 +tp46857 +g38 +I00 +S'S\xfc\x02\xb4|!P?' +p46858 +tp46859 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46860 +g179 +tp46861 +Rp46862 +(I1 +(I1 +I1 +I1 +tp46863 +g38 +I00 +S'Jn\x11\xc9O7\xe8?' +p46864 +tp46865 +bsg252 +g260 +sg48 +(lp46866 +g0 +(g52 +g2 +Ntp46867 +Rp46868 +(dp46869 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46870 +g179 +tp46871 +Rp46872 +(I1 +(I1 +I1 +I1 +tp46873 +g38 +I00 +S'\x8cA`\x19\xe4\x06Q@' +p46874 +tp46875 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46876 +g334 +asg113 +I11523 +sg280 +I01 +sbaatp46877 +Rp46878 +sg337 +I00 +sg338 +Nsbaa(lp46879 +g340 +ag0 +(g341 +g2 +Ntp46880 +Rp46881 +(dp46882 +g17 +g46757 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46883 +(lp46884 +g189 +ag0 +(g190 +g2 +Ntp46885 +Rp46886 +(dp46887 +g194 +I01 +sg195 +(lp46888 +g0 +(g197 +g2 +Ntp46889 +Rp46890 +(dp46891 +g201 +g176 +(g177 +(I0 +tp46892 +g179 +tp46893 +Rp46894 +(I1 +(I1 +tp46895 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p46896 +tp46897 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46898 +Rp46899 +(dp46900 +g201 +g176 +(g177 +(I0 +tp46901 +g179 +tp46902 +Rp46903 +(I1 +(I2 +tp46904 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46905 +tp46906 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46907 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46908 +g179 +tp46909 +Rp46910 +(I1 +(I1 +I1 +I1 +tp46911 +g38 +I00 +S'\x99O\xd8!\xdd\x1eH@' +p46912 +tp46913 +bsg238 +g176 +(g177 +(I0 +tp46914 +g179 +tp46915 +Rp46916 +(I1 +(I1 +I1 +I1 +tp46917 +g38 +I00 +S'$\\\x8e\x93\r\xeeD?' +p46918 +tp46919 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46920 +g179 +tp46921 +Rp46922 +(I1 +(I1 +I1 +I1 +tp46923 +g38 +I00 +S'7\xb1\x9d;em\xe7?' +p46924 +tp46925 +bsg252 +g260 +sg48 +(lp46926 +g0 +(g52 +g2 +Ntp46927 +Rp46928 +(dp46929 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46930 +g179 +tp46931 +Rp46932 +(I1 +(I1 +I1 +I1 +tp46933 +g38 +I00 +S'\x9b\xe0\xea-\xebxP@' +p46934 +tp46935 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46936 +g279 +asg113 +I11526 +sg280 +I01 +sbaa(lp46937 +g401 +ag0 +(g190 +g2 +Ntp46938 +Rp46939 +(dp46940 +g194 +I01 +sg195 +(lp46941 +g0 +(g197 +g2 +Ntp46942 +Rp46943 +(dp46944 +g201 +g176 +(g177 +(I0 +tp46945 +g179 +tp46946 +Rp46947 +(I1 +(I1 +tp46948 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p46949 +tp46950 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp46951 +Rp46952 +(dp46953 +g201 +g176 +(g177 +(I0 +tp46954 +g179 +tp46955 +Rp46956 +(I1 +(I2 +tp46957 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p46958 +tp46959 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp46960 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp46961 +g179 +tp46962 +Rp46963 +(I1 +(I1 +I1 +I1 +tp46964 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46965 +tp46966 +bsg238 +g176 +(g177 +(I0 +tp46967 +g179 +tp46968 +Rp46969 +(I1 +(I1 +I1 +I1 +tp46970 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46971 +tp46972 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp46973 +g179 +tp46974 +Rp46975 +(I1 +(I1 +I1 +I1 +tp46976 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46977 +tp46978 +bsg252 +g260 +sg48 +(lp46979 +g0 +(g52 +g2 +Ntp46980 +Rp46981 +(dp46982 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp46983 +g179 +tp46984 +Rp46985 +(I1 +(I1 +I1 +I1 +tp46986 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p46987 +tp46988 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp46989 +g454 +asg113 +I11527 +sg280 +I01 +sbaatp46990 +Rp46991 +sg337 +I00 +sg338 +Nsbaa(lp46992 +g458 +ag0 +(g459 +g2 +Ntp46993 +Rp46994 +(dp46995 +g17 +g46757 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp46996 +(lp46997 +g189 +ag0 +(g190 +g2 +Ntp46998 +Rp46999 +(dp47000 +g194 +I01 +sg195 +(lp47001 +g0 +(g197 +g2 +Ntp47002 +Rp47003 +(dp47004 +g201 +g176 +(g177 +(I0 +tp47005 +g179 +tp47006 +Rp47007 +(I1 +(I1 +tp47008 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p47009 +tp47010 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47011 +Rp47012 +(dp47013 +g201 +g176 +(g177 +(I0 +tp47014 +g179 +tp47015 +Rp47016 +(I1 +(I2 +tp47017 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47018 +tp47019 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp47020 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp47021 +g179 +tp47022 +Rp47023 +(I1 +(I1 +I1 +I1 +tp47024 +g38 +I00 +S'\xd1\xb3\x15f[4H@' +p47025 +tp47026 +bsg238 +g176 +(g177 +(I0 +tp47027 +g179 +tp47028 +Rp47029 +(I1 +(I1 +I1 +I1 +tp47030 +g38 +I00 +S'N\xe9s\x93\x06\x1bX?' +p47031 +tp47032 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp47033 +g179 +tp47034 +Rp47035 +(I1 +(I1 +I1 +I1 +tp47036 +g38 +I00 +S'\xb3B\xc6\x98\xf3v\xe7?' +p47037 +tp47038 +bsg252 +g513 +sg48 +(lp47039 +g0 +(g52 +g2 +Ntp47040 +Rp47041 +(dp47042 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp47043 +g179 +tp47044 +Rp47045 +(I1 +(I1 +I1 +I1 +tp47046 +g38 +I00 +S'\xe6fkG\xa3\x7fP@' +p47047 +tp47048 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp47049 +g527 +asg113 +I11530 +sg280 +I01 +sbaa(lp47050 +g529 +ag0 +(g190 +g2 +Ntp47051 +Rp47052 +(dp47053 +g194 +I01 +sg195 +(lp47054 +g0 +(g197 +g2 +Ntp47055 +Rp47056 +(dp47057 +g201 +g176 +(g177 +(I0 +tp47058 +g179 +tp47059 +Rp47060 +(I1 +(I1 +tp47061 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p47062 +tp47063 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47064 +Rp47065 +(dp47066 +g201 +g176 +(g177 +(I0 +tp47067 +g179 +tp47068 +Rp47069 +(I1 +(I2 +tp47070 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47071 +tp47072 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47073 +Rp47074 +(dp47075 +g201 +g176 +(g177 +(I0 +tp47076 +g179 +tp47077 +Rp47078 +(I1 +(I2 +tp47079 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47080 +tp47081 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp47082 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp47083 +g179 +tp47084 +Rp47085 +(I1 +(I1 +I1 +I1 +tp47086 +g38 +I00 +S'\xa0\xd0\x99Q\x7f=I@' +p47087 +tp47088 +bsg238 +g176 +(g177 +(I0 +tp47089 +g179 +tp47090 +Rp47091 +(I1 +(I1 +I1 +I1 +tp47092 +g38 +I00 +S'\xac\xd7\xc1P\x0b#V?' +p47093 +tp47094 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp47095 +g179 +tp47096 +Rp47097 +(I1 +(I1 +I1 +I1 +tp47098 +g38 +I00 +S'.\xe7R\\U\xf6\xe7?' +p47099 +tp47100 +bsg252 +g586 +sg48 +(lp47101 +g0 +(g52 +g2 +Ntp47102 +Rp47103 +(dp47104 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp47105 +g179 +tp47106 +Rp47107 +(I1 +(I1 +I1 +I1 +tp47108 +g38 +I00 +S'\x8cJ\xea\x044\xd9P@' +p47109 +tp47110 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp47111 +g600 +asg113 +I11531 +sg280 +I01 +sbaatp47112 +Rp47113 +sg337 +I00 +sg338 +Nsbaa(lp47114 +g604 +ag0 +(g605 +g2 +Ntp47115 +Rp47116 +(dp47117 +g17 +g46757 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp47118 +(lp47119 +g611 +ag0 +(g190 +g2 +Ntp47120 +Rp47121 +(dp47122 +g194 +I01 +sg195 +(lp47123 +g0 +(g197 +g2 +Ntp47124 +Rp47125 +(dp47126 +g201 +g176 +(g177 +(I0 +tp47127 +g179 +tp47128 +Rp47129 +(I1 +(I1 +tp47130 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p47131 +tp47132 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47133 +Rp47134 +(dp47135 +g201 +g176 +(g177 +(I0 +tp47136 +g179 +tp47137 +Rp47138 +(I1 +(I2 +tp47139 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47140 +tp47141 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp47142 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp47143 +g179 +tp47144 +Rp47145 +(I1 +(I1 +I1 +I1 +tp47146 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47147 +tp47148 +bsg238 +g176 +(g177 +(I0 +tp47149 +g179 +tp47150 +Rp47151 +(I1 +(I1 +I1 +I1 +tp47152 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47153 +tp47154 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp47155 +g179 +tp47156 +Rp47157 +(I1 +(I1 +I1 +I1 +tp47158 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47159 +tp47160 +bsg252 +g513 +sg48 +(lp47161 +g0 +(g52 +g2 +Ntp47162 +Rp47163 +(dp47164 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp47165 +g179 +tp47166 +Rp47167 +(I1 +(I1 +I1 +I1 +tp47168 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47169 +tp47170 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp47171 +g664 +asg113 +I11534 +sg280 +I01 +sbaa(lp47172 +g666 +ag0 +(g190 +g2 +Ntp47173 +Rp47174 +(dp47175 +g194 +I01 +sg195 +(lp47176 +g0 +(g197 +g2 +Ntp47177 +Rp47178 +(dp47179 +g201 +g176 +(g177 +(I0 +tp47180 +g179 +tp47181 +Rp47182 +(I1 +(I1 +tp47183 +g208 +I00 +S"p'\x00\x00\x00\x00\x00\x00" +p47184 +tp47185 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47186 +Rp47187 +(dp47188 +g201 +g176 +(g177 +(I0 +tp47189 +g179 +tp47190 +Rp47191 +(I1 +(I2 +tp47192 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47193 +tp47194 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp47195 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp47196 +g179 +tp47197 +Rp47198 +(I1 +(I1 +I1 +I1 +tp47199 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47200 +tp47201 +bsg238 +g176 +(g177 +(I0 +tp47202 +g179 +tp47203 +Rp47204 +(I1 +(I1 +I1 +I1 +tp47205 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47206 +tp47207 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp47208 +g179 +tp47209 +Rp47210 +(I1 +(I1 +I1 +I1 +tp47211 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47212 +tp47213 +bsg252 +g713 +sg48 +(lp47214 +g0 +(g52 +g2 +Ntp47215 +Rp47216 +(dp47217 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp47218 +g179 +tp47219 +Rp47220 +(I1 +(I1 +I1 +I1 +tp47221 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p47222 +tp47223 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp47224 +g727 +asg113 +I11535 +sg280 +I01 +sbaatp47225 +Rp47226 +sg337 +I00 +sg338 +Nsbaatp47227 +Rp47228 +aa(lp47229 +I10097 +ag7 +((lp47230 +(lp47231 +g12 +ag0 +(g13 +g2 +Ntp47232 +Rp47233 +(dp47234 +g17 +g0 +(g18 +g2 +Ntp47235 +Rp47236 +(dp47237 +g22 +Nsg23 +g24 +sg25 +Nsg26 +g29 +sg114 +Nsg46 +Vclad +p47238 +sg116 +g0 +(g117 +g2 +Ntp47239 +Rp47240 +(dp47241 +g121 +(lp47242 +g0 +(g123 +g2 +Ntp47243 +Rp47244 +(dp47245 +g127 +g36140 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp47246 +Rp47247 +(dp47248 +g127 +g130 +sg148 +g162 +sbasbsg163 +Nsg113 +I10097 +sbsg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g12 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp47249 +(lp47250 +g189 +ag0 +(g190 +g2 +Ntp47251 +Rp47252 +(dp47253 +g194 +I01 +sg195 +(lp47254 +g0 +(g197 +g2 +Ntp47255 +Rp47256 +(dp47257 +g201 +g176 +(g177 +(I0 +tp47258 +g179 +tp47259 +Rp47260 +(I1 +(I1 +tp47261 +g208 +I00 +S"q'\x00\x00\x00\x00\x00\x00" +p47262 +tp47263 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp47264 +Rp47265 +(dp47266 +g201 +g176 +(g177 +(I0 +tp47267 +g179 +tp47268 +Rp47269 +(I1 +(I2 +tp47270 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p47271 +tp47272 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp47273 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp47274 +g179 +tp47275 +Rp47276 +(I1 +(I1 +I1 +I1 +tp47277 +g38 +I00 +S'\x87\xbd&\xd1K\xe7\r@' +p47278 +tp47279 +bsg238 +g176 +(g177 +(I0 +tp47280 +g179 +tp47281 +Rp47282 +(I1 +(I1 +I1 +I1 +tp47283 +g38 +I00 +S'\xbf\xeb\x9b\xab\x8c\xfe*?' +p47284 +tp47285 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp47286 +g179 +tp47287 +Rp47288 +(I1 +(I1 +I1 +I1 +tp47289 +g38 +I00 +S'\xa6\xb8\xcb\x90\xab\x15\xca?' +p47290 +tp47291 +bsg252 +g260 +sg48 +(lp47292 +g0 +(g52 +g2 +Ntp47293 +Rp47294 +(dp47295 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp47296 +g179 +tp47297 +Rp47298 +(I1 +(I1 +I1 +I1 +tp47299 +g38 +I00 +S'\xd5=\xcf\xa1=\xc2\xe97\xd8?' +p48768 +tp48769 +bsg238 +g176 +(g177 +(I0 +tp48770 +g179 +tp48771 +Rp48772 +(I1 +(I1 +I1 +I1 +tp48773 +g38 +I00 +S'\xc9\r\xa7\xd8\xa6\xc0\x13?' +p48774 +tp48775 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp48776 +g179 +tp48777 +Rp48778 +(I1 +(I1 +I1 +I1 +tp48779 +g38 +I00 +S'\xb6\t\xe3\xd4G\x99\xb0?' +p48780 +tp48781 +bsg252 +g260 +sg48 +(lp48782 +g0 +(g52 +g2 +Ntp48783 +Rp48784 +(dp48785 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp48786 +g179 +tp48787 +Rp48788 +(I1 +(I1 +I1 +I1 +tp48789 +g38 +I00 +S'\xa8E_\x03\x8dW\x17@' +p48790 +tp48791 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp48792 +g334 +asg113 +I11587 +sg280 +I01 +sbaatp48793 +Rp48794 +sg337 +I00 +sg338 +Nsbaa(lp48795 +g340 +ag0 +(g341 +g2 +Ntp48796 +Rp48797 +(dp48798 +g17 +g48673 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g345 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp48799 +(lp48800 +g189 +ag0 +(g190 +g2 +Ntp48801 +Rp48802 +(dp48803 +g194 +I01 +sg195 +(lp48804 +g0 +(g197 +g2 +Ntp48805 +Rp48806 +(dp48807 +g201 +g176 +(g177 +(I0 +tp48808 +g179 +tp48809 +Rp48810 +(I1 +(I1 +tp48811 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p48812 +tp48813 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp48814 +Rp48815 +(dp48816 +g201 +g176 +(g177 +(I0 +tp48817 +g179 +tp48818 +Rp48819 +(I1 +(I2 +tp48820 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p48821 +tp48822 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp48823 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp48824 +g179 +tp48825 +Rp48826 +(I1 +(I1 +I1 +I1 +tp48827 +g38 +I00 +S'\x86tI\xc7\x97:\x0f@' +p48828 +tp48829 +bsg238 +g176 +(g177 +(I0 +tp48830 +g179 +tp48831 +Rp48832 +(I1 +(I1 +I1 +I1 +tp48833 +g38 +I00 +S'\xe6\xb1\xc2P\x9d\xf5,?' +p48834 +tp48835 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp48836 +g179 +tp48837 +Rp48838 +(I1 +(I1 +I1 +I1 +tp48839 +g38 +I00 +S"\r\x81'w\x04\xa8\xca?" +p48840 +tp48841 +bsg252 +g260 +sg48 +(lp48842 +g0 +(g52 +g2 +Ntp48843 +Rp48844 +(dp48845 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp48846 +g179 +tp48847 +Rp48848 +(I1 +(I1 +I1 +I1 +tp48849 +g38 +I00 +S'\xbd\xc6\xc7##\xbe2@' +p48850 +tp48851 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp48852 +g279 +asg113 +I11590 +sg280 +I01 +sbaa(lp48853 +g401 +ag0 +(g190 +g2 +Ntp48854 +Rp48855 +(dp48856 +g194 +I01 +sg195 +(lp48857 +g0 +(g197 +g2 +Ntp48858 +Rp48859 +(dp48860 +g201 +g176 +(g177 +(I0 +tp48861 +g179 +tp48862 +Rp48863 +(I1 +(I1 +tp48864 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p48865 +tp48866 +bsg213 +Nsg23 +g214 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp48867 +Rp48868 +(dp48869 +g201 +g176 +(g177 +(I0 +tp48870 +g179 +tp48871 +Rp48872 +(I1 +(I2 +tp48873 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p48874 +tp48875 +bsg213 +Nsg23 +g226 +sg215 +I1 +sg216 +I1 +sbasg227 +g228 +sg229 +(lp48876 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp48877 +g179 +tp48878 +Rp48879 +(I1 +(I1 +I1 +I1 +tp48880 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p48881 +tp48882 +bsg238 +g176 +(g177 +(I0 +tp48883 +g179 +tp48884 +Rp48885 +(I1 +(I1 +I1 +I1 +tp48886 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p48887 +tp48888 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp48889 +g179 +tp48890 +Rp48891 +(I1 +(I1 +I1 +I1 +tp48892 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p48893 +tp48894 +bsg252 +g260 +sg48 +(lp48895 +g0 +(g52 +g2 +Ntp48896 +Rp48897 +(dp48898 +g56 +Nsg58 +Nsg59 +Nsg46 +g265 +sbasg266 +g176 +(g177 +(I0 +tp48899 +g179 +tp48900 +Rp48901 +(I1 +(I1 +I1 +I1 +tp48902 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p48903 +tp48904 +bsg273 +g274 +sg275 +I01 +sg276 +I01 +sg277 +(lp48905 +g454 +asg113 +I11591 +sg280 +I01 +sbaatp48906 +Rp48907 +sg337 +I00 +sg338 +Nsbaa(lp48908 +g458 +ag0 +(g459 +g2 +Ntp48909 +Rp48910 +(dp48911 +g17 +g48673 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g463 +sg46 +g169 +sg48 +Nsg464 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp48912 +(lp48913 +g189 +ag0 +(g190 +g2 +Ntp48914 +Rp48915 +(dp48916 +g194 +I01 +sg195 +(lp48917 +g0 +(g197 +g2 +Ntp48918 +Rp48919 +(dp48920 +g201 +g176 +(g177 +(I0 +tp48921 +g179 +tp48922 +Rp48923 +(I1 +(I1 +tp48924 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p48925 +tp48926 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp48927 +Rp48928 +(dp48929 +g201 +g176 +(g177 +(I0 +tp48930 +g179 +tp48931 +Rp48932 +(I1 +(I2 +tp48933 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p48934 +tp48935 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp48936 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp48937 +g179 +tp48938 +Rp48939 +(I1 +(I1 +I1 +I1 +tp48940 +g38 +I00 +S"'\xa2\\\xdc\xf2\xa6\x0f@" +p48941 +tp48942 +bsg238 +g176 +(g177 +(I0 +tp48943 +g179 +tp48944 +Rp48945 +(I1 +(I1 +I1 +I1 +tp48946 +g38 +I00 +S'\r\x80@\xe1\xe1\xf0N?' +p48947 +tp48948 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp48949 +g179 +tp48950 +Rp48951 +(I1 +(I1 +I1 +I1 +tp48952 +g38 +I00 +S'\xaf_\x8c\\?\xd0\xca?' +p48953 +tp48954 +bsg252 +g513 +sg48 +(lp48955 +g0 +(g52 +g2 +Ntp48956 +Rp48957 +(dp48958 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp48959 +g179 +tp48960 +Rp48961 +(I1 +(I1 +I1 +I1 +tp48962 +g38 +I00 +S'G\xb3\x12\x8dl\xda2@' +p48963 +tp48964 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp48965 +g527 +asg113 +I11594 +sg280 +I01 +sbaa(lp48966 +g529 +ag0 +(g190 +g2 +Ntp48967 +Rp48968 +(dp48969 +g194 +I01 +sg195 +(lp48970 +g0 +(g197 +g2 +Ntp48971 +Rp48972 +(dp48973 +g201 +g176 +(g177 +(I0 +tp48974 +g179 +tp48975 +Rp48976 +(I1 +(I1 +tp48977 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p48978 +tp48979 +bsg213 +Nsg23 +g543 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp48980 +Rp48981 +(dp48982 +g201 +g176 +(g177 +(I0 +tp48983 +g179 +tp48984 +Rp48985 +(I1 +(I2 +tp48986 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p48987 +tp48988 +bsg213 +Nsg23 +g553 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp48989 +Rp48990 +(dp48991 +g201 +g176 +(g177 +(I0 +tp48992 +g179 +tp48993 +Rp48994 +(I1 +(I2 +tp48995 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p48996 +tp48997 +bsg213 +Nsg23 +g563 +sg215 +I1 +sg216 +I1 +sbasg227 +g564 +sg229 +(lp48998 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp48999 +g179 +tp49000 +Rp49001 +(I1 +(I1 +I1 +I1 +tp49002 +g38 +I00 +S"\xe4\xa8'\x1c\x0f0\xd8?" +p49003 +tp49004 +bsg238 +g176 +(g177 +(I0 +tp49005 +g179 +tp49006 +Rp49007 +(I1 +(I1 +I1 +I1 +tp49008 +g38 +I00 +S'vJ\x94\xf4\xa2\xbb2?' +p49009 +tp49010 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp49011 +g179 +tp49012 +Rp49013 +(I1 +(I1 +I1 +I1 +tp49014 +g38 +I00 +S'|&\xac+*\x93\xb0?' +p49015 +tp49016 +bsg252 +g586 +sg48 +(lp49017 +g0 +(g52 +g2 +Ntp49018 +Rp49019 +(dp49020 +g56 +Nsg58 +Nsg59 +Nsg46 +g591 +sbasg266 +g176 +(g177 +(I0 +tp49021 +g179 +tp49022 +Rp49023 +(I1 +(I1 +I1 +I1 +tp49024 +g38 +I00 +S'\x1e\x16jM\xf3N\x17@' +p49025 +tp49026 +bsg273 +g598 +sg275 +I01 +sg276 +I01 +sg277 +(lp49027 +g600 +asg113 +I11595 +sg280 +I01 +sbaatp49028 +Rp49029 +sg337 +I00 +sg338 +Nsbaa(lp49030 +g604 +ag0 +(g605 +g2 +Ntp49031 +Rp49032 +(dp49033 +g17 +g48673 +sg164 +I00 +sg165 +g166 +sg167 +Nsg168 +g604 +sg46 +g169 +sg48 +Nsg170 +g173 +sg185 +Nsg186 +g7 +((lp49034 +(lp49035 +g611 +ag0 +(g190 +g2 +Ntp49036 +Rp49037 +(dp49038 +g194 +I01 +sg195 +(lp49039 +g0 +(g197 +g2 +Ntp49040 +Rp49041 +(dp49042 +g201 +g176 +(g177 +(I0 +tp49043 +g179 +tp49044 +Rp49045 +(I1 +(I1 +tp49046 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p49047 +tp49048 +bsg213 +Nsg23 +g480 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp49049 +Rp49050 +(dp49051 +g201 +g176 +(g177 +(I0 +tp49052 +g179 +tp49053 +Rp49054 +(I1 +(I2 +tp49055 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p49056 +tp49057 +bsg213 +Nsg23 +g490 +sg215 +I1 +sg216 +I1 +sbasg227 +g491 +sg229 +(lp49058 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp49059 +g179 +tp49060 +Rp49061 +(I1 +(I1 +I1 +I1 +tp49062 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49063 +tp49064 +bsg238 +g176 +(g177 +(I0 +tp49065 +g179 +tp49066 +Rp49067 +(I1 +(I1 +I1 +I1 +tp49068 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49069 +tp49070 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp49071 +g179 +tp49072 +Rp49073 +(I1 +(I1 +I1 +I1 +tp49074 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49075 +tp49076 +bsg252 +g513 +sg48 +(lp49077 +g0 +(g52 +g2 +Ntp49078 +Rp49079 +(dp49080 +g56 +Nsg58 +Nsg59 +Nsg46 +g518 +sbasg266 +g176 +(g177 +(I0 +tp49081 +g179 +tp49082 +Rp49083 +(I1 +(I1 +I1 +I1 +tp49084 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49085 +tp49086 +bsg273 +g525 +sg275 +I01 +sg276 +I01 +sg277 +(lp49087 +g664 +asg113 +I11598 +sg280 +I01 +sbaa(lp49088 +g666 +ag0 +(g190 +g2 +Ntp49089 +Rp49090 +(dp49091 +g194 +I01 +sg195 +(lp49092 +g0 +(g197 +g2 +Ntp49093 +Rp49094 +(dp49095 +g201 +g176 +(g177 +(I0 +tp49096 +g179 +tp49097 +Rp49098 +(I1 +(I1 +tp49099 +g208 +I00 +S"t'\x00\x00\x00\x00\x00\x00" +p49100 +tp49101 +bsg213 +Nsg23 +g680 +sg215 +I1 +sg216 +I1 +sbag0 +(g197 +g2 +Ntp49102 +Rp49103 +(dp49104 +g201 +g176 +(g177 +(I0 +tp49105 +g179 +tp49106 +Rp49107 +(I1 +(I2 +tp49108 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004@' +p49109 +tp49110 +bsg213 +Nsg23 +g690 +sg215 +I1 +sg216 +I1 +sbasg227 +g691 +sg229 +(lp49111 +sg164 +I00 +sg231 +g176 +(g177 +(I0 +tp49112 +g179 +tp49113 +Rp49114 +(I1 +(I1 +I1 +I1 +tp49115 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49116 +tp49117 +bsg238 +g176 +(g177 +(I0 +tp49118 +g179 +tp49119 +Rp49120 +(I1 +(I1 +I1 +I1 +tp49121 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49122 +tp49123 +bsg46 +g143 +sg245 +g176 +(g177 +(I0 +tp49124 +g179 +tp49125 +Rp49126 +(I1 +(I1 +I1 +I1 +tp49127 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49128 +tp49129 +bsg252 +g713 +sg48 +(lp49130 +g0 +(g52 +g2 +Ntp49131 +Rp49132 +(dp49133 +g56 +Nsg58 +Nsg59 +Nsg46 +g718 +sbasg266 +g176 +(g177 +(I0 +tp49134 +g179 +tp49135 +Rp49136 +(I1 +(I1 +I1 +I1 +tp49137 +g38 +I00 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49138 +tp49139 +bsg273 +g725 +sg275 +I01 +sg276 +I01 +sg277 +(lp49140 +g727 +asg113 +I11599 +sg280 +I01 +sbaatp49141 +Rp49142 +sg337 +I00 +sg338 +Nsbaatp49143 +Rp49144 +aatp49145 +Rp49146 +sg170 +g173 +sg227 +Vstatepoint.100.h5 +p49147 +sS'_openmc_geometry' +p49148 +g0 +(copenmc.geometry +Geometry +p49149 +g2 +Ntp49150 +Rp49151 +(dp49152 +g163 +(dp49153 +sS'_root_universe' +p49154 +g0 +(copenmc.universe +Universe +p49155 +g2 +Ntp49156 +Rp49157 +(dp49158 +S'_cells' +p49159 +g7 +((lp49160 +(lp49161 +I10011 +ag0 +(g18 +g2 +Ntp49162 +Rp49163 +(dp49164 +g22 +Nsg23 +S'fill' +p49165 +sg25 +Nsg26 +g0 +(g49155 +g2 +Ntp49166 +Rp49167 +(dp49168 +g49159 +g7 +((lp49169 +(lp49170 +I10000 +ag20 +aa(lp49171 +I10001 +ag739 +aa(lp49172 +I10002 +ag1236 +aa(lp49173 +I10003 +ag1777 +aa(lp49174 +I10004 +ag2331 +aa(lp49175 +I10005 +ag2828 +aa(lp49176 +I10006 +ag3325 +aa(lp49177 +I10007 +ag3822 +aa(lp49178 +I10008 +ag4319 +aa(lp49179 +I10009 +ag4816 +aa(lp49180 +I10010 +ag5313 +aa(lp49181 +I10012 +ag5810 +aa(lp49182 +I10013 +ag6298 +aa(lp49183 +I10014 +ag6795 +aa(lp49184 +I10015 +ag7292 +aa(lp49185 +I10016 +ag7789 +aa(lp49186 +I10017 +ag8268 +aa(lp49187 +I10018 +ag8765 +aa(lp49188 +I10019 +ag9262 +aa(lp49189 +I10020 +ag9741 +aa(lp49190 +I10021 +ag10229 +aa(lp49191 +I10022 +ag10726 +aa(lp49192 +I10023 +ag11223 +aa(lp49193 +I10024 +ag11720 +aa(lp49194 +I10025 +ag12208 +aa(lp49195 +I10026 +ag12705 +aa(lp49196 +I10027 +ag13193 +aa(lp49197 +I10028 +ag13690 +aa(lp49198 +I10029 +ag14187 +aa(lp49199 +I10030 +ag14684 +aa(lp49200 +I10031 +ag15172 +aa(lp49201 +I10032 +ag15669 +aa(lp49202 +I10033 +ag16148 +aa(lp49203 +I10034 +ag16636 +aa(lp49204 +I10035 +ag17133 +aa(lp49205 +I10036 +ag17630 +aa(lp49206 +I10037 +ag18127 +aa(lp49207 +I10038 +ag18624 +aa(lp49208 +I10039 +ag19112 +aa(lp49209 +I10040 +ag19600 +aa(lp49210 +I10041 +ag20079 +aa(lp49211 +I10042 +ag20576 +aa(lp49212 +I10043 +ag21064 +aa(lp49213 +I10044 +ag21552 +aa(lp49214 +I10045 +ag22040 +aa(lp49215 +I10046 +ag22528 +aa(lp49216 +I10047 +ag23007 +aa(lp49217 +I10048 +ag23504 +aa(lp49218 +I10049 +ag23992 +aa(lp49219 +I10050 +ag24480 +aa(lp49220 +I10051 +ag24977 +aa(lp49221 +I10052 +ag25465 +aa(lp49222 +I10053 +ag25953 +aa(lp49223 +I10054 +ag26432 +aa(lp49224 +I10055 +ag26920 +aa(lp49225 +I10056 +ag27417 +aa(lp49226 +I10057 +ag27896 +aa(lp49227 +I10058 +ag28384 +aa(lp49228 +I10059 +ag28863 +aa(lp49229 +I10060 +ag29351 +aa(lp49230 +I10061 +ag29830 +aa(lp49231 +I10062 +ag30318 +aa(lp49232 +I10063 +ag30797 +aa(lp49233 +I10064 +ag31276 +aa(lp49234 +I10065 +ag31773 +aa(lp49235 +I10066 +ag32270 +aa(lp49236 +I10067 +ag32758 +aa(lp49237 +I10068 +ag33237 +aa(lp49238 +I10069 +ag33734 +aa(lp49239 +I10070 +ag34213 +aa(lp49240 +I10071 +ag34692 +aa(lp49241 +I10072 +ag35171 +aa(lp49242 +I10073 +ag35650 +aa(lp49243 +I10074 +ag36129 +aa(lp49244 +I10075 +ag36617 +aa(lp49245 +I10076 +ag37114 +aa(lp49246 +I10077 +ag37593 +aa(lp49247 +I10078 +ag38072 +aa(lp49248 +I10079 +ag38551 +aa(lp49249 +I10080 +ag39039 +aa(lp49250 +I10081 +ag39518 +aa(lp49251 +I10082 +ag40006 +aa(lp49252 +I10083 +ag40494 +aa(lp49253 +I10084 +ag40973 +aa(lp49254 +I10085 +ag41452 +aa(lp49255 +I10086 +ag41940 +aa(lp49256 +I10087 +ag42419 +aa(lp49257 +I10088 +ag42898 +aa(lp49258 +I10089 +ag43377 +aa(lp49259 +I10090 +ag43865 +aa(lp49260 +I10091 +ag44344 +aa(lp49261 +I10092 +ag44832 +aa(lp49262 +I10093 +ag45311 +aa(lp49263 +I10094 +ag45790 +aa(lp49264 +I10095 +ag46278 +aa(lp49265 +I10096 +ag46757 +aa(lp49266 +I10097 +ag47236 +aa(lp49267 +I10098 +ag47715 +aa(lp49268 +I10099 +ag48194 +aa(lp49269 +I10100 +ag48673 +aatp49270 +Rp49271 +sS'_num_regions' +p49272 +I0 +sg113 +I1 +sS'_cell_offsets' +p49273 +g7 +((lp49274 +tp49275 +Rp49276 +sg46 +g169 +sbsg114 +Nsg46 +Vroot cell +p49277 +sg116 +g0 +(g117 +g2 +Ntp49278 +Rp49279 +(dp49280 +g121 +(lp49281 +g0 +(g123 +g2 +Ntp49282 +Rp49283 +(dp49284 +g127 +g0 +(copenmc.surface +ZPlane +p49285 +g2 +Ntp49286 +Rp49287 +(dp49288 +g23 +S'z-plane' +p49289 +sg133 +(dp49290 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sS'z0' +p49291 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00$@' +p49292 +tp49293 +Rp49294 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p49295 +sg113 +I24 +sg146 +(lp49296 +g49291 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp49297 +Rp49298 +(dp49299 +g127 +g21078 +sg148 +g149 +sbag0 +(g123 +g2 +Ntp49300 +Rp49301 +(dp49302 +g127 +g0 +(g49285 +g2 +Ntp49303 +Rp49304 +(dp49305 +g23 +g49289 +sg133 +(dp49306 +g135 +F1.0 +sg136 +F0.0 +sg137 +F0.0 +sg49291 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49307 +tp49308 +Rp49309 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p49310 +sg113 +I26 +sg146 +(lp49311 +g49291 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp49312 +Rp49313 +(dp49314 +g127 +g0 +(copenmc.surface +YPlane +p49315 +g2 +Ntp49316 +Rp49317 +(dp49318 +g23 +S'y-plane' +p49319 +sg133 +(dp49320 +g135 +F1.0 +sS'y0' +p49321 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00$@' +p49322 +tp49323 +Rp49324 +sg136 +F0.0 +sg137 +F0.0 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p49325 +sg113 +I27 +sg146 +(lp49326 +g49321 +asbsg148 +g149 +sbag0 +(g123 +g2 +Ntp49327 +Rp49328 +(dp49329 +g127 +g0 +(g49315 +g2 +Ntp49330 +Rp49331 +(dp49332 +g23 +g49319 +sg133 +(dp49333 +g135 +F1.0 +sg49321 +g34 +(g38 +S'\x00\x00\x00\x00\x00\x00\x00\x00' +p49334 +tp49335 +Rp49336 +sg136 +F0.0 +sg137 +F0.0 +sg142 +F0.0 +ssg46 +g143 +sg144 +Vreflective +p49337 +sg113 +I28 +sg146 +(lp49338 +g49321 +asbsg148 +g162 +sbag0 +(g123 +g2 +Ntp49339 +Rp49340 +(dp49341 +g127 +g18150 +sg148 +g162 +sbasbsg163 +Nsg113 +I10011 +sbaatp49342 +Rp49343 +sg49272 +I0 +sg113 +I0 +sg49273 +g7 +((lp49344 +tp49345 +Rp49346 +sg46 +g169 +sbsbsg164 +I00 +sS'_mgxs_types' +p49347 +(lp49348 +g12 +ag340 +ag458 +ag604 +asg165 +g166 +sg167 +Nsg46 +g169 +sS'_domains' +p49349 +S'all' +p49350 +sS'_opencg_geometry' +p49351 +Nsg464 +NsS'_keff' +p49352 +g34 +(g38 +S'\xeb#\xce\xfcA\xd6\xee?' +p49353 +tp49354 +Rp49355 +sg337 +I00 +sb. \ No newline at end of file diff --git a/sample-input/sph-factors/slab/run-openmc.py b/sample-input/sph-factors/slab/run-openmc.py new file mode 100644 index 000000000..fddea983c --- /dev/null +++ b/sample-input/sph-factors/slab/run-openmc.py @@ -0,0 +1,225 @@ +import numpy as np +import opencg +import openmc +import openmc.mgxs +import openmc.opencg_compatible + +############################################################################### +# Simulation Input File Parameters +############################################################################### + +# OpenMC simulation parameters +batches = 100 +inactive = 10 +particles = 10000 + + +############################################################################### +# Exporting to OpenMC materials.xml File +############################################################################### + +# Instantiate some Nuclides +h1 = openmc.Nuclide('H-1') +b10 = openmc.Nuclide('B-10') +b11 = openmc.Nuclide('B-11') +o16 = openmc.Nuclide('O-16') +u235 = openmc.Nuclide('U-235') +u238 = openmc.Nuclide('U-238') +zr90 = openmc.Nuclide('Zr-90') +zr91 = openmc.Nuclide('Zr-91') +zr92 = openmc.Nuclide('Zr-92') +zr94 = openmc.Nuclide('Zr-94') +zr96 = openmc.Nuclide('Zr-96') + +# Instantiate some Materials and register the appropriate Nuclides +fuel = openmc.Material(name='3.1 w/o enriched UO2') +fuel.set_density('sum') +fuel.add_nuclide(u235, 7.18132E-4,) +fuel.add_nuclide(u238, 2.21546E-2) +fuel.add_nuclide(o16, 4.57642E-2) + +clad = openmc.Material(name='Cladding') +clad.set_density('sum') +clad.add_nuclide(zr90, 2.18865E-2) +clad.add_nuclide(zr91, 4.77292E-3) +clad.add_nuclide(zr92, 7.29551E-3) +clad.add_nuclide(zr94, 7.39335E-3) +clad.add_nuclide(zr96, 1.19110E-3) + +water = openmc.Material(name='Borated Water') +water.set_density('sum') +water.add_nuclide(h1, 4.41459E-2) +water.add_nuclide(o16, 2.20729E-2) +water.add_nuclide(b10, 9.52537E-6) +water.add_nuclide(b11, 3.83408E-5) +water.add_s_alpha_beta(name='HH2O', xs='71t') + +# Instantiate a MaterialsFile, add Materials +materials_file = openmc.MaterialsFile() +materials_file.add_materials([fuel, clad, water]) +materials_file.make_isotropic_in_lab() +materials_file.default_xs = '71c' + +# Export to "materials.xml" +materials_file.export_to_xml() + +# Get OpenCG versions of each OpenMC material to fill OpenCG Cells below +opencg_fuel = openmc.opencg_compatible.get_opencg_material(fuel) +opencg_clad = openmc.opencg_compatible.get_opencg_material(clad) +opencg_water = openmc.opencg_compatible.get_opencg_material(water) + + +############################################################################### +# Exporting to OpenMC geometry.xml File +############################################################################### + +# Create bounding surfaces +min_x = opencg.XPlane(boundary='reflective', x0=0.0) +max_x = opencg.XPlane(boundary='reflective', x0=5.0) +min_y = opencg.YPlane(boundary='reflective', y0=0.0) +max_y = opencg.YPlane(boundary='reflective', y0=10.0) +min_z = opencg.ZPlane(boundary='reflective', z0=0.0) +max_z = opencg.ZPlane(boundary='reflective', z0=10.0) + +# Create material interfacial surfaces +left = opencg.XPlane(surface_id=1, boundary='interface', x0=2.0) +right = opencg.XPlane(surface_id=2, boundary='interface', x0=2.4) + +# Create a Universe to encapsulate the 1D slab +slab_universe = opencg.Universe(name='1D slab') + +# Create fuel Cell +fuel_cell = opencg.Cell(name='fuel') +fuel_cell.fill = opencg_fuel +fuel_cell.add_surface(halfspace=+1, surface=min_x) +fuel_cell.add_surface(halfspace=-1, surface=left) +slab_universe.add_cell(fuel_cell) + +# Create clad Cell +clad_cell = opencg.Cell(name='clad') +clad_cell.fill = opencg_clad +clad_cell.add_surface(halfspace=+1, surface=left) +clad_cell.add_surface(halfspace=-1, surface=right) +slab_universe.add_cell(clad_cell) + +# Create water Cell +water_cell = opencg.Cell(name='water') +water_cell.fill = opencg_water +water_cell.add_surface(halfspace=+1, surface=right) +water_cell.add_surface(halfspace=-1, surface=max_x) +slab_universe.add_cell(water_cell) + +# Create root Cell +root_cell = opencg.Cell(name='root cell') +root_cell.fill = slab_universe + +# Add boundary planes +root_cell.add_surface(halfspace=+1, surface=min_x) +root_cell.add_surface(halfspace=-1, surface=max_x) +root_cell.add_surface(halfspace=+1, surface=min_y) +root_cell.add_surface(halfspace=-1, surface=max_y) +root_cell.add_surface(halfspace=+1, surface=min_z) +root_cell.add_surface(halfspace=-1, surface=max_z) + +# Create root Universe +root_universe = opencg.Universe(universe_id=0, name='root universe') +root_universe.add_cell(root_cell) + +# Instantiate OpenCG's linear mesh operators for spatial discretization +fuel_mesh = opencg.LinearMesh('x', fuel_cell.min_x, fuel_cell.max_x, 40) +clad_mesh = opencg.LinearMesh('x', clad_cell.min_x, clad_cell.max_x, 20) +water_mesh = opencg.LinearMesh('x', water_cell.min_x, water_cell.max_x, 40) + +# Discretize the fuel, clad and water cells +fuel_cells = fuel_mesh.subdivide_cell(fuel_cell, slab_universe) +clad_cells = clad_mesh.subdivide_cell(clad_cell, slab_universe) +water_cells = water_mesh.subdivide_cell(water_cell, slab_universe) + +# Create Geometry and set root Universe +opencg_geometry = opencg.Geometry() +opencg_geometry.root_universe = root_universe + +# Get an OpenMC version of this OpenCG geometry +openmc_geometry = openmc.opencg_compatible.get_openmc_geometry(opencg_geometry) + +# Instantiate a GeometryFile, register Geometry, and export to XML +geometry_file = openmc.GeometryFile() +geometry_file.geometry = openmc_geometry +geometry_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC settings.xml File +############################################################################### + +# Construct uniform initial source distribution over fissionable zones +lower_left = opencg_geometry.bounds[:3] +upper_right = opencg_geometry.bounds[3:] +source = openmc.source.Source(space=openmc.stats.Box(lower_left, upper_right)) +source.only_fissionable = True + +# Instantiate a SettingsFile +settings_file = openmc.SettingsFile() +settings_file.batches = batches +settings_file.inactive = inactive +settings_file.particles = particles +settings_file.output = {'tallies': False, 'summary': True} +settings_file.source = source +settings_file.sourcepoint_write = False + +# Export to "settings.xml" +settings_file.export_to_xml() + + +############################################################################### +# Exporting to OpenMC plots.xml File +############################################################################### + +# Find the edge widths for the geometry's bounding box +delta_x = opencg_geometry.max_x - opencg_geometry.min_x +delta_y = opencg_geometry.max_y - opencg_geometry.min_y +delta_z = opencg_geometry.max_z - opencg_geometry.min_z + +# Instantiate a Plot +plot = openmc.Plot() +plot.origin = [delta_x/2., delta_y/2., delta_z/2.] +plot.width = [delta_x, delta_z] +plot.pixels = [250, 250] +plot.color = 'cell' + +# Instantiate a PlotsFile, add Plot, and export to "plots.xml" +plot_file = openmc.PlotsFile() +plot_file.add_plot(plot) +plot_file.export_to_xml() + + +############################################################################### +# Create OpenMC MGXS Library +############################################################################### + +# Instantiate a 1-group EnergyGroups object +groups = openmc.mgxs.EnergyGroups() +groups.group_edges = [0., 20.] + +# Initialize an MGXS Library for OpenMOC +mgxs_lib = openmc.mgxs.Library(openmc_geometry, by_nuclide=False) +mgxs_lib.energy_groups = groups +mgxs_lib.mgxs_types = ['total', 'nu-fission', 'nu-scatter matrix', 'chi'] +mgxs_lib.domain_type = 'cell' +mgxs_lib.correction = None +mgxs_lib.domains = openmc_geometry.get_all_material_cells() +mgxs_lib.build_library() + +# Create a "tallies.xml" file for the MGXS Library +tallies_file = openmc.TalliesFile() +mgxs_lib.add_to_tallies_file(tallies_file, merge=True) +tallies_file.export_to_xml() + + +############################################################################### +# Run OpenMC Simulation +############################################################################### + +# Run OpenMC +executor = openmc.Executor() +executor.run_simulation(output=True, mpi_procs=3) diff --git a/sample-input/sph-factors/slab/sph-factors.py b/sample-input/sph-factors/slab/sph-factors.py new file mode 100644 index 000000000..1f74030b2 --- /dev/null +++ b/sample-input/sph-factors/slab/sph-factors.py @@ -0,0 +1,141 @@ +import openmoc +import openmc.mgxs + +import numpy as np +import matplotlib + +# Enable Matplotib to work for headless nodes +matplotlib.use('Agg') +import matplotlib.pyplot as plt +plt.ioff() + + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Eigenvalue Calculation w/o SPH Factors +############################################################################### + +# Initialize 2-group OpenMC multi-group cross section library for a pin cell +mgxs_lib = openmc.mgxs.Library.load_from_file(filename='mgxs', directory='.') + +# Create an OpenMOC Geometry from the OpenCG Geometry +openmoc_geometry = \ + openmoc.opencg_compatible.get_openmoc_geometry(mgxs_lib.opencg_geometry) + +# Load cross section data +openmoc_materials = \ + openmoc.materialize.load_openmc_mgxs_lib(mgxs_lib, openmoc_geometry) + +# Initialize an OpenMOC TrackGenerator and Solver +track_generator = openmoc.TrackGenerator(openmoc_geometry, opts.num_azim, + opts.track_spacing) +track_generator.generateTracks() + +# Initialize an OpenMOC Solver +solver = openmoc.CPUSolver(track_generator) +solver.setConvergenceThreshold(opts.tolerance) +solver.setNumThreads(opts.num_omp_threads) + +# Run an eigenvalue calulation with the MGXS from OpenMC +solver.computeEigenvalue() +solver.printTimerReport() +keff_no_sph = solver.getKeff() + +# Extract the OpenMOC scalar fluxes +fluxes_no_sph = openmoc.process.get_scalar_fluxes(solver) + + +############################################################################### +# Eigenvalue Calculation with SPH Factors +############################################################################### + +# Compute SPH factors +sph, sph_mgxs_lib, sph_indices = \ + openmoc.materialize.compute_sph_factors(mgxs_lib, + track_spacing=opts.track_spacing, + num_azim=opts.num_azim, + num_threads=opts.num_omp_threads) + +# Load the SPH-corrected MGXS library data +materials = \ + openmoc.materialize.load_openmc_mgxs_lib(sph_mgxs_lib, openmoc_geometry) + +# Run an eigenvalue calculation with the SPH-corrected modifed MGXS library +solver.computeEigenvalue() +solver.printTimerReport() +keff_with_sph = solver.getKeff() + +# Report the OpenMC and OpenMOC eigenvalues +openmoc.log.py_printf('RESULT', 'OpenMOC keff w/o SPH: \t%1.5f', keff_no_sph) +openmoc.log.py_printf('RESULT', 'OpenMOC keff w/ SPH: \t%1.5f', keff_with_sph) +openmoc.log.py_printf('RESULT', 'OpenMC keff: \t\t0.96281 +/- 0.00009') + +# Extract the OpenMOC scalar fluxes +fluxes_sph = openmoc.process.get_scalar_fluxes(solver) * sph + + +############################################################################### +# Plottting Scalar Fluxes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +# Allocate arrays for FSR-specific data to extract from OpenMOC model +num_fsrs = openmoc_geometry.getNumFSRs() +cell_ids = np.zeros(num_fsrs, dtype=np.int) +centroids = np.zeros(num_fsrs, dtype=np.float) +volumes = np.zeros(num_fsrs, dtype=np.float) + +# Find the cell IDs, volumes, centroids and fluxes for each FSR +for fsr_id in range(num_fsrs): + cell = openmoc_geometry.findCellContainingFSR(fsr_id) + cell_ids[fsr_id] = cell.getId() + volumes[fsr_id] = solver.getFSRVolume(fsr_id) + centroids[fsr_id] = cell.getMinX() + +# Organize cell IDs, volumes and fluxes in order of increasing centroid +indices = np.argsort(centroids) +centroids = centroids[indices] +cell_ids = cell_ids[indices] +volumes = volumes[indices] +fluxes_no_sph = fluxes_no_sph[indices,:] +fluxes_sph = fluxes_sph[indices,:] + +# Get OpenMC fluxes +tot_fiss_src = 0. +openmc_fluxes = np.zeros((num_fsrs, mgxs_lib.num_groups)) +for fsr_id, cell_id in enumerate(cell_ids): + + # Get NuFissionXS for cell from MGXS Library + mgxs = mgxs_lib.get_mgxs(cell_id, 'nu-fission') + + # Store this cell's flux + flux_tally = mgxs.tallies['flux'] + openmc_fluxes[fsr_id, :] = flux_tally.get_values().flatten() + + # Increment the total fission source + nu_fission = mgxs.tallies['nu-fission'] + tot_fiss_src += np.sum(nu_fission.mean) + +# Normalize OpenMC flux to total fission source * volume to compare to OpenMOC +openmc_fluxes /= volumes[:,np.newaxis] * tot_fiss_src + +# Plot the OpenMOC and OpenMC spatially-varying fluxes +for group in range(mgxs_lib.num_groups): + fig = plt.figure() + plt.plot(centroids, openmc_fluxes[:,group]) + plt.plot(centroids, fluxes_no_sph[:,group]) + plt.plot(centroids, fluxes_sph[:,group]) + plt.legend(['openmc', 'openmoc (w/o sph)', 'openmoc (sph)'],loc='best') + plt.title('Volume-Averaged Scalar Flux (Group {})'.format(group+1)) + plt.xlabel('x [cm]') + plt.ylabel('flux') + plt.savefig('flux-group-{}.png'.format(group+1), bbox_inches='tight') diff --git a/sample-input/subcritical/subcritical.py b/sample-input/subcritical/subcritical.py new file mode 100644 index 000000000..f992d00c3 --- /dev/null +++ b/sample-input/subcritical/subcritical.py @@ -0,0 +1,162 @@ +import numpy as np +import openmoc + +############################################################################### +# Main Simulation Parameters +############################################################################### + +opts = openmoc.options.Options() + +openmoc.log.set_log_level('NORMAL') + + +############################################################################### +# Creating Materials +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') + +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') + + +############################################################################### +# Creating Surfaces +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') + +left =openmoc. XPlane(x=-5.0, name='left') +right = openmoc.XPlane(x=5.0, name='right') +bottom = openmoc.YPlane(y=-5.0, name='bottom') +top = openmoc.YPlane(y=5.0, name='top') +boundaries = [left, right, top, bottom] + +for boundary in boundaries: boundary.setBoundaryType(openmoc.VACUUM) + + +############################################################################### +# Creating Cells +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating cells...') + +water_cell = openmoc.Cell(name='water') +water_cell.setFill(materials['Water']) + +fuel_cell = openmoc.Cell(name='fuel') +fuel_cell.setFill(materials['UO2']) + +source_cell = openmoc.Cell(name='source') +source_cell.setFill(materials['Water']) + +root_cell = openmoc.Cell(name='root cell') +root_cell.addSurface(halfspace=+1, surface=left) +root_cell.addSurface(halfspace=-1, surface=right) +root_cell.addSurface(halfspace=+1, surface=bottom) +root_cell.addSurface(halfspace=-1, surface=top) + + +############################################################################### +# Creating Universes +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating universes...') + +water_univ = openmoc.Universe(name='water') +fuel_univ = openmoc.Universe(name='fuel') +source_univ = openmoc.Universe(name='source') +root_universe = openmoc.Universe(name='root universe') + +water_univ.addCell(water_cell) +fuel_univ.addCell(fuel_cell) +source_univ.addCell(source_cell) +root_universe.addCell(root_cell) + + +############################################################################### +# Creating Lattices +############################################################################### + +# Number of lattice cells +num_x = 100 +num_y = 100 + +# Compute widths of each lattice cell +width_x = (root_universe.getMaxX() - root_universe.getMinX()) / num_y +width_y = (root_universe.getMaxY() - root_universe.getMinY()) / num_x + +# Create 2D array of Universes in each lattice cell +universes = [[water_univ]*num_x for _ in range(num_y)] + +# Place fixed source Universe at (x=10, y=10) +source_x = 2.5 +source_y = 2.5 +lat_x = (root_universe.getMaxX() - source_x) / width_x +lat_y = (root_universe.getMaxY() - source_y) / width_y +universes[int(lat_x)][int(lat_y)] = source_univ + +# Place fuel Universes at (x=[-0.5, 0.5], y=[-0.5,0.5]) +fuel_x = np.array([-0.5,0.5]) +fuel_y = np.array([-0.5,0.5]) +lat_x = (root_universe.getMaxX() - fuel_x) / width_x +lat_y = (root_universe.getMaxY() - fuel_y) / width_y + +for i in np.arange(lat_x[1], lat_x[0], dtype=np.int): + for j in np.arange(lat_y[1], lat_y[0], dtype=np.int): + universes[i][j] = fuel_univ + +openmoc.log.py_printf('NORMAL', \ + 'Creating a {0}x{0} lattice...'.format(num_x, num_y)) + +lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) +lattice.setWidth(width_x=width_x, width_y=width_y) +lattice.setUniverses([universes]) +root_cell.setFill(lattice) + + +############################################################################### +# Creating the Geometry +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Creating geometry...') + +geometry = openmoc.Geometry() +geometry.setRootUniverse(root_universe) + + +############################################################################### +# Creating the TrackGenerator +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') + +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) +track_generator.generateTracks() + + +############################################################################### +# Running a Simulation +############################################################################### + +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.setFixedSourceByCell(source_cell, group=3, source=1e-2) +solver.computeSource(opts.max_iters, k_eff=0.6) +solver.printTimerReport() + + +############################################################################### +# Generating Plots +############################################################################### + +openmoc.log.py_printf('NORMAL', 'Plotting data...') + +openmoc.plotter.plot_materials(geometry, gridsize=250) +openmoc.plotter.plot_cells(geometry, gridsize=250) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=250) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) + +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/sample-input/tiny-lattice/tiny-lattice.py b/sample-input/tiny-lattice/tiny-lattice.py index 7d298ca2c..0547d1ea5 100644 --- a/sample-input/tiny-lattice/tiny-lattice.py +++ b/sample-input/tiny-lattice/tiny-lattice.py @@ -1,67 +1,56 @@ -from openmoc import * -import openmoc.log as log -import openmoc.plotter as plotter -import openmoc.materialize as materialize -from openmoc.options import Options - +import openmoc ############################################################################### # Main Simulation Parameters ############################################################################### -options = Options() - -num_threads = options.getNumThreads() -track_spacing = options.getTrackSpacing() -num_azim = options.getNumAzimAngles() -tolerance = options.getTolerance() -max_iters = options.getMaxIterations() +opts = openmoc.options.Options() -log.set_log_level('NORMAL') +openmoc.log.set_log_level('NORMAL') ############################################################################### # Creating Materials ############################################################################### -log.py_printf('NORMAL', 'Importing materials data from HDF5...') +openmoc.log.py_printf('NORMAL', 'Importing materials data from HDF5...') -materials = materialize.materialize('../c5g7-materials.h5') +materials = openmoc.materialize.load_from_hdf5('c5g7-mgxs.h5', '../') ############################################################################### # Creating Surfaces ############################################################################### -log.py_printf('NORMAL', 'Creating surfaces...') +openmoc.log.py_printf('NORMAL', 'Creating surfaces...') -circle = Circle(x=0.0, y=0.0, radius=0.8, name='pin') -left = XPlane(x=-2.0, name='left') -right = XPlane(x=2.0, name='right') -top = YPlane(y=2.0, name='top') -bottom = YPlane(y=-2.0, name='bottom') +zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.8, name='pin') +left = openmoc.XPlane(x=-2.0, name='left') +right = openmoc.XPlane(x=2.0, name='right') +top = openmoc.YPlane(y=2.0, name='top') +bottom = openmoc.YPlane(y=-2.0, name='bottom') -left.setBoundaryType(REFLECTIVE) -right.setBoundaryType(REFLECTIVE) -top.setBoundaryType(REFLECTIVE) -bottom.setBoundaryType(REFLECTIVE) +left.setBoundaryType(openmoc.REFLECTIVE) +right.setBoundaryType(openmoc.REFLECTIVE) +top.setBoundaryType(openmoc.REFLECTIVE) +bottom.setBoundaryType(openmoc.REFLECTIVE) ############################################################################### # Creating Cells ############################################################################### -log.py_printf('NORMAL', 'Creating cells...') +openmoc.log.py_printf('NORMAL', 'Creating cells...') -fuel = CellBasic(name='fuel') -fuel.setMaterial(materials['UO2']) -fuel.addSurface(halfspace=-1, surface=circle) +fuel = openmoc.Cell(name='fuel') +fuel.setFill(materials['UO2']) +fuel.addSurface(halfspace=-1, surface=zcylinder) -moderator = CellBasic(name='moderator') -moderator.setMaterial(materials['Water']) -moderator.addSurface(halfspace=+1, surface=circle) +moderator = openmoc.Cell(name='moderator') +moderator.setFill(materials['Water']) +moderator.addSurface(halfspace=+1, surface=zcylinder) -root_cell = CellFill(name='root cell') +root_cell = openmoc.Cell(name='root cell') root_cell.addSurface(halfspace=+1, surface=left) root_cell.addSurface(halfspace=-1, surface=right) root_cell.addSurface(halfspace=+1, surface=bottom) @@ -72,10 +61,10 @@ # Creating Universes ############################################################################### -log.py_printf('NORMAL', 'Creating universes...') +openmoc.log.py_printf('NORMAL', 'Creating universes...') -pincell = Universe(name='pin cell') -root_universe = Universe(name='root universe') +pincell = openmoc.Universe(name='pin cell') +root_universe = openmoc.Universe(name='root universe') pincell.addCell(fuel) pincell.addCell(moderator) @@ -86,11 +75,11 @@ # Creating Lattices ############################################################################### -log.py_printf('NORMAL', 'Creating simple 2 x 2 lattice...') +openmoc.log.py_printf('NORMAL', 'Creating simple 2 x 2 lattice...') -lattice = Lattice(name='2x2 lattice') +lattice = openmoc.Lattice(name='2x2 lattice') lattice.setWidth(width_x=2.0, width_y=2.0) -lattice.setUniverses([[pincell, pincell], [pincell, pincell]]) +lattice.setUniverses([[[pincell, pincell], [pincell, pincell]]]) root_cell.setFill(lattice) @@ -99,21 +88,21 @@ # Creating the Geometry ############################################################################### -log.py_printf('NORMAL', 'Creating geometry...') +openmoc.log.py_printf('NORMAL', 'Creating geometry...') -geometry = Geometry() +geometry = openmoc.Geometry() geometry.setRootUniverse(root_universe) -geometry.initializeFlatSourceRegions() ############################################################################### # Creating the TrackGenerator ############################################################################### -log.py_printf('NORMAL', 'Initializing the track generator...') +openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') -track_generator = TrackGenerator(geometry, num_azim, track_spacing) -track_generator.setNumThreads(num_threads) +track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, + opts.track_spacing) +track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() @@ -121,10 +110,10 @@ # Running a Simulation ############################################################################### -solver = CPUSolver(geometry, track_generator) -solver.setNumThreads(num_threads) -solver.setSourceConvergenceThreshold(tolerance) -solver.convergeSource(max_iters) +solver = openmoc.CPUSolver(track_generator) +solver.setNumThreads(opts.num_omp_threads) +solver.setConvergenceThreshold(opts.tolerance) +solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() @@ -132,13 +121,11 @@ # Generating Plots ############################################################################### -log.py_printf('NORMAL', 'Plotting data...') +openmoc.log.py_printf('NORMAL', 'Plotting data...') -#plotter.plot_tracks(track_generator) -#plotter.plot_segments(track_generator) -#plotter.plot_materials(geometry, gridsize=50) -#plotter.plot_cells(geometry, gridsize=50) -#plotter.plot_flat_source_regions(geometry, gridsize=50) -#plotter.plot_fluxes(geometry, solver, energy_groups=[1,2,3,4,5,6,7]) +openmoc.plotter.plot_materials(geometry, gridsize=50) +openmoc.plotter.plot_cells(geometry, gridsize=50) +openmoc.plotter.plot_flat_source_regions(geometry, gridsize=50) +openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1,2,3,4,5,6,7]) -log.py_printf('TITLE', 'Finished') +openmoc.log.py_printf('TITLE', 'Finished') diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..11e9ec40e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +description-file = README.rst \ No newline at end of file diff --git a/setup.py b/setup.py index 802da1bc2..39d725afa 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,31 @@ -from distutils.core import setup -from distutils.command.build_ext import build_ext -from distutils.command.build_py import build_py -from distutils.command.install import install -from distutils.errors import DistutilsOptionError +''' +The setup script for OpenMOC +''' + import os, string +from distutils.errors import DistutilsOptionError +import distutils.ccompiler +import multiprocessing +import multiprocessing.pool as pool + +# Use setuptools only if the user opts-in by setting the USE_SETUPTOOLS. +# This ensures consistent behavior but allows for advanced usage with +# virtualenv, buildout, pip and others. +with_setuptools = False +if 'USE_SETUPTOOLS' in os.environ or 'pip' in __file__: + with_setuptools = True + +if with_setuptools: + from setuptools import setup + from setuptools.command.build_ext import build_ext + from setuptools.command.build_py import build_py + from setuptools.command.install import install +else: + from distutils.core import setup + from distutils.command.build_ext import build_ext + from distutils.command.build_py import build_py + from distutils.command.install import install + import config @@ -26,8 +48,8 @@ class custom_install(install): The custom_install class extracts user-defined options from the command line and uses them to populate the config.configurations class. The - configurations class then uses these options to generate a list of - Python C/C++/CUDA extension objects which are delivered to the distutils + configurations class then uses these options to generate the Python + C/C++/CUDA extension objects which are delivered to the distutils setup method at the end of this script. Developers wishing to extend OpenMOC's functionality with new compilation @@ -40,16 +62,9 @@ class custom_install(install): ('fp=', None, "Floating point precision (single or double) for " + \ "main openmoc module"), ('with-cuda', None, "Build openmoc.cuda module for NVIDIA GPUs"), - ('with-gcc', None, "Build openmoc.gnu modules using GNU compiler"), - ('with-icpc', None, "Build openmoc.intel modules using Intel compiler"), - ('with-bgxlc', None, "Build openmoc.bgxlc modules using IBM compiler"), - ('with-sp', None, "Build modules with single precision"), - ('with-dp', None, "Build modules with double precision"), ('debug-mode', None, "Build with debugging symbols"), ('profile-mode', None, "Build with profiling symbols"), ('with-ccache', None, "Build with ccache for rapid recompilation"), - ('with-papi', None, 'Build modules with PAPI instrumentation'), - ('no-numpy', None, 'Build modules without NumPy C API') ] # Include all of the default options provided by distutils for the @@ -57,17 +72,9 @@ class custom_install(install): user_options += install.user_options # Set some compile options to be boolean switches - boolean_options = ['with-sp', - 'with-dp', - 'with_cuda', - 'with-gcc', - 'with-icpc', - 'with-bgxlc', - 'debug-mode', + boolean_options = ['debug-mode', 'profile-mode', - 'with-ccache', - 'with-papi', - 'no-numpy'] + 'with-ccache'] # Include all of the boolean options provided by distutils for the # install command parent class @@ -81,9 +88,8 @@ def initialize_options(self): python setup.py install - This will build the main openmoc C/C++ Python extension using the - GCC compiler with single precision. No additional modules will be - build with Intel or IBM compilers, or with double precision. + By default, this will build the main openmoc C/C++ Python extension using + the GCC compiler with single precision (default). """ # Run the install command parent class' initialize_options method @@ -93,21 +99,11 @@ def initialize_options(self): self.cc = 'gcc' self.fp = 'single' - # By default, do not build openmoc.gnu.single, openmoc.intel.double, etc - # extension modules - self.with_gcc = False - self.with_icpc = False - self.with_bgxlc = False - self.with_cuda = False - self.with_sp = False - self.with_dp = False - # Set defaults for each of the newly defined compile time options + self.with_cuda = False self.debug_mode = False self.profile_mode = False self.with_ccache = False - self.with_papi = False - self.no_numpy = False def finalize_options(self): @@ -116,8 +112,8 @@ def finalize_options(self): This method performs error checking of the options specified by the user at compile time, and initialize the config.configurations class instance. The method conclude with a call to the - configurations.setup_extension_modules class method which builds - a list of C/C++/CUDA extension modules to be passed to the distutils + configurations.setup_extension_modules class method which creates + the C/C++/CUDA extension modules to be passed to the distutils setup method at the end of this script. """ @@ -130,14 +126,12 @@ class instance. The method conclude with a call to the config.debug_mode = self.debug_mode config.profile_mode = self.profile_mode config.with_ccache = self.with_ccache - config.with_papi = self.with_papi - config.with_numpy = not self.no_numpy # Check that the user specified a supported C++ compiler - if self.cc not in ['gcc', 'icpc', 'bgxlc']: + if self.cc not in ['gcc', 'clang', 'icpc', 'bgxlc']: raise DistutilsOptionError \ ('Must supply the -cc flag with one of the supported ' + - 'C++ compilers: gcc, icpc, bgxlc') + 'C++ compilers: gcc, clang, icpc, bgxlc') else: config.cc = self.cc @@ -149,67 +143,7 @@ class instance. The method conclude with a call to the else: config.fp = self.fp - # Build the openmoc.gnu.single and/or openmoc.gnu.double - # extension module(s) - if self.with_gcc: - config.cpp_compilers += ['gcc'] - - # If a precision level was not specified, use the default - if not any([self.with_sp, self.with_dp]): - config.fp_precision += [self.fp] - - - # Build the openmoc.intel.single and/or openmoc.intel.double - # extension module(s) - if self.with_icpc: - - config.cpp_compilers += ['icpc'] - - # If a precision level was not specified, use the default - if not any([self.with_sp, self.with_dp]): - config.fp_precision += [self.fp] - - - # Build the openmoc.bgxlc.single and/or openmoc.bgxlc.double - # extension module(s) - if self.with_bgxlc: - config.cpp_compilers += ['bgxlc'] - - # If a precision level was not specified, use the default - if not any([self.with_sp, self.with_dp]): - config.fp_precision += [self.fp] - - # If the user requested to build extra modules (ie, openmoc.gnu.single) - # using single precision floating point - if self.with_sp: - - # If no compiler was specified, thrown an error - if not any([self.with_gcc, self.with_icpc, not self.with_bgxlc]): - raise DistutilsOptionError \ - ('Must supply either with-gcc/with-icpc/with-bgxlc for ' + - 'the with-sp option') - - # Otherwise add the single precision option - else: - config.fp_precision += ['single'] - - - # If the user requested to build extra modules (ie, openmoc.gnu.single) - # using single precision floating point - if self.with_dp: - - # If no compiler was specified, thrown an error - if not any([self.with_gcc, self.with_icpc, not self.with_bgxlc]): - raise DistutilsOptionError \ - ('Must supply either with-gcc/with-icpc/with-bgxlc for ' + - 'the with-dp option') - - # Otherwise add the double precision option - else: - config.fp_precision += ['double'] - - # Build a list of the C/C++/CUDA extension modules to be built - # for this distribution + # Build the C/C++/CUDA extension modules for this distribution config.setup_extension_modules() @@ -218,7 +152,7 @@ def customize_compiler(self): """Inject redefined _compile method into distutils This method enables us to choose compilers based on the macros defined - in the compiler flags (ie, '-DGNU', '-DCUDA', etc), or on the + in the compiler flags (ie, '-DGCC', '-DNVCC', etc), or on the source extension (ie, *.cpp, *.cu, etc.). Adapted from Robert McGibbon's CUDA distutils setup provided in open source @@ -236,8 +170,8 @@ def customize_compiler(self): # based on source extension, so we add that functionality here def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): - # If GNU is a defined macro and the source is C++, use gcc - if '-DGNU' in pp_opts and os.path.splitext(src)[1] == '.cpp': + # If compiler is GNU's gcc and the source is C++, use gcc + if config.cc == 'gcc' and os.path.splitext(src)[1] == '.cpp': if config.with_ccache: self.set_executable('compiler_so', 'ccache gcc') else: @@ -245,9 +179,17 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): postargs = config.compiler_flags['gcc'] + # If compiler is Apple's clang and the source is C++, use clang + elif config.cc == 'clang' and os.path.splitext(src)[1] == '.cpp': + if config.with_ccache: + self.set_executable('compiler_so', 'ccache clang') + else: + self.set_executable('compiler_so', 'clang') + + postargs = config.compiler_flags['clang'] - # If INTEL is a defined macro and the source is C++, use icpc - elif '-DINTEL' in pp_opts and os.path.splitext(src)[1] == '.cpp': + # If compiler is Intel's icpc and the source is C++, use icpc + elif config.cc == 'icpc' and os.path.splitext(src)[1] == '.cpp': if config.with_ccache: self.set_executable('compiler_so', 'ccache icpc') else: @@ -255,8 +197,8 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): postargs = config.compiler_flags['icpc'] - # If BGXLC is a defined macro and the source is C++, use bgxlc - elif '-DBGXLC' in pp_opts and os.path.splitext(src)[1] == '.cpp': + # If compiler is IBM's bgxlc and the source is C++, use bgxlc + elif config.cc == 'bgxlc' and os.path.splitext(src)[1] == '.cpp': if config.with_ccache: self.set_executable('compiler_so', 'bgxlc++_r') else: @@ -264,10 +206,9 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): postargs = config.compiler_flags['bgxlc'] - - # If CUDA is a defined macro and the source is C++, compile + # If NVCC is a defined macro and the source is C++, compile # SWIG-wrapped CUDA code with gcc - elif '-DCUDA' in pp_opts and os.path.splitext(src)[1] == '.cpp': + elif '-DNVCC' in pp_opts and os.path.splitext(src)[1] == '.cpp': if config.with_ccache: self.set_executable('compiler_so', 'ccache gcc') else: @@ -275,9 +216,8 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): postargs = config.compiler_flags['gcc'] - - # If CUDA is a defined macro and the source is CUDA, use nvcc - elif '-DCUDA' in pp_opts and os.path.splitext(src)[1] == '.cu': + # If NVCC is a defined macro and the source is CUDA, use nvcc + elif '-DNVCC' in pp_opts and os.path.splitext(src)[1] == '.cu': if config.with_ccache: self.set_executable('compiler_so', 'ccache nvcc') else: @@ -285,7 +225,6 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): postargs = config.compiler_flags['nvcc'] - # If we cannot determine how to compile this file, throw exception else: raise EnvironmentError('Unable to compile ' + str(src)) @@ -319,65 +258,26 @@ def link(target_desc, objects, output_filename, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): - # If compiling different extensions of openmoc using different compilers - # and/or floating point precision levels, we must remove autogenerated - # files from distutils for each subsequent extension. If the user is - # compiling multiple modules at once (ie, openmoc.gnu.single and - # openmoc.intel.single) we have to ensure that only one of the objects - # openmoc_gnu_single.o or openmoc_intel_single.o is specified at the - # link stage. Unfortunately, distutils enumerates all object files - # compiled up to this point at the final linker stage which leads to - # 'previously defined...' errors - for obj in objects[:]: - - if 'openmoc' in obj: - - if 'intel' in output_filename and 'intel' not in obj: - objects = [o for o in objects if o is not obj] - elif 'intel' not in output_filename and 'intel' in obj: - objects = [o for o in objects if o is not obj] - - if 'gnu' in output_filename and 'gnu' not in obj: - objects = [o for o in objects if o is not obj] - elif 'gnu' not in output_filename and 'gnu' in obj: - objects = [o for o in objects if o is not obj] - if 'bgxlc' in output_filename and 'bgxlc' not in obj: - objects = [o for o in objects if o is not obj] - elif 'bgxlc' not in output_filename and 'bgxlc' in obj: - objects = [o for o in objects if o is not obj] - - if 'single' in output_filename and 'single' not in obj: - objects = [o for o in objects if o is not obj] - elif 'single' not in output_filename and 'single' in obj: - objects = [o for o in objects if o is not obj] - - if 'double' in output_filename and 'double' not in obj: - objects = [o for o in objects if o is not obj] - elif 'double' not in output_filename and 'double' in obj: - objects = [o for o in objects if o is not obj] - - # If the linker receives -fopenmp as an option, then the objects - # are built by a GNU compiler - if '-fopenmp' in extra_postargs: - self.set_executable('linker_so', 'g++') - self.set_executable('linker_exe', 'g++') - - # If the linker receives -openmp as an option, then the objects - # are built by a GNU compiler - if '-openmp' in extra_postargs: + if config.cc == 'gcc': + self.set_executable('linker_so', 'gcc') + self.set_executable('linker_exe', 'gcc') + + elif config.cc == 'clang': + self.set_executable('linker_so', 'clang') + self.set_executable('linker_exe', 'clang') + + elif config.cc == 'icpc': self.set_executable('linker_so', 'icpc') - self.set_executable('linker_exe', 'icpc') + self.set_executable('linker_exe', 'icpc') - # If the linker receives -qmkshrobj as an option, then the objects - # are build by an IBM compiler - if '-qmkshrobj' in extra_postargs: + elif config.cc == 'bgxlc': self.set_executable('linker_so', 'bgxlc++_r') self.set_executable('linker_exe', 'bgxlc++_r') - # If the filename for the extension contains cuda, use g++ to link + # If the filename for the extension contains cuda, use nvcc to link if 'cuda' in output_filename: - self.set_executable('linker_so', 'g++') - self.set_executable('linker_exe', 'g++') + self.set_executable('linker_so', 'nvcc') + self.set_executable('linker_exe', 'nvcc') # Now call distutils-defined link method super_link(target_desc, objects, @@ -390,6 +290,37 @@ def link(target_desc, objects, output_filename, self.link = link +# monkey-patch for parallel compilation +def parallel_compile(self, sources, output_dir=None, macros=None, + include_dirs=None, debug=0, extra_preargs=None, + extra_postargs=None, depends=None): + """A parallel version of the Distutils compile method + + Note that this routine is modified from StackOverflow post #11013851 + """ + + # Copy args from distutils.ccompiler.CCompiler directly + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) + num_cpus = multiprocessing.cpu_count() + + # Define routine for each thread to use to compile on its own + def _single_compile(obj): + try: src, ext = build[obj] + except KeyError: return + self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) + + # Convert thread mapping to C/C++/CUDA objects to a list and return + list(pool.ThreadPool(num_cpus).imap(_single_compile, objects)) + return objects + + +# Inject parallel_compile to override distutils sequential compile method +distutils.ccompiler.CCompiler.compile=parallel_compile + + # Run the customize_compiler to inject redefined and customized _compile and # link methods into distutils class custom_build_ext(build_ext): @@ -404,63 +335,28 @@ def build_extensions(self): customize_compiler(self.compiler) customize_linker(self.compiler) - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/openmoc_wrap.cpp openmoc/openmoc.i') - - if 'gcc' in config.cpp_compilers and 'single' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/gnu/single/openmoc_gnu_single_wrap.cpp ' + \ - 'openmoc/gnu/single/openmoc_gnu_single.i') - - if 'gcc' in config.cpp_compilers and 'double' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/gnu/double/openmoc_gnu_double_wrap.cpp ' + \ - 'openmoc/gnu/double/openmoc_gnu_double.i') - - if 'icpc' in config.cpp_compilers and 'single' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/intel/single/openmoc_intel_single_wrap.cpp ' + \ - 'openmoc/intel/single/openmoc_intel_single.i') - - if 'icpc' in config.cpp_compilers and 'double' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/intel/double/openmoc_intel_double_wrap.cpp ' + \ - 'openmoc/intel/double/openmoc_intel_double.i') - - if 'bgxlc' in config.cpp_compilers and 'single' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/bgq/single/openmoc_bgq_single_wrap.cpp ' + \ - 'openmoc/bgq/single/openmoc_bgq_single.i') - - if 'bgxlc' in config.cpp_compilers and 'double' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/bgq/double/openmoc_bgq_double_wrap.cpp ' + \ - 'openmoc/bgq/double/openmoc_bgq_double.i') - - if 'nvcc' in config.cpp_compilers: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/cuda/openmoc_cuda_wrap.cpp ' + \ - 'openmoc/cuda/openmoc_cuda.i') - - if 'nvcc' in config.cpp_compilers and 'single' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/cuda/single/openmoc_cuda_single_wrap.cpp ' + \ - 'openmoc/cuda/single/openmoc_cuda_single.i') - - if 'nvcc' in config.cpp_compilers and 'double' in config.fp_precision: - os.system('swig {0} -o '.format(str.join(' ', config.swig_flags)) + \ - 'openmoc/cuda/double/openmoc_cuda_double_wrap.cpp ' + \ - 'openmoc/cuda/double/openmoc_cuda_double.i') + # Append a macro for the compiler to the SWIG flags + swig_flags = config.swig_flags + ['-D' + config.cc.upper()] + + os.system('swig {0} -o '.format(str.join(' ', swig_flags)) + \ + 'openmoc/openmoc_wrap.cpp openmoc/openmoc.i') + + if config.with_cuda: + swig_flags = config.swig_flags + ['-DNVCC'] + os.system('swig {0} -o '.format(str.join(' ', swig_flags)) + \ + 'openmoc/cuda/openmoc_cuda_wrap.cpp ' + \ + 'openmoc/cuda/openmoc_cuda.i') build_ext.build_extensions(self) # Run the distutils setup method for the complete build dist = setup(name = 'openmoc', - version = '0.1.4', + version = '0.1.4b', description = 'An open source method of characteristics code for ' + \ 'solving the 2D neutron distribution in nuclear reactors', url = 'https://github.com/mit-crpg/OpenMOC', + download_url = 'https://github.com/mit-crpg/OpenMOC/tarball/v0.1.4b', # Set the C/C++/CUDA extension modules built in setup_extension_modules() # in config.py based on the user-defined flags at compile time @@ -470,6 +366,9 @@ def build_extensions(self): # (ie, openmoc.log, openmoc.materialize, etc) packages = config.packages, + # Include SWIG interface files in package - this is important for PyPI + package_data = {'' : ['*.i*']}, + # Inject our custom compiler and linker triggers cmdclass={ 'build_ext': custom_build_ext, 'install': custom_install} diff --git a/src/CPUSolver.cpp b/src/CPUSolver.cpp index 09e6ec770..6365f0c29 100644 --- a/src/CPUSolver.cpp +++ b/src/CPUSolver.cpp @@ -7,16 +7,13 @@ * and azimuthal angles from the Geometry and TrackGenerator if * passed in as parameters by the user. The constructor initalizes * the number of OpenMP threads to a default of 1. - * @param geometry an optional pointer to the Geometry * @param track_generator an optional pointer to the TrackGenerator */ -CPUSolver::CPUSolver(Geometry* geometry, TrackGenerator* track_generator) - : Solver(geometry, track_generator) { +CPUSolver::CPUSolver(TrackGenerator* track_generator) + : Solver(track_generator) { setNumThreads(1); - _FSR_locks = NULL; - _cmfd_surface_locks = NULL; } @@ -25,17 +22,7 @@ CPUSolver::CPUSolver(Geometry* geometry, TrackGenerator* track_generator) * FSR scalar flux updates, and calls Solver parent class destructor * to deletes arrays for fluxes and sources. */ -CPUSolver::~CPUSolver() { - - if (_FSR_locks != NULL) - delete [] _FSR_locks; - - if (_cmfd_surface_locks != NULL) - delete [] _cmfd_surface_locks; - - if (_surface_currents != NULL) - delete [] _surface_currents; -} +CPUSolver::~CPUSolver() {} /** @@ -48,147 +35,111 @@ int CPUSolver::getNumThreads() { /** - * @brief Returns the scalar flux for some FSR and energy group. - * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest - * @return the FSR scalar flux - */ -FP_PRECISION CPUSolver::getFSRScalarFlux(int fsr_id, int energy_group) { - - /* Error checking */ - if (fsr_id >= _num_FSRs) - log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d in energy" - " group %d since the solver only contains FSR with IDs less" - " than or equal to %d", fsr_id, energy_group, _num_FSRs-1); - - if (fsr_id < 0) - log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " - "in energy group %d since FSRs do not have ", - "negative IDs", fsr_id, energy_group); - - if (energy_group-1 >= _num_groups) - log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " - "in energy group %d since the solver only has %d energy " - "groups", fsr_id, energy_group, _num_groups); - - if (energy_group <= 0) - log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " - "in energy group %d since energy groups are greater than " - "or equal to 1", fsr_id, energy_group); - - return _scalar_flux(fsr_id,energy_group-1); -} - - -/** - * @brief Returns the source for some energy group for a flat source region - * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest - * @return the flat source region source + * @brief Fills an array with the scalar fluxes. + * @details This class method is a helper routine called by the OpenMOC + * Python "openmoc.krylov" module for Krylov subspace methods. + * Although this method appears to require two arguments, in + * reality it only requires one due to SWIG and would be called + * from within Python as follows: + * + * @code + * num_fluxes = num_groups * num_FSRs + * fluxes = solver.getFluxes(num_fluxes) + * @endcode + * + * @param fluxes an array of FSR scalar fluxes in each energy group + * @param num_fluxes the total number of FSR flux values */ -FP_PRECISION CPUSolver::getFSRSource(int fsr_id, int energy_group) { - - /* Error checking */ - if (fsr_id >= _num_FSRs) - log_printf(ERROR, "Unable to return a source for FSR ID = %d in energy " - "group %d since the solver only contains FSR with IDs less than " - "or equal to %d", fsr_id, energy_group, _num_FSRs-1); - - if (fsr_id < 0) - log_printf(ERROR, "Unable to return a source for FSR ID = %d " - "in energy group %d since FSRs do not have negative IDs", - fsr_id, energy_group); - - if (energy_group-1 >= _num_groups) - log_printf(ERROR, "Unable to return a source for FSR ID = %d " - "in energy group %d since the solver only has %d energy " - "groups", fsr_id, energy_group, _num_groups); - - if (energy_group <= 0) - log_printf(ERROR, "Unable to return a source for FSR ID = %d " - "in energy group %d since energy groups are greater than " - "or equal to 1", fsr_id, energy_group); - - Material* material = _FSR_materials[fsr_id]; - FP_PRECISION* nu_sigma_f = material->getNuSigmaF(); - FP_PRECISION* chi = material->getChi(); - FP_PRECISION fission_source = 0.0; - FP_PRECISION scatter_source = 0.0; - FP_PRECISION total_source = 0.0; - - /* Compute fission source for each group */ - if (material->isFissionable()) { - for (int e=0; e < _num_groups; e++) - fission_source += _scalar_flux(fsr_id,e) * nu_sigma_f[e]; +void CPUSolver::getFluxes(FP_PRECISION* out_fluxes, int num_fluxes) { - fission_source /= _k_eff; - } + if (num_fluxes != _num_groups * _num_FSRs) + log_printf(ERROR, "Unable to get FSR scalar fluxes since there are " + "%d groups and %d FSRs which does not match the requested " + "%d flux values", _num_groups, _num_FSRs, num_fluxes); - for (int g=0; g < _num_groups; g++) - scatter_source += material->getSigmaSByGroupInline(g,energy_group-1) - * _scalar_flux(fsr_id,g); + else if (_scalar_flux == NULL) + log_printf(ERROR, "Unable to get FSR scalar fluxes since they " + "have not yet been allocated"); - /* Compute the total source */ - total_source = (fission_source * chi[energy_group-1] + scatter_source) * - ONE_OVER_FOUR_PI; + /* If the user called setFluxes(...) they already have the flux */ + if (_user_fluxes && _scalar_flux == out_fluxes) + return; - return total_source; + /* Otherwise, copy the fluxes into the input array */ + else { +#pragma omp parallel for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + for (int e=0; e < _num_groups; e++) + out_fluxes[r*_num_groups+e] = _scalar_flux(r,e); + } + } } /** - * @brief Return a scalar flux array indexed by FSR IDs and energy groups. - * @details This energy groups are the innermost index, while the FSR ID is - * the outermost index. - * @return an array of flat source region scalar fluxes + * @brief Sets the number of shared memory OpenMP threads to use (>0). + * @param num_threads the number of threads */ -FP_PRECISION* CPUSolver::getFSRScalarFluxes() { +void CPUSolver::setNumThreads(int num_threads) { - if (_scalar_flux == NULL) - log_printf(ERROR, "Unable to returns the Solver's FSR scalar flux array " - "since it has not yet been allocated in memory"); + if (num_threads <= 0) + log_printf(ERROR, "Unable to set the number of threads to %d " + "since it is less than or equal to 0", num_threads); - return _scalar_flux; + /* Set the number of threads for OpenMP */ + _num_threads = num_threads; + omp_set_num_threads(_num_threads); } /** - * @brief Return a surface current array indexed by Cmfd Mesh surface IDs - * and energy groups. - * @return an array of Cmfd Mesh cell surface currents + * @brief Set the flux array for use in transport sweep source calculations. + * @detail This is a helper method for the checkpoint restart capabilities, + * as well as the IRAMSolver in the openmoc.krylov submodule. This + * routine may be used as follows from within Python: + * + * @code + * fluxes = numpy.random.rand(num_FSRs * num_groups, dtype=np.float) + * solver.setFluxes(fluxes) + * @endcode + * + * NOTE: This routine stores a pointer to the fluxes for the Solver + * to use during transport sweeps and other calculations. Hence, the + * flux array pointer is shared between NumPy and the Solver. + * + * @param in_fluxes an array with the fluxes to use + * @param num_fluxes the number of flux values (# groups x # FSRs) */ -FP_PRECISION* CPUSolver::getSurfaceCurrents() { +void CPUSolver::setFluxes(FP_PRECISION* in_fluxes, int num_fluxes) { + if (num_fluxes != _num_groups * _num_FSRs) + log_printf(ERROR, "Unable to set an array with %d flux values for %d " + " groups and %d FSRs", num_fluxes, _num_groups, _num_FSRs); - if (_surface_currents == NULL) - log_printf(ERROR, "Unable to returns the Solver's Cmfd Mesh surface " - "currents array since it has not yet been allocated in memory"); + /* Allocate array if flux arrays have not yet been initialized */ + if (_scalar_flux == NULL) + initializeFluxArrays(); - return _surface_currents; + /* Set the scalar flux array pointer to the array passed in from NumPy */ + _scalar_flux = in_fluxes; + _user_fluxes = true; } /** - * @brief Sets the number of shared memory OpenMP threads to use (>0). - * @param num_threads the number of threads + * @brief Initializes the FSR volumes and Materials array. + * @details This method gets an array of OpenMP mutual exclusion locks + * for each FSR for use in the transport sweep algorithm. */ -void CPUSolver::setNumThreads(int num_threads) { - - if (num_threads <= 0) - log_printf(ERROR, "Unable to set the number of threads for the Solver " - "to %d since it is less than or equal to 0", num_threads); - - _num_threads = num_threads; - - /* Set the number of threads for OpenMP */ - omp_set_num_threads(_num_threads); +void CPUSolver::initializeFSRs() { + Solver::initializeFSRs(); + _FSR_locks = _track_generator->getFSRLocks(); } /** - * @brief Allocates memory for Track boundary angular flux and leakage - * and FSR scalar flux arrays. - * @details Deletes memory for old flux arrays if they were allocated for a - * previous simulation. + * @brief Allocates memory for Track boundary angular and FSR scalar fluxes. + * @details Deletes memory for old flux arrays if they were allocated + * for a previous simulation. */ void CPUSolver::initializeFluxArrays() { @@ -196,32 +147,28 @@ void CPUSolver::initializeFluxArrays() { if (_boundary_flux != NULL) delete [] _boundary_flux; - if (_boundary_leakage != NULL) - delete [] _boundary_leakage; - if (_scalar_flux != NULL) delete [] _scalar_flux; - int size; + if (_old_scalar_flux != NULL) + delete [] _old_scalar_flux; - /* Allocate memory for the Track boundary flux and leakage arrays */ + /* Allocate memory for the Track boundary flux arrays */ try{ - size = 2 * _tot_num_tracks * _polar_times_groups; + int size = 2 * _tot_num_tracks * _polar_times_groups; _boundary_flux = new FP_PRECISION[size]; - _boundary_leakage = new FP_PRECISION[size]; /* Allocate an array for the FSR scalar flux */ size = _num_FSRs * _num_groups; _scalar_flux = new FP_PRECISION[size]; + _old_scalar_flux = new FP_PRECISION[size]; } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the Solver's fluxes. " - "Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for the fluxes"); } } - /** * @brief Allocates memory for FSR source arrays. * @details Deletes memory for old source arrays if they were allocated for a @@ -230,253 +177,70 @@ void CPUSolver::initializeFluxArrays() { void CPUSolver::initializeSourceArrays() { /* Delete old sources arrays if they exist */ - if (_fission_sources != NULL) - delete [] _fission_sources; - - if (_scatter_sources != NULL) - delete [] _scatter_sources; - - if (_old_fission_sources != NULL) - delete [] _old_fission_sources; - if (_reduced_sources != NULL) delete [] _reduced_sources; + if (_fixed_sources != NULL) + delete [] _fixed_sources; - if (_source_residuals != NULL) - delete [] _source_residuals; - - int size; + int size = _num_FSRs * _num_groups; /* Allocate memory for all source arrays */ try{ - - size = _num_FSRs * _num_groups; - _fission_sources = new FP_PRECISION[size]; _reduced_sources = new FP_PRECISION[size]; - - size = _num_threads * _num_groups; - _scatter_sources = new FP_PRECISION[size]; - - size = _num_FSRs; - _old_fission_sources = new FP_PRECISION[size]; - _source_residuals = new FP_PRECISION[size]; - + _fixed_sources = new FP_PRECISION[size]; } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the solver's FSR " - "sources array. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for FSR sources"); } -} - - -/** - * @brief Creates a polar Quadrature object for the solver. - * @details Deletes memory for old Quadrature if one was allocated for a - * previous simulation. - */ -void CPUSolver::initializePolarQuadrature() { - - /* Deletes the old Quadrature if one existed */ - if (_quad != NULL) - delete _quad; + /* Initialize fixed sources to zero */ + memset(_fixed_sources, 0.0, sizeof(FP_PRECISION) * size); - _quad = new Quadrature(_quadrature_type, _num_polar); - _polar_times_groups = _num_groups * _num_polar; + /* Populate fixed source array with any user-defined sources */ + initializeFixedSources(); } /** - * @brief Builds a linear interpolation table to compute exponentials for - * each segment of each Track for each polar angle. + * @brief Populates array of fixed sources assigned by FSR. */ -void CPUSolver::buildExpInterpTable() { +void CPUSolver::initializeFixedSources() { - log_printf(INFO, "Building exponential interpolation table..."); + Solver::initializeFixedSources(); - FP_PRECISION azim_weight; + int fsr_id, group; + std::pair fsr_group_key; + std::map< std::pair, FP_PRECISION >::iterator fsr_iter; - if (_polar_weights != NULL) - delete [] _polar_weights; + /* Populate fixed source array with any user-defined sources */ + for (fsr_iter = _fix_src_FSR_map.begin(); + fsr_iter != _fix_src_FSR_map.end(); ++fsr_iter) { - _polar_weights = new FP_PRECISION[_num_azim*_num_polar]; + /* Get the FSR with an assigned fixed source */ + fsr_group_key = fsr_iter->first; + fsr_id = fsr_group_key.first; + group = fsr_group_key.second; - /* Compute the total azimuthal weight for tracks at each polar angle */ - #pragma omp parallel for private(azim_weight) schedule(guided) - for (int i=0; i < _num_azim; i++) { + if (group <= 0 || group > _num_groups) + log_printf(ERROR,"Unable to use fixed source for group %d in " + "a %d energy group problem", group, _num_groups); - azim_weight = _azim_weights[i]; + if (fsr_id < 0 || fsr_id >= _num_FSRs) + log_printf(ERROR,"Unable to use fixed source for FSR %d with only " + "%d FSRs in the geometry", fsr_id, _num_FSRs); - for (int p=0; p < _num_polar; p++) - _polar_weights(i,p) = azim_weight*_quad->getMultiple(p)*FOUR_PI; + _fixed_sources(fsr_id, group-1) = _fix_src_FSR_map[fsr_group_key]; } - - /* Find largest optical path length track segment */ - FP_PRECISION tau = _track_generator->getMaxOpticalLength(); - - /* Expand tau slightly to accomodate track segments which have a - * length very nearly equal to the maximum value */ - tau *= 1.01; - - /* Set size of interpolation table */ - int num_array_values = tau * sqrt(1./(8.*_source_convergence_thresh*1e-2)); - _exp_table_spacing = tau / num_array_values; - _exp_table_size = _two_times_num_polar * num_array_values; - _exp_table_max_index = _exp_table_size - _two_times_num_polar - 1.; - - log_printf(DEBUG, "Exponential interpolation table size: %i, max index: %i", - _exp_table_size, _exp_table_max_index); - - /* Allocate array for the table */ - if (_exp_table != NULL) - delete [] _exp_table; - - _exp_table = new FP_PRECISION[_exp_table_size]; - - FP_PRECISION expon; - FP_PRECISION intercept; - FP_PRECISION slope; - - /* Create exponential linear interpolation table */ - for (int i=0; i < num_array_values; i ++){ - for (int p=0; p < _num_polar; p++){ - expon = exp(- (i * _exp_table_spacing) / _quad->getSinTheta(p)); - slope = - expon / _quad->getSinTheta(p); - intercept = expon * (1 + (i * _exp_table_spacing)/_quad->getSinTheta(p)); - _exp_table[_two_times_num_polar * i + 2 * p] = slope; - _exp_table[_two_times_num_polar * i + 2 * p + 1] = intercept; - } - } - - /* Compute the reciprocal of the table entry spacing */ - _inverse_exp_table_spacing = 1.0 / _exp_table_spacing; - - return; } /** - * @brief Initializes the FSR volumes and Materials array. - * @details This method assigns each FSR a unique, monotonically increasing - * ID, sets the Material for each FSR, and assigns a volume based on - * the cumulative length of all of the segments inside the FSR. - */ -void CPUSolver::initializeFSRs() { - - log_printf(INFO, "Initializing flat source regions..."); - - /* Delete old FSR arrays if they exist */ - if (_FSR_volumes != NULL) - delete [] _FSR_volumes; - - if (_FSR_materials != NULL) - delete [] _FSR_materials; - - _FSR_volumes = (FP_PRECISION*)calloc(_num_FSRs, sizeof(FP_PRECISION)); - _FSR_materials = new Material*[_num_FSRs]; - _FSR_locks = new omp_lock_t[_num_FSRs]; - - int num_segments; - segment* curr_segment; - segment* segments; - FP_PRECISION volume; - Material* material; - Universe* root_universe = _geometry->getRootUniverse(); - _num_fissionable_FSRs = 0; - - /* Set each FSR's "volume" by accumulating the total length of all Tracks - * inside the FSR. Loop over azimuthal angles, Tracks and Track segments. */ - for (int i=0; i < _tot_num_tracks; i++) { - - int azim_index = _tracks[i]->getAzimAngleIndex(); - num_segments = _tracks[i]->getNumSegments(); - segments = _tracks[i]->getSegments(); - - for (int s=0; s < num_segments; s++) { - curr_segment = &segments[s]; - volume = curr_segment->_length * _azim_weights[azim_index]; - _FSR_volumes[curr_segment->_region_id] += volume; - } - } - - std::map all_materials = _geometry->getAllMaterials(); - - /* Loop over all FSRs to extract FSR material pointers */ - for (int r=0; r < _num_FSRs; r++) { - - /* Assign the Material corresponding to this FSR */ - material = _geometry->findFSRMaterial(r); - _FSR_materials[r] = material; - - /* Increment number of fissionable FSRs */ - if (material->isFissionable()) - _num_fissionable_FSRs++; - - log_printf(DEBUG, "FSR ID = %d has Material ID = %d " - "and volume = %f", r, _FSR_materials[r]->getId(), - _FSR_volumes[r]); - } - - /* Loop over all FSRs to initialize OpenMP locks */ - #pragma omp parallel for schedule(guided) - for (int r=0; r < _num_FSRs; r++) - omp_init_lock(&_FSR_locks[r]); - - return; -} - - -/** - * @brief Initializes Cmfd object for acceleration prior to source iteration. - * @details Instantiates a dummy Cmfd object if one was not assigned to - * the Solver by the user and initializes FSRs, Materials, fluxes - * and the Mesh. This method intializes a global array for the - * surface currents. - */ -void CPUSolver::initializeCmfd() { - - /* Call parent class method */ - Solver::initializeCmfd(); - - /* Delete old Cmfd surface currents array it it exists */ - if (_surface_currents != NULL) - delete [] _surface_currents; - - int size; - - /* Allocate memory for the Cmfd Mesh surface currents array */ - try{ - - /* Allocate an array for the Cmfd Mesh surface currents */ - size = _num_mesh_cells * _cmfd->getNumCmfdGroups() * 8; - _surface_currents = new FP_PRECISION[size]; - } - catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the Solver's Cmfd " - "surface currents. Backtrace:%s", e.what()); - } - - _cmfd->setSurfaceCurrents(_surface_currents); - - /* Initialize an array of OpenMP locks for each Cmfd Mesh surface */ - _cmfd_surface_locks = new omp_lock_t[_num_mesh_cells * 8]; - - /* Loop over all mesh cell surfaces to initialize OpenMP locks */ - #pragma omp parallel for schedule(guided) - for (int r=0; r < _num_mesh_cells*8; r++) - omp_init_lock(&_cmfd_surface_locks[r]); - - return; -} - - -/** - * @brief Zero each Track's boundary fluxes for each energy group and polar - * angle in the "forward" and "reverse" directions. + * @brief Zero each Track's boundary fluxes for each energy group + * and polar angle in the "forward" and "reverse" directions. */ void CPUSolver::zeroTrackFluxes() { - #pragma omp parallel for schedule(guided) +#pragma omp parallel for schedule(guided) for (int t=0; t < _tot_num_tracks; t++) { for (int d=0; d < 2; d++) { for (int p=0; p < _num_polar; p++) { @@ -486,8 +250,6 @@ void CPUSolver::zeroTrackFluxes() { } } } - - return; } @@ -497,45 +259,24 @@ void CPUSolver::zeroTrackFluxes() { */ void CPUSolver::flattenFSRFluxes(FP_PRECISION value) { - #pragma omp parallel for schedule(guided) +#pragma omp parallel for schedule(guided) for (int r=0; r < _num_FSRs; r++) { for (int e=0; e < _num_groups; e++) _scalar_flux(r,e) = value; } - - return; -} - - - /** - * @brief Set the Cmfd Mesh surface currents for each Mesh cell and energy - * group to zero. - */ -void CPUSolver::zeroSurfaceCurrents() { - - #pragma omp parallel for schedule(guided) - for (int r=0; r < _num_mesh_cells; r++) { - for (int s=0; s < 8; s++) { - for (int e=0; e < _num_groups; e++) - _surface_currents(r*8+s,e) = 0.0; - } - } - - return; } /** - * @brief Set the source for each FSR and energy group to some value. - * @param value the value to assign to each FSR source + * @brief Stores the FSR scalar fluxes in the old scalar flux array. */ -void CPUSolver::flattenFSRSources(FP_PRECISION value) { - - #pragma omp parallel for schedule(guided) - for (int r=0; r < _num_FSRs; r++) - _old_fission_sources[r] = value; +void CPUSolver::storeFSRFluxes() { - return; +#pragma omp parallel for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + for (int e=0; e < _num_groups; e++) + _old_scalar_flux(r,e) = _scalar_flux(r,e); + } } @@ -550,8 +291,11 @@ void CPUSolver::normalizeFluxes() { FP_PRECISION tot_fission_source; FP_PRECISION norm_factor; + int size = _num_FSRs * _num_groups; + FP_PRECISION* fission_sources = new FP_PRECISION[_num_FSRs * _num_groups]; + /* Compute total fission source for each FSR, energy group */ - #pragma omp parallel for private(volume, nu_sigma_f) schedule(guided) +#pragma omp parallel for private(volume, nu_sigma_f) schedule(guided) for (int r=0; r < _num_FSRs; r++) { /* Get pointers to important data structures */ @@ -559,239 +303,345 @@ void CPUSolver::normalizeFluxes() { volume = _FSR_volumes[r]; for (int e=0; e < _num_groups; e++) - _fission_sources(r,e) = nu_sigma_f[e] * _scalar_flux(r,e) * volume; + fission_sources(r,e) = nu_sigma_f[e] * _scalar_flux(r,e) * volume; } /* Compute the total fission source */ - tot_fission_source = pairwise_sum(_fission_sources, - _num_FSRs*_num_groups); + tot_fission_source = pairwise_sum(fission_sources,size); + + /* Deallocate memory for fission source array */ + delete [] fission_sources; /* Normalize scalar fluxes in each FSR */ norm_factor = 1.0 / tot_fission_source; - log_printf(DEBUG, "Tot. Fiss. Src = %f, Normalization factor = %f", + log_printf(DEBUG, "Tot. Fiss. Src. = %f, Norm. factor = %f", tot_fission_source, norm_factor); - #pragma omp parallel for schedule(guided) +#pragma omp parallel for schedule(guided) for (int r=0; r < _num_FSRs; r++) { - for (int e=0; e < _num_groups; e++) + for (int e=0; e < _num_groups; e++) { _scalar_flux(r,e) *= norm_factor; + _old_scalar_flux(r,e) *= norm_factor; + } } /* Normalize angular boundary fluxes for each Track */ - #pragma omp parallel for schedule(guided) - for (int i=0; i < _tot_num_tracks; i++) { - for (int j=0; j < 2; j++) { +#pragma omp parallel for schedule(guided) + for (int t=0; t < _tot_num_tracks; t++) { + for (int d=0; d < 2; d++) { for (int p=0; p < _num_polar; p++) { for (int e=0; e < _num_groups; e++) { - _boundary_flux(i,j,p,e) *= norm_factor; + _boundary_flux(t,d,p,e) *= norm_factor; } } } } - - return; } /** - * @brief Computes the total source (fission and scattering) in each FSR. + * @brief Computes the total source (fission, scattering, fixed) in each FSR. * @details This method computes the total source in each FSR based on - * this iteration's current approximation to the scalar flux. A - * residual for the source with respect to the source compute on - * the previous iteration is computed and returned. The residual - * is determined as follows: - * \f$ res = \sqrt{\frac{\displaystyle\sum \displaystyle\sum - * \left(\frac{Q^i - Q^{i-1}}{Q^i}\right)^2}{\# FSRs}} \f$ - * - * @return the residual between this source and the previous source + * this iteration's current approximation to the scalar flux. */ -FP_PRECISION CPUSolver::computeFSRSources() { +void CPUSolver::computeFSRSources() { - int tid; - Material* material; - FP_PRECISION scatter_source; - FP_PRECISION fission_source; - FP_PRECISION fsr_fission_source; - FP_PRECISION* nu_sigma_f; - FP_PRECISION* sigma_s; - FP_PRECISION* sigma_t; - FP_PRECISION* chi; +#pragma omp parallel default(none) + { + int tid; + Material* material; + FP_PRECISION* sigma_t; + FP_PRECISION sigma_s, fiss_mat; + FP_PRECISION scatter_source, fission_source; + FP_PRECISION* fission_sources = new FP_PRECISION[_num_groups]; + FP_PRECISION* scatter_sources = new FP_PRECISION[_num_groups]; + + /* Compute the total source for each FSR */ +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { - FP_PRECISION source_residual = 0.0; + tid = omp_get_thread_num(); + material = _FSR_materials[r]; + sigma_t = material->getSigmaT(); + + /* Compute scatter + fission source for group g */ + for (int g=0; g < _num_groups; g++) { + for (int g_prime=0; g_prime < _num_groups; g_prime++) { + sigma_s = material->getSigmaSByGroup(g_prime+1,g+1); + fiss_mat = material->getFissionMatrixByGroup(g_prime+1,g+1); + scatter_sources[g_prime] = sigma_s * _scalar_flux(r,g_prime); + fission_sources[g_prime] = fiss_mat * _scalar_flux(r,g_prime); + } - FP_PRECISION inverse_k_eff = 1.0 / _k_eff; + scatter_source = pairwise_sum(scatter_sources, + _num_groups); + fission_source = pairwise_sum(fission_sources, + _num_groups); + fission_source /= _k_eff; - /* For all FSRs, find the source */ - #pragma omp parallel for private(tid, material, nu_sigma_f, chi, \ - sigma_s, sigma_t, fission_source, scatter_source, fsr_fission_source) \ - schedule(guided) - for (int r=0; r < _num_FSRs; r++) { + /* Compute total (scatter+fission+fixed) reduced source */ + _reduced_sources(r,g) = _fixed_sources(r,g); + _reduced_sources(r,g) += scatter_source + fission_source; + _reduced_sources(r,g) *= ONE_OVER_FOUR_PI / sigma_t[g]; + } + } - tid = omp_get_thread_num(); - material = _FSR_materials[r]; - nu_sigma_f = material->getNuSigmaF(); - chi = material->getChi(); - sigma_s = material->getSigmaS(); - sigma_t = material->getSigmaT(); + delete [] fission_sources; + delete [] scatter_sources; + } +} - /* Initialize the source residual to zero */ - _source_residuals[r] = 0.; - fsr_fission_source = 0.0; +/** + * @brief Computes the total fission source in each FSR. + * @details This method is a helper routine for the openmoc.krylov submodule. + */ +void CPUSolver::computeFSRFissionSources() { - /* Compute fission source for each group */ - if (material->isFissionable()) { - for (int e=0; e < _num_groups; e++) - _fission_sources(r,e) = _scalar_flux(r,e) * nu_sigma_f[e]; +#pragma omp parallel default(none) + { + int tid; + Material* material; + FP_PRECISION* sigma_t; + FP_PRECISION fiss_mat; + FP_PRECISION fission_source; + FP_PRECISION* fission_sources = new FP_PRECISION[_num_groups]; - fission_source = pairwise_sum(&_fission_sources(r,0), - _num_groups); - fission_source *= inverse_k_eff; - } + /* Compute the total source for each FSR */ +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { - else - fission_source = 0.0; + tid = omp_get_thread_num(); + material = _FSR_materials[r]; + sigma_t = material->getSigmaT(); + + /* Compute scatter + fission source for group g */ + for (int g=0; g < _num_groups; g++) { + for (int g_prime=0; g_prime < _num_groups; g_prime++) { + fiss_mat = material->getFissionMatrixByGroup(g_prime+1,g+1); + fission_sources[g_prime] = fiss_mat * _scalar_flux(r,g_prime); + } - /* Compute total scattering source for group G */ - for (int G=0; G < _num_groups; G++) { - scatter_source = 0; + fission_source = pairwise_sum(fission_sources, + _num_groups); - for (int g=0; g < _num_groups; g++) - _scatter_sources(tid,g) = material->getSigmaSByGroupInline(g,G) - * _scalar_flux(r,g); + /* Compute total (fission) reduced source */ + _reduced_sources(r,g) = fission_source; + _reduced_sources(r,g) *= ONE_OVER_FOUR_PI / sigma_t[g]; + } + } - scatter_source=pairwise_sum(&_scatter_sources(tid,0), - _num_groups); + delete [] fission_sources; + } +} - /* Set the fission source for FSR r in group G */ - fsr_fission_source += fission_source * chi[G]; +/** + * @brief Computes the total scattering source in each FSR. + * @details This method is a helper routine for the openmoc.krylov submodule. + */ +void CPUSolver::computeFSRScatterSources() { - /* Set the reduced source for FSR r in group G */ - _reduced_sources(r,G) = (fission_source * chi[G] + scatter_source) * - ONE_OVER_FOUR_PI / sigma_t[G]; - } +#pragma omp parallel default(none) + { + int tid; + Material* material; + FP_PRECISION* sigma_t; + FP_PRECISION sigma_s; + FP_PRECISION scatter_source; + FP_PRECISION* scatter_sources = new FP_PRECISION[_num_groups]; - /* Compute the norm of residual of the source in the FSR */ - if (fsr_fission_source > 0.0) - _source_residuals[r] = pow((fsr_fission_source - _old_fission_sources[r]) - / fsr_fission_source, 2); + /* Compute the total source for each FSR */ +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { - /* Update the old source */ - _old_fission_sources[r] = fsr_fission_source; - } + tid = omp_get_thread_num(); + material = _FSR_materials[r]; + sigma_t = material->getSigmaT(); + + /* Compute scatter + fission source for group g */ + for (int g=0; g < _num_groups; g++) { + for (int g_prime=0; g_prime < _num_groups; g_prime++) { + sigma_s = material->getSigmaSByGroup(g_prime+1,g+1); + scatter_sources[g_prime] = sigma_s * _scalar_flux(r,g_prime); + } - /* Sum up the residuals from each FSR */ - source_residual = pairwise_sum(_source_residuals, _num_FSRs); - source_residual = sqrt(source_residual \ - / (_num_fissionable_FSRs * _num_groups)); + scatter_source = pairwise_sum(scatter_sources, + _num_groups); - return source_residual; -} + /* Compute total (scatter) reduced source */ + _reduced_sources(r,g) = scatter_source; + _reduced_sources(r,g) *= ONE_OVER_FOUR_PI / sigma_t[g]; + } + } + delete [] scatter_sources; + } +} /** - * @brief Compute \f$ k_{eff} \f$ from the total, fission and scattering - * reaction rates and leakage. - * @details This method computes the current approximation to the - * multiplication factor on this iteration as follows: - * \f$ k_{eff} = \frac{\displaystyle\sum_{i \in I} - * \displaystyle\sum_{g \in G} \nu \Sigma^F_g \Phi V_{i}} - * {\displaystyle\sum_{i \in I} - * \displaystyle\sum_{g \in G} (\Sigma^T_g \Phi V_{i} - - * \Sigma^S_g \Phi V_{i} - L_{i,g})} \f$ + * @brief Computes the residual between source/flux iterations. + * @param res_type the type of residuals to compute + * (SCALAR_FLUX, FISSION_SOURCE, TOTAL_SOURCE) + * @return the average residual in each FSR */ -void CPUSolver::computeKeff() { +double CPUSolver::computeResidual(residualType res_type) { - int tid; - Material* material; - FP_PRECISION* sigma; - FP_PRECISION volume; + int norm; + double residual; + double* residuals = new double[_num_FSRs]; + memset(residuals, 0., _num_FSRs * sizeof(double)); - FP_PRECISION total = 0.0; - FP_PRECISION fission = 0.0; - FP_PRECISION scatter = 0.0; + if (res_type == SCALAR_FLUX) { - FP_PRECISION* FSR_rates = new FP_PRECISION[_num_FSRs]; - FP_PRECISION* group_rates = new FP_PRECISION[_num_threads * _num_groups]; + norm = _num_FSRs; - /* Loop over all FSRs and compute the volume-weighted total rates */ - #pragma omp parallel for private(tid, volume, \ - material, sigma) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { +#pragma omp parallel for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + for (int e=0; e < _num_groups; e++) + if (_old_scalar_flux(r,e) > 0.) { + residuals[r] += pow((_scalar_flux(r,e) - _old_scalar_flux(r,e)) / + _old_scalar_flux(r,e), 2); + } + } + } - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; - sigma = material->getSigmaT(); + else if (res_type == FISSION_SOURCE) { - for (int e=0; e < _num_groups; e++) - group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); + if (_num_fissionable_FSRs == 0) + log_printf(ERROR, "The Solver is unable to compute a " + "FISSION_SOURCE residual without fissionable FSRs"); - FSR_rates[r]=pairwise_sum(&group_rates[tid], _num_groups); - FSR_rates[r] *= volume; - } + norm = _num_fissionable_FSRs; - /* Reduce total rates across FSRs */ - total = pairwise_sum(FSR_rates, _num_FSRs); +#pragma omp parallel + { - /* Loop over all FSRs and compute the volume-weighted fission rates */ - #pragma omp parallel for private(tid, volume, \ - material, sigma) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { + double new_fission_source, old_fission_source; + FP_PRECISION* nu_sigma_f; + Material* material; - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; - sigma = material->getNuSigmaF(); +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + new_fission_source = 0.; + old_fission_source = 0.; + material = _FSR_materials[r]; - for (int e=0; e < _num_groups; e++) - group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); + if (material->isFissionable()) { + nu_sigma_f = material->getNuSigmaF(); + + for (int e=0; e < _num_groups; e++) { + new_fission_source += _scalar_flux(r,e) * nu_sigma_f[e]; + old_fission_source += _old_scalar_flux(r,e) * nu_sigma_f[e]; + } - FSR_rates[r]=pairwise_sum(&group_rates[tid], _num_groups); - FSR_rates[r] *= volume; + if (old_fission_source > 0.) + residuals[r] = pow((new_fission_source - old_fission_source) / + old_fission_source, 2); + } + } + } } - /* Reduce fission rates across FSRs */ - fission = pairwise_sum(FSR_rates, _num_FSRs); + else if (res_type == TOTAL_SOURCE) { - /* Loop over all FSRs and compute the volume-weighted scattering rates */ - #pragma omp parallel for private(tid, volume, \ - material) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { + norm = _num_FSRs; - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; +#pragma omp parallel + { - FSR_rates[r] = 0.; + double new_total_source, old_total_source; + FP_PRECISION inverse_k_eff = 1.0 / _k_eff; + FP_PRECISION* nu_sigma_f; + Material* material; + FP_PRECISION* sigma_s; - for (int G=0; G < _num_groups; G++) { - for (int g=0; g < _num_groups; g++) - group_rates[tid+g] = material->getSigmaSByGroupInline(g,G) - * _scalar_flux(r,g); +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + new_total_source = 0.; + old_total_source = 0.; + material = _FSR_materials[r]; + sigma_s = material->getSigmaS(); - FSR_rates[r]+=pairwise_sum(&group_rates[tid], _num_groups); - } + if (material->isFissionable()) { + nu_sigma_f = material->getNuSigmaF(); + + for (int e=0; e < _num_groups; e++) { + new_total_source += _scalar_flux(r,e) * nu_sigma_f[e]; + old_total_source += _old_scalar_flux(r,e) * nu_sigma_f[e]; + } + + new_total_source *= inverse_k_eff; + old_total_source *= inverse_k_eff; + } + + /* Compute total scattering source for group G */ + for (int G=0; G < _num_groups; G++) { + for (int g=0; g < _num_groups; g++) { + new_total_source += sigma_s[G*_num_groups+g] + * _scalar_flux(r,g); + old_total_source += sigma_s[G*_num_groups+g] + * _old_scalar_flux(r,g); + } + } - FSR_rates[r] *= volume; + if (old_total_source > 0.) + residuals[r] = pow((new_total_source - old_total_source) / + old_total_source, 2); + } + } } - /* Reduce scattering rates across FSRs */ - scatter = pairwise_sum(FSR_rates, _num_FSRs); + /* Sum up the residuals from each FSR and normalize */ + residual = pairwise_sum(residuals, _num_FSRs); + residual = sqrt(residual / norm); + + /* Deallocate memory for residuals array */ + delete [] residuals; + + return residual; +} + + +/** + * @brief Compute \f$ k_{eff} \f$ from successive fission sources. + */ +void CPUSolver::computeKeff() { + + FP_PRECISION fission; + FP_PRECISION* FSR_rates = new FP_PRECISION[_num_FSRs]; + FP_PRECISION* group_rates = new FP_PRECISION[_num_threads * _num_groups]; + + /* Compute the old nu-fission rates in each FSR */ +#pragma omp parallel + { - /* Reduce leakage array across Tracks, energy groups, polar angles */ - int size = 2 * _tot_num_tracks * _polar_times_groups; - _leakage = pairwise_sum(_boundary_leakage, size) * 0.5; + int tid = omp_get_thread_num() * _num_groups; + Material* material; + FP_PRECISION* sigma; + FP_PRECISION volume; - _k_eff = fission / (total - scatter + _leakage); +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { - log_printf(DEBUG, "tot = %f, fiss = %f, scatt = %f, leakage = %f," - "k_eff = %f", total, fission, scatter, _leakage, _k_eff); + volume = _FSR_volumes[r]; + material = _FSR_materials[r]; + sigma = material->getNuSigmaF(); + + for (int e=0; e < _num_groups; e++) + group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); + + FSR_rates[r]=pairwise_sum(&group_rates[tid], _num_groups); + FSR_rates[r] *= volume; + } + } + + /* Reduce new fission rates across FSRs */ + fission = pairwise_sum(FSR_rates, _num_FSRs); + + _k_eff *= fission; delete [] FSR_rates; delete [] group_rates; - - return; } @@ -804,71 +654,73 @@ void CPUSolver::computeKeff() { */ void CPUSolver::transportSweep() { - int tid; - int min_track, max_track; - Track* curr_track; - int azim_index; - int num_segments; - segment* curr_segment; - segment* segments; - FP_PRECISION* track_flux; - log_printf(DEBUG, "Transport sweep with %d OpenMP threads", _num_threads); + int min_track = 0; + int max_track = 0; + /* Initialize flux in each FSr to zero */ flattenFSRFluxes(0.0); if (_cmfd != NULL && _cmfd->isFluxUpdateOn()) - zeroSurfaceCurrents(); + _cmfd->zeroCurrents(); - /* Loop over azimuthal angle halfspaces */ - for (int i=0; i < 2; i++) { + /* Loop over the parallel track groups */ + for (int i=0; i < _num_parallel_track_groups; i++) { /* Compute the minimum and maximum Track IDs corresponding to - * this azimuthal angular halfspace */ - min_track = i * (_tot_num_tracks / 2); - max_track = (i + 1) * (_tot_num_tracks / 2); - - /* Loop over each thread within this azimuthal angle halfspace */ - #pragma omp parallel for private(curr_track, azim_index, num_segments, \ - curr_segment, segments, track_flux, tid) schedule(guided) - for (int track_id=min_track; track_id < max_track; track_id++) { - - tid = omp_get_thread_num(); + * this parallel track group */ + min_track = max_track; + max_track += _track_generator->getNumTracksByParallelGroup(i); + +#pragma omp parallel + { + + int tid = omp_get_thread_num(); + int azim_index, num_segments; + Track* curr_track; + segment* curr_segment; + segment* segments; + FP_PRECISION* track_flux; + + /* Use local array accumulator to prevent false sharing */ + FP_PRECISION thread_fsr_flux[_num_groups]; + + /* Loop over each thread within this azimuthal angle halfspace */ +#pragma omp for schedule(guided) + for (int track_id=min_track; track_id < max_track; track_id++) { + + /* Initialize local pointers to important data structures */ + curr_track = _tracks[track_id]; + azim_index = curr_track->getAzimAngleIndex(); + num_segments = curr_track->getNumSegments(); + segments = curr_track->getSegments(); + track_flux = &_boundary_flux(track_id,0,0,0); + + /* Loop over each Track segment in forward direction */ + for (int s=0; s < num_segments; s++) { + curr_segment = &segments[s]; + tallyScalarFlux(curr_segment, azim_index, track_flux, + thread_fsr_flux); + tallyCurrent(curr_segment, azim_index, track_flux, true); + } - /* Use local array accumulator to prevent false sharing*/ - FP_PRECISION* thread_fsr_flux; - thread_fsr_flux = new FP_PRECISION[_num_groups]; - - /* Initialize local pointers to important data structures */ - curr_track = _tracks[track_id]; - azim_index = curr_track->getAzimAngleIndex(); - num_segments = curr_track->getNumSegments(); - segments = curr_track->getSegments(); - track_flux = &_boundary_flux(track_id,0,0,0); - - /* Loop over each Track segment in forward direction */ - for (int s=0; s < num_segments; s++) { - curr_segment = &segments[s]; - scalarFluxTally(curr_segment, azim_index, track_flux, - thread_fsr_flux, true); - } + /* Transfer boundary angular flux to outgoing Track */ + transferBoundaryFlux(track_id, azim_index, true, track_flux); - /* Transfer boundary angular flux to outgoing Track */ - transferBoundaryFlux(track_id, azim_index, true, track_flux); + /* Loop over each Track segment in reverse direction */ + track_flux += _polar_times_groups; - /* Loop over each Track segment in reverse direction */ - track_flux += _polar_times_groups; + for (int s=num_segments-1; s > -1; s--) { + curr_segment = &segments[s]; + tallyScalarFlux(curr_segment, azim_index, track_flux, + thread_fsr_flux); + tallyCurrent(curr_segment, azim_index, track_flux, false); + } - for (int s=num_segments-1; s > -1; s--) { - curr_segment = &segments[s]; - scalarFluxTally(curr_segment, azim_index, track_flux, - thread_fsr_flux, false); + /* Transfer boundary angular flux to outgoing Track */ + transferBoundaryFlux(track_id, azim_index, false, track_flux); } - delete thread_fsr_flux; - - /* Transfer boundary angular flux to outgoing Track */ - transferBoundaryFlux(track_id, azim_index, false, track_flux); } } @@ -887,88 +739,28 @@ void CPUSolver::transportSweep() { * @param fsr_flux a pointer to the temporary FSR flux buffer * @param fwd */ -void CPUSolver::scalarFluxTally(segment* curr_segment, - int azim_index, +void CPUSolver::tallyScalarFlux(segment* curr_segment, int azim_index, FP_PRECISION* track_flux, - FP_PRECISION* fsr_flux, - bool fwd){ + FP_PRECISION* fsr_flux) { - int tid = omp_get_thread_num(); int fsr_id = curr_segment->_region_id; FP_PRECISION length = curr_segment->_length; FP_PRECISION* sigma_t = curr_segment->_material->getSigmaT(); - - /* The change in angular flux along this Track segment in the FSR */ - FP_PRECISION delta_psi; - FP_PRECISION exponential; + FP_PRECISION delta_psi, exponential; /* Set the FSR scalar flux buffer to zero */ memset(fsr_flux, 0.0, _num_groups * sizeof(FP_PRECISION)); - /* Loop over energy groups */ + /* Compute change in angular flux along segment in this FSR */ for (int e=0; e < _num_groups; e++) { - - /* Loop over polar angles */ - for (int p=0; p < _num_polar; p++){ - exponential = computeExponential(sigma_t[e], length, p); - delta_psi = (track_flux(p,e)-_reduced_sources(fsr_id,e))*exponential; + for (int p=0; p < _num_polar; p++) { + exponential = _exp_evaluator->computeExponential(sigma_t[e] * length, p); + delta_psi = (track_flux(p,e)-_reduced_sources(fsr_id,e)) * exponential; fsr_flux[e] += delta_psi * _polar_weights(azim_index,p); track_flux(p,e) -= delta_psi; } } - if (_cmfd != NULL && _cmfd->isFluxUpdateOn()){ - if (curr_segment->_cmfd_surface_fwd != -1 && fwd){ - - int pe = 0; - - /* Atomically increment the Cmfd Mesh surface current from the - * temporary array using mutual exclusion locks */ - omp_set_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_fwd]); - - /* Loop over energy groups */ - for (int e = 0; e < _num_groups; e++) { - - /* Loop over polar angles */ - for (int p = 0; p < _num_polar; p++){ - - /* Increment current (polar and azimuthal weighted flux, group) */ - _surface_currents(curr_segment->_cmfd_surface_fwd,e) += - track_flux(p,e)*_polar_weights(azim_index,p)/2.0; - pe++; - } - } - - /* Release Cmfd Mesh surface mutual exclusion lock */ - omp_unset_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_fwd]); - - } - else if (curr_segment->_cmfd_surface_bwd != -1 && !fwd){ - - int pe = 0; - - /* Atomically increment the Cmfd Mesh surface current from the - * temporary array using mutual exclusion locks */ - omp_set_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_bwd]); - - /* Loop over energy groups */ - for (int e = 0; e < _num_groups; e++) { - - /* Loop over polar angles */ - for (int p = 0; p < _num_polar; p++){ - - /* Increment current (polar and azimuthal weighted flux, group) */ - _surface_currents(curr_segment->_cmfd_surface_bwd,e) += - track_flux(p,e)*_polar_weights(azim_index,p)/2.0; - pe++; - } - } - - /* Release Cmfd Mesh surface mutual exclusion lock */ - omp_unset_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_bwd]); - } - } - /* Atomically increment the FSR scalar flux from the temporary array */ omp_set_lock(&_FSR_locks[fsr_id]); { @@ -976,55 +768,33 @@ void CPUSolver::scalarFluxTally(segment* curr_segment, _scalar_flux(fsr_id,e) += fsr_flux[e]; } omp_unset_lock(&_FSR_locks[fsr_id]); - - return; } /** - * @brief Computes the exponential term in the transport equation for a - * Track segment. - * @details This method computes \f$ 1 - exp(-l\Sigma^T_g/sin(\theta_p)) \f$ - * for a segment with total group cross-section and for some polar - * angle. This method uses either a linear interpolation table - * (default) or the exponential intrinsic exp(...) function if - * requested by the user through a call to the - * Solver::useExponentialIntrinsic() routine. - * @param sigma_t the total group cross-section at this energy - * @param length the length of the Track segment projected in the xy-plane - * @param p the polar angle index - * @return the evaluated exponential + * @brief Tallies the current contribution from this segment across the + * the appropriate CMFD mesh cell surface. + * @param curr_segment a pointer to the Track segment of interest + * @param azim_index the azimuthal index for this segmenbt + * @param track_flux a pointer to the Track's angular flux + * @param fwd boolean indicating direction of integration along segment */ -FP_PRECISION CPUSolver::computeExponential(FP_PRECISION sigma_t, - FP_PRECISION length, int p) { - - FP_PRECISION exponential; - FP_PRECISION tau = sigma_t * length; - - /* Evaluate the exponential using the lookup table - linear interpolation */ - if (_interpolate_exponential) { - int index; - index = round_to_int(tau * _inverse_exp_table_spacing); - index *= _two_times_num_polar; - exponential = (1. - (_exp_table[index+2 * p] * tau + - _exp_table[index + 2 * p +1])); - } +void CPUSolver::tallyCurrent(segment* curr_segment, int azim_index, + FP_PRECISION* track_flux, bool fwd) { - /* Evalute the exponential using the intrinsic exp(...) function */ - else { - FP_PRECISION sintheta = _quad->getSinTheta(p); - exponential = 1.0 - exp(- tau / sintheta); - } - - return exponential; + /* Tally surface currents if CMFD is in use */ + if (_cmfd != NULL && _cmfd->isFluxUpdateOn()) + _cmfd->tallyCurrent(curr_segment, track_flux, + &_polar_weights(azim_index,0), fwd); } /** * @brief Updates the boundary flux for a Track given boundary conditions. - * @details For reflective boundary conditions, the outgoing boundary flux - * for the Track is given to the reflecting Track. For vacuum - * boundary conditions, the outgoing flux tallied as leakage. + * @details For reflective and periodic boundary conditions, the outgoing + * boundary flux for the Track is given to the corresponding reflecting + * or periodic Track. For vacuum boundary conditions, the outgoing flux + * is tallied as leakage. * @param track_id the ID number for the Track of interest * @param azim_index a pointer to the azimuthal angle index for this segment * @param direction the Track direction (forward - true, reverse - false) @@ -1035,26 +805,20 @@ void CPUSolver::transferBoundaryFlux(int track_id, bool direction, FP_PRECISION* track_flux) { int start; - int bc; - FP_PRECISION* track_leakage; + bool transfer_flux; int track_out_id; - /* Extract boundary conditions for this Track and the pointer to the - * outgoing reflective Track, and index into the leakage array */ - /* For the "forward" direction */ if (direction) { - start = _tracks[track_id]->isReflOut() * _polar_times_groups; - bc = (int)_tracks[track_id]->getBCOut(); - track_leakage = &_boundary_leakage(track_id,0); + start = _tracks[track_id]->isNextOut() * _polar_times_groups; + transfer_flux = _tracks[track_id]->getTransferFluxOut(); track_out_id = _tracks[track_id]->getTrackOut()->getUid(); } /* For the "reverse" direction */ else { - start = _tracks[track_id]->isReflIn() * _polar_times_groups; - bc = (int)_tracks[track_id]->getBCIn(); - track_leakage = &_boundary_leakage(track_id,_polar_times_groups); + start = _tracks[track_id]->isNextIn() * _polar_times_groups; + transfer_flux = _tracks[track_id]->getTransferFluxIn(); track_out_id = _tracks[track_id]->getTrackIn()->getUid(); } @@ -1062,11 +826,8 @@ void CPUSolver::transferBoundaryFlux(int track_id, /* Loop over polar angles and energy groups */ for (int e=0; e < _num_groups; e++) { - for (int p=0; p < _num_polar; p++) { - track_out_flux(p,e) = track_flux(p,e) * bc; - track_leakage(p,e) = track_flux(p,e) * - _polar_weights(azim_index,p) * (!bc); - } + for (int p=0; p < _num_polar; p++) + track_out_flux(p,e) = track_flux(p,e) * transfer_flux; } } @@ -1082,59 +843,58 @@ void CPUSolver::addSourceToScalarFlux() { /* Add in source term and normalize flux to volume for each FSR */ /* Loop over FSRs, energy groups */ - #pragma omp parallel for private(volume, sigma_t) schedule(guided) +#pragma omp parallel for private(volume, sigma_t) schedule(guided) for (int r=0; r < _num_FSRs; r++) { - volume = _FSR_volumes[r]; sigma_t = _FSR_materials[r]->getSigmaT(); - for (int e=0; e < _num_groups; e++) { - _scalar_flux(r,e) *= 0.5; - _scalar_flux(r,e) = FOUR_PI * _reduced_sources(r,e) + - (_scalar_flux(r,e) / (sigma_t[e] * volume)); + for (int e=0; e < _num_groups; e++) { + _scalar_flux(r,e) *= 0.5; + _scalar_flux(r,e) /= (sigma_t[e] * volume); + _scalar_flux(r,e) += (FOUR_PI * _reduced_sources(r,e)); } } - - return; } /** - * @brief Computes the volume-weighted, energy integrated fission rate in + * @brief Computes the volume-integrated, energy-integrated nu-fission rate in * each FSR and stores them in an array indexed by FSR ID. * @details This is a helper method for SWIG to allow users to retrieve - * FSR fission rates as a NumPy array. An example of how this method - * can be called from Python is as follows: + * FSR nu-fission rates as a NumPy array. An example of how this + * method can be called from Python is as follows: * * @code * num_FSRs = geometry.getNumFSRs() * fission_rates = solver.computeFSRFissionRates(num_FSRs) * @endcode * - * @param fission_rates an array to store the fission rates (implicitly passed - * in as a NumPy array from Python) + * @param fission_rates an array to store the nu-fission rates (implicitly + * passed in as a NumPy array from Python) * @param num_FSRs the number of FSRs passed in from Python */ void CPUSolver::computeFSRFissionRates(double* fission_rates, int num_FSRs) { + if (_scalar_flux == NULL) + log_printf(ERROR, "Unable to compute FSR fission rates since the " + "source distribution has not been calculated"); + log_printf(INFO, "Computing FSR fission rates..."); FP_PRECISION* sigma_f; - - FP_PRECISION* scalar_flux = getFSRScalarFluxes(); + FP_PRECISION volume; /* Initialize fission rates to zero */ for (int r=0; r < _num_FSRs; r++) fission_rates[r] = 0.0; - /* Loop over all FSRs and compute the volume-weighted fission rate */ - #pragma omp parallel for private (sigma_f) schedule(guided) + /* Loop over all FSRs and compute the volume-averaged fission rate */ +#pragma omp parallel for private (sigma_f, volume) schedule(guided) for (int r=0; r < _num_FSRs; r++) { sigma_f = _FSR_materials[r]->getSigmaF(); + volume = _FSR_volumes[r]; for (int e=0; e < _num_groups; e++) - fission_rates[r] += sigma_f[e] * _scalar_flux(r,e); + fission_rates[r] += sigma_f[e] * _scalar_flux(r,e) * volume; } - - return; } diff --git a/src/CPUSolver.h b/src/CPUSolver.h index 45e142781..55779b270 100644 --- a/src/CPUSolver.h +++ b/src/CPUSolver.h @@ -11,24 +11,23 @@ #ifdef __cplusplus #define _USE_MATH_DEFINES +#include "Solver.h" #include #include #include -#include "Solver.h" #endif + +#undef track_flux + /** Indexing macro for the angular fluxes for each polar angle and energy - * group for either the forward or reverse direction for a given Track */ + * group for either the forward or reverse direction for a given Track */ #define track_flux(p,e) (track_flux[(p)*_num_groups + (e)]) /** Indexing macro for the angular fluxes for each polar angle and energy * group for the outgoing reflective track from a given Track */ #define track_out_flux(p,e) (track_out_flux[(p)*_num_groups + (e)]) -/** Indexing macro for the leakage for each polar angle and energy group - * for either the forward or reverse direction for a given Track */ -#define track_leakage(p,e) (track_leakage[(p)*_num_groups + (e)]) - /** * @class CPUSolver CPUSolver.h "src/CPUSolver.h" @@ -45,34 +44,25 @@ class CPUSolver : public Solver { /** OpenMP mutual exclusion locks for atomic FSR scalar flux updates */ omp_lock_t* _FSR_locks; - /** OpenMP mutual exclusion locks for atomic surface current updates */ - omp_lock_t* _cmfd_surface_locks; - - void initializeFluxArrays(); - void initializeSourceArrays(); - void initializePolarQuadrature(); - void buildExpInterpTable(); - void initializeFSRs(); - void initializeCmfd(); - - void zeroTrackFluxes(); - void flattenFSRFluxes(FP_PRECISION value); - void zeroSurfaceCurrents(); - void flattenFSRSources(FP_PRECISION value); - void normalizeFluxes(); - FP_PRECISION computeFSRSources(); - /** * @brief Computes the contribution to the FSR flux from a Track segment. * @param curr_segment a pointer to the Track segment of interest * @param azim_index a pointer to the azimuthal angle index for this segment * @param track_flux a pointer to the Track's angular flux * @param fsr_flux a pointer to the temporary FSR scalar flux buffer - * @param fwd */ - virtual void scalarFluxTally(segment* curr_segment, int azim_index, - FP_PRECISION* track_flux, FP_PRECISION* fsr_flux, - bool fwd); + virtual void tallyScalarFlux(segment* curr_segment, int azim_index, + FP_PRECISION* track_flux, FP_PRECISION* fsr_flux); + + /** + * @brief Computes the contribution to surface current from a segment. + * @param curr_segment a pointer to the Track segment of interest + * @param azim_index a pointer to the azimuthal angle index for this segment + * @param track_flux a pointer to the Track's angular flux + * @param fwd the direction of integration along the segment + */ + virtual void tallyCurrent(segment* curr_segment, int azim_index, + FP_PRECISION* track_flux, bool fwd); /** * @brief Updates the boundary flux for a Track given boundary conditions. @@ -82,41 +72,36 @@ class CPUSolver : public Solver { * @param track_flux a pointer to the Track's outgoing angular flux */ virtual void transferBoundaryFlux(int track_id, int azim_index, - bool direction, - FP_PRECISION* track_flux); - void addSourceToScalarFlux(); - void computeKeff(); - void transportSweep(); - - /** - * @brief Computes the exponential term in the transport equation for a - * track segment. - * @details This method uses either a linear interpolation table (default) - * or the exponential intrinsic exp(...) function if requested by - * the user through a call to the Solver::useExponentialIntrinsic() - * routine. - * @param sigma_t the total group cross-section at this energy - * @param length the length of the Track segment projected in the xy-plane - * @param p the polar angle index - * @return the evaluated exponential - */ - virtual FP_PRECISION computeExponential(FP_PRECISION sigma_t, - FP_PRECISION length, int p); + bool direction, FP_PRECISION* track_flux); public: - CPUSolver(Geometry* geometry=NULL, TrackGenerator* track_generator=NULL); + CPUSolver(TrackGenerator* track_generator=NULL); virtual ~CPUSolver(); int getNumThreads(); - FP_PRECISION getFSRScalarFlux(int fsr_id, int energy_group); - FP_PRECISION* getFSRScalarFluxes(); - FP_PRECISION getFSRSource(int fsr_id, int energy_group); - FP_PRECISION* getSurfaceCurrents(); + virtual void getFluxes(FP_PRECISION* out_fluxes, int num_fluxes); void setNumThreads(int num_threads); + virtual void setFluxes(FP_PRECISION* in_fluxes, int num_fluxes); - void computeFSRFissionRates(double* fission_rates, int num_FSRs); + void initializeFluxArrays(); + void initializeSourceArrays(); + void initializeFixedSources(); + void initializeFSRs(); + void zeroTrackFluxes(); + void flattenFSRFluxes(FP_PRECISION value); + void storeFSRFluxes(); + void normalizeFluxes(); + void computeFSRSources(); + void computeFSRFissionSources(); + void computeFSRScatterSources(); + void transportSweep(); + void addSourceToScalarFlux(); + void computeKeff(); + double computeResidual(residualType res_type); + + void computeFSRFissionRates(double* fission_rates, int num_FSRs); }; diff --git a/src/Cell.cpp b/src/Cell.cpp index 997ad4a78..58ff08847 100644 --- a/src/Cell.cpp +++ b/src/Cell.cpp @@ -3,7 +3,7 @@ int Cell::_n = 0; -static int auto_id = 10000; +static int auto_id = DEFAULT_INIT_ID; /** @@ -26,15 +26,22 @@ int cell_id() { * @brief Resets the auto-generated unique Cell ID counter to 10000. */ void reset_cell_id() { - auto_id = 10000; + auto_id = DEFAULT_INIT_ID; } /** - * @brief Default constructor used in rings/sectors subdivision of Cells. + * @brief Maximize the auto-generated unique Cell ID counter. + * @details This method updates the auto-generated unique Cell ID + * counter if the input parameter is greater than the present + * value. This is useful for the OpenCG compatibility module + * to ensure that the auto-generated Cell IDs do not + * collide with those created in OpenCG. + * @param cell_id the id assigned to the auto-generated counter */ -Cell::Cell() { - _name = NULL; +void maximize_cell_id(int cell_id) { + if (cell_id > auto_id) + auto_id = cell_id; } @@ -59,13 +66,21 @@ Cell::Cell(int id, const char* name) { _name = NULL; setName(name); - /* Set a default bounding box around the Cell */ - _min_x = -std::numeric_limits::infinity(); - _max_x = std::numeric_limits::infinity(); - _min_y = -std::numeric_limits::infinity(); - _max_y = std::numeric_limits::infinity(); - _min_z = -std::numeric_limits::infinity(); - _max_z = std::numeric_limits::infinity(); + _cell_type = UNFILLED; + _fill = NULL; + _volume = 0.; + _num_instances = 0; + + _rotated = false; + memset(&_rotation, 0., 3); + memset(&_rotation_matrix, 0., 9); + + _translated = false; + memset(&_translation, 0., 3); + + _num_rings = 0; + _num_sectors = 0; + _parent = NULL; } @@ -73,6 +88,10 @@ Cell::Cell(int id, const char* name) { * @brief Destructor clears vector of Surface pointers bounding the Cell. */ Cell::~Cell() { + + std::map::iterator iter; + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) + delete iter->second; _surfaces.clear(); if (_name != NULL) @@ -116,12 +135,244 @@ cellType Cell::getType() const { } +/** + * @brief Return a pointer to the Material filling this Cell. + * @return the Material fill pointer + */ +Material* Cell::getFillMaterial() { + if (_cell_type == FILL) + log_printf(ERROR, "Unable to get Material fill from Cell ID=%d", _id); + + return (Material*)_fill; +} + + +/** + * @brief Return a pointer to the Material filling this Cell. + * @return the Material fill pointer + */ +Universe* Cell::getFillUniverse() { + if (_cell_type == MATERIAL) + log_printf(ERROR, "Unable to get Universe fill from Cell ID=%d", _id); + + return (Universe*)_fill; +} + + +/** + * @brief Return the aggregate volume/area of all instances of this Cell. + * @details The volume/area of the Cell is computed from track segments which + * overlap this Cell during track generation. + * @return the volume/area of the Cell + */ +double Cell::getVolume() { + return _volume; +} + + +/** + * @brief Return a boolean indicating whether the Cell has been rotated. + * @return whether the Cell has been rotated + */ +bool Cell::isRotated() { + return _rotated; +} + + +/** + * @brief Return the number of instances of this Cell in the Geometry. + * @details The number of instances of this Cell in the Geometry is + * determined during track generation. + * @return the number of cell instances + */ +int Cell::getNumInstances() { + return _num_instances; +} + + +/** + * @brief Return a boolean indicating whether the Cell has been translated. + * @return whether the Cell has been translated + */ +bool Cell::isTranslated() { + return _translated; +} + + +/** + * @brief Get the rotation angle about the x-axis in degrees. + * @param units the angular units in "radians" or "degrees" (default) + * @return the rotation angle about the x-axis + */ +double Cell::getPhi(std::string units) { + std::string degrees("degrees"); + std::string radians("radians"); + + /* Return phi in degrees or radians */ + if (degrees.compare(units) == 0) + return _rotation[0] * M_PI / 180.; + else if (radians.compare(units) == 0) + return _rotation[0]; + else + log_printf(ERROR, "Unable to return phi in units %s", units.c_str()); +} + + +/** + * @brief Get the rotation angle about the y-axis in degrees. + * @param units the angular units in "radians" or "degrees" (default) + * @return the rotation angle about the y-axis + */ +double Cell::getTheta(std::string units) { + std::string degrees("degrees"); + std::string radians("radians"); + + /* Return theta in degrees or radians */ + if (degrees.compare(units) == 0) + return _rotation[1] * M_PI / 180.; + else if (radians.compare(units) == 0) + return _rotation[1]; + else + log_printf(ERROR, "Unable to return theta in units %s", units.c_str()); +} + + +/** + * @brief Get the rotation angle about the z-axis in degrees. + * @param units the angular units in "radians" or "degrees" (default) + * @return the rotation angle about the z-axis + */ +double Cell::getPsi(std::string units) { + std::string degrees("degrees"); + std::string radians("radians"); + + /* Return psi in degrees or radians */ + if (degrees.compare(units) == 0) + return _rotation[2] * M_PI / 180.; + else if (radians.compare(units) == 0) + return _rotation[2]; + else + log_printf(ERROR, "Unable to return psi in units %s", units.c_str()); +} + + +/** + * @brief Return pointer to array for the rotation matrix. + * @return a pointer to an array of rotation angles + */ +double* Cell::getRotationMatrix() { + return _rotation_matrix; +} + + +/** + * @brief Fills an array with the rotation angles for x, y and z. + * @details This class method is intended to be called by the OpenMOC + * Python OpenCG compatiblity module. Although this method appears to + * require two arguments, in reality it only requires one due to SWIG + * and would be called from within Python as follows: + * + * @code + * rotation = cell.getRotation(3) + * @endcode + * + * @param rotation an array of rotation angles of length 3 for x, y and z + * @param num_axes the number of axes (this must always be 3) + * @param units the angular units in "radians" or "degrees" (default) + */ +void Cell::retrieveRotation(double* rotations, int num_axes, + std::string units) { + if (num_axes != 3) + log_printf(ERROR, "Unable to get rotation with %d axes for Cell %d. " + "The rotation array should be length 3.", num_axes, _id); + + std::string degrees("degrees"); + std::string radians("radians"); + + /* Return psi in degrees or radians */ + for (int i=0; i < 3; i++) { + if (degrees.compare(units) == 0) + rotations[i] = _rotation[i] * 180. / M_PI; + else if (radians.compare(units) == 0) + rotations[i] = _rotation[i]; + else + log_printf(ERROR, "Unable to return rotation in units %s", units.c_str()); + } +} + + +/** + * @brief Return pointer to array for the translations along x, y and z. + * @return a pointer to an array of translations + */ +double* Cell::getTranslation() { + return _translation; +} + + +/** + * @brief Fills an array with the translations along x, y and z. + * @details This class method is intended to be called by the OpenMOC + * Python OpenCG compatiblity module. Although this method appears to + * require two arguments, in reality it only requires one due to SWIG + * and would be called from within Python as follows: + * + * @code + * translation = cell.retrieveTranslation(3) + * @endcode + * + * @param translation an array of translations of length 3 for x, y and z + * @param num_axes the number of axes (this must always be 3) + */ +void Cell::retrieveTranslation(double* translations, int num_axes) { + if (num_axes != 3) + log_printf(ERROR, "Unable to get translation with %d axes for Cell %d. " + "The translation array should be length 3.", num_axes, _id); + + for (int i=0; i < 3; i++) + translations[i] = _translation[i]; +} + + +/** + * @brief Return the number of rings in the Cell. + * @return the number of rings + */ +int Cell::getNumRings() { + return _num_rings; +} + + +/** + * @brief Return the number of sectors in the Cell. + * @return the number of sectors + */ +int Cell::getNumSectors() { + return _num_sectors; +} + + /** * @brief Return the minimum reachable x-coordinate in the Cell. * @return the minimum x-coordinate */ double Cell::getMinX() { - return _min_x; + + /* Set a default min-x */ + double min_x = -std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + min_x = std::max(min_x, surface->getMinX(halfspace)); + } + + return min_x; } @@ -130,7 +381,22 @@ double Cell::getMinX() { * @return the maximum x-coordinate */ double Cell::getMaxX() { - return _max_x; + + /* Set a default max-x */ + double max_x = std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + max_x = std::min(max_x, surface->getMaxX(halfspace)); + } + + return max_x; } @@ -139,7 +405,22 @@ double Cell::getMaxX() { * @return the minimum y-coordinate */ double Cell::getMinY() { - return _min_y; + + /* Set a default min-y */ + double min_y = -std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + min_y = std::max(min_y, surface->getMinY(halfspace)); + } + + return min_y; } @@ -148,7 +429,22 @@ double Cell::getMinY() { * @return the maximum y-coordinate */ double Cell::getMaxY() { - return _max_y; + + /* Set a default max-y */ + double max_y = std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + max_y = std::min(max_y, surface->getMaxY(halfspace)); + } + + return max_y; } @@ -157,7 +453,22 @@ double Cell::getMaxY() { * @return the minimum z-coordinate */ double Cell::getMinZ() { - return _min_z; + + /* Set a default min-z */ + double min_z = -std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + min_z = std::max(min_z, surface->getMinZ(halfspace)); + } + + return min_z; } @@ -166,7 +477,22 @@ double Cell::getMinZ() { * @return the maximum z-coordinate */ double Cell::getMaxZ() { - return _max_z; + + /* Set a default max-z */ + double max_z = std::numeric_limits::infinity(); + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + max_z = std::min(max_z, surface->getMaxZ(halfspace)); + } + + return max_z; } @@ -176,7 +502,27 @@ double Cell::getMaxZ() { * @return the boundary condition at the minimum x-coordinate */ boundaryType Cell::getMinXBoundaryType() { - return _min_x_bc; + + /* Set a default min-x and boundary type*/ + double min_x = -std::numeric_limits::infinity(); + boundaryType bc = BOUNDARY_NONE; + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + + if (min_x < surface->getMinX(halfspace)) { + min_x = surface->getMinX(halfspace); + bc = surface->getBoundaryType(); + } + } + + return bc; } @@ -185,86 +531,429 @@ boundaryType Cell::getMinXBoundaryType() { * the maximum reachable x-coordinate in the Cell. * @return the boundary condition at the maximum x-coordinate */ -boundaryType Cell::getMaxXBoundaryType() { - return _max_x_bc; +boundaryType Cell::getMaxXBoundaryType() { + + /* Set a default max-x and boundary type*/ + double max_x = std::numeric_limits::infinity(); + boundaryType bc = BOUNDARY_NONE; + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + + if (max_x > surface->getMaxX(halfspace)) { + max_x = surface->getMaxX(halfspace); + bc = surface->getBoundaryType(); + } + } + + return bc; +} + + +/** + * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at + * the minimum reachable y-coordinate in the Cell. + * @return the boundary condition at the minimum y-coordinate + */ +boundaryType Cell::getMinYBoundaryType() { + + /* Set a default min-y and boundary type*/ + double min_y = -std::numeric_limits::infinity(); + boundaryType bc = BOUNDARY_NONE; + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + + if (min_y < surface->getMinY(halfspace)) { + min_y = surface->getMinY(halfspace); + bc = surface->getBoundaryType(); + } + } + + return bc; +} + + +/** + * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at + * the maximum reachable y-coordinate in the Cell. + * @return the boundary condition at the maximum y-coordinate + */ +boundaryType Cell::getMaxYBoundaryType() { + + /* Set a default max-y and boundary type*/ + double max_y = std::numeric_limits::infinity(); + boundaryType bc = BOUNDARY_NONE; + + /* Loop over all Surfaces inside the Cell */ + std::map::iterator iter; + Surface* surface; + int halfspace; + + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + + if (max_y > surface->getMaxY(halfspace)) { + max_y = surface->getMaxY(halfspace); + bc = surface->getBoundaryType(); + } + } + + return bc; +} + + +/** + * @brief Return the number of Surfaces in the Cell. + * @return the number of Surfaces + */ +int Cell::getNumSurfaces() const { + return _surfaces.size(); +} + + +/** + * @brief Return the std::map of Surface pointers and halfspaces (+/-1) for all + * surfaces bounding the Cell. + * @return std::map of Surface pointers and halfspaces + */ +std::map Cell::getSurfaces() const { + return _surfaces; +} + + +/** + * @brief Return the std::vector of neighbor Cells to this Cell. + * @return std::vector of neighbor Cell pointers + */ +std::vector Cell::getNeighbors() const { + return _neighbors; +} + + +/** + * @brief Return true if the Cell has a parent and false otherwise. + * @return whether the Cell has a parent Cell + */ +bool Cell::hasParent() { + if (_parent == NULL) + return false; + else + return true; +} + + +/** + * @brief Return this Cell's parent Cell. + * @details If no parent Cell has been assigned from Cell cloning, then + * NULL is returned. + * @return a pointer to the parent Cell + */ +Cell* Cell::getParent() { + return _parent; +} + + +/** + * @brief Get the oldest ancestor Cell for this Cell. + * @details This method traverses the linked list of parent Cells to find + * the one at the root node. The oldest ancestor Cell is likely the + * one created by the user at runtime, while intermediate ancestors + * were created during radial and angular spatial discretization. + * @return this Cell's oldest ancestor Cell + */ +Cell* Cell::getOldestAncestor() { + + /* If this Cell has no parent, return NULL */ + if (_parent == NULL) + return _parent; + + /* Otherwise, navigate to the first parent Cell */ + else { + /* Traverse linked list to the root node */ + Cell* curr = _parent; + while (curr->hasParent()) + curr = curr->getParent(); + + return curr; + } +} + + + +/** + * @brief Returns the std::map of Cell IDs and Cell pointers within any + * nested Universes filling this Cell. + * @return std::map of Cell IDs and pointers + */ +std::map Cell::getAllCells() { + + std::map cells; + + if (_cell_type == FILL && _fill != NULL) { + std::map nested_cells; + Universe* univ_fill = static_cast(_fill); + + if (univ_fill->getType() == SIMPLE) + nested_cells = univ_fill->getAllCells(); + else + nested_cells = static_cast(univ_fill)->getAllCells(); + + cells.insert(nested_cells.begin(), nested_cells.end()); + } + + return cells; +} + + +/** + * @brief Returns the std::map of all nested Universe IDs and Universe pointers + filling this Cell. + * @return std::map of Universe IDs and pointers + */ +std::map Cell::getAllUniverses() { + + std::map universes; + + if (_cell_type == FILL && _fill != NULL) { + Universe* univ_fill = static_cast(_fill); + universes[univ_fill->getId()] = univ_fill; + + std::map nested_universes; + if (univ_fill->getType() == SIMPLE) + nested_universes = static_cast(_fill)->getAllUniverses(); + else + nested_universes = static_cast(_fill)->getAllUniverses(); + universes.insert(nested_universes.begin(), nested_universes.end()); + } + + return universes; +} + + +/** + * @brief Sets the name of the Cell + * @param name the Cell name string + */ +void Cell::setName(const char* name) { + int length = strlen(name); + + if (_name != NULL) + delete [] _name; + + /* Initialize a character array for the Cell's name */ + _name = new char[length+1]; + + /* Copy the input character array Cell name to the class attribute name */ + for (int i=0; i <= length; i++) + _name[i] = name[i]; +} + + +/** + * @brief Sets the Material filling this Cell. + * @param fill the Material filling this Cell + */ +void Cell::setFill(Material* fill) { + _cell_type = MATERIAL; + _fill = fill; +} + + +/** + * @brief Sets the Universe filling this Cell. + * @param fill the Universe filling this Cell + */ +void Cell::setFill(Universe* fill) { + _cell_type = FILL; + _fill = fill; +} + + +/** + * @brief Set the volume/area of the Cell. + * @param volume the volume/area of the Cell + */ +void Cell::setVolume(double volume) { + _volume = volume; } /** - * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at - * the minimum reachable y-coordinate in the Cell. - * @return the boundary condition at the minimum y-coordinate + * @brief Increment the volume/area of the Cell by some amount. + * @details This routine is called by the TrackGenerator during track + * generation and segmentation. + * @param volume the amount to increment the current volume by */ -boundaryType Cell::getMinYBoundaryType() { - return _min_y_bc; +void Cell::incrementVolume(double volume) { + _volume += volume; } /** - * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at - * the maximum reachable y-coordinate in the Cell. - * @return the boundary condition at the maximum y-coordinate + * @brief Set the number of instances of this Cell. + * @param num_instances the number of instances of this Cell in the Geometry */ -boundaryType Cell::getMaxYBoundaryType() { - return _max_y_bc; +void Cell::setNumInstances(int num_instances) { + _num_instances = num_instances; } - /** - * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at - * the minimum reachable z-coordinate in the Cell. - * @return the boundary condition at the minimum z-coordinate + * @brief Set the Cell's rotation angles about the x, y and z axes. + * @details This method is a helper function to allow OpenMOC users to assign + * the Cell's rotation angles in Python. A user must initialize a + * length 3 NumPy array as input to this function. This function then + * stores the data values in the NumPy array in the Cell's rotation + * array. An example of how this function might be called in Python + * is as follows: + * + * @code + * rotation = numpy.array([0., 0., 90.]) + * cell = openmoc.Cell() + * cell.setRotation(rotation) + * @endcode + * + * @param rotation the array of rotation angles + * @param num_axes the number of axes (this must always be 3) + * @param units the angular units in "radians" or "degrees" (default) */ -boundaryType Cell::getMinZBoundaryType() { - return _min_z_bc; +void Cell::setRotation(double* rotation, int num_axes, std::string units) { + + if (num_axes != 3) + log_printf(ERROR, "Unable to set rotation with %d axes for Cell %d. " + "The rotation array should be length 3.", num_axes, _id); + + std::string degrees("degrees"); + std::string radians("radians"); + + /* Store rotation angles in radians */ + for (int i=0; i < 3; i++) { + if (degrees.compare(units) == 0) + _rotation[i] = rotation[i] * M_PI / 180.; + else if (radians.compare(units) == 0) + _rotation[i] = rotation[i]; + else + log_printf(ERROR, "Unable to set rotation with units %s", units.c_str()); + } + + /* Use pitch-roll-yaw convention according to eqns 51-59 on Wolfram: + * http://mathworld.wolfram.com/EulerAngles.html */ + double theta = _rotation[0]; + double psi = _rotation[1]; + double phi = _rotation[2]; + + /* Calculate rotation matrix based on angles given */ + /* Indexed by (y,x) since the universe array is indexed by (z,y,z) */ + _rotation_matrix[0] = cos(theta) * cos(phi); + _rotation_matrix[1] = cos(theta) * sin(phi); + _rotation_matrix[2] = -sin(theta); + _rotation_matrix[3] = sin(psi) * sin(theta) * cos(psi) - + cos(psi) * sin(phi); + _rotation_matrix[4] = sin(psi) * sin(theta) * sin(phi) + + cos(psi) * cos(phi); + _rotation_matrix[5] = cos(theta) * sin(psi); + _rotation_matrix[6] = cos(psi) * sin(theta) * cos(phi) + + sin(psi) * sin(phi); + _rotation_matrix[7] = cos(psi) * sin(theta) * sin(phi) - + sin(psi) * cos(phi); + _rotation_matrix[8] = cos(theta) * cos(psi); + + _rotated = true; } /** - * @brief Return the boundary condition (REFLECTIVE, VACUUM, or INTERFACE) at - * the maximum reachable z-coordinate in the Cell. - * @return the boundary condition at the maximum z-coordinate + * @brief Increment the number of instances of this Cell. + * @details This routine is called by the TrackGenerator during track + * generation and segmentation. */ -boundaryType Cell::getMaxZBoundaryType() { - return _max_z_bc; +void Cell::incrementNumInstances() { + _num_instances++; } - /** - * @brief Return the number of Surfaces in the Cell. - * @return the number of Surfaces + * @brief Set the Cell's translation along the x, y and z axes. + * @details This method is a helper function to allow OpenMOC users to assign + * the Cell's translations in Python. A user must initialize a + * length 3 NumPy array as input to this function. This function then + * stores the data values in the NumPy array in the Cell's translation + * array. An example of how this function might be called in Python + * is as follows: + * + * @code + * translation = numpy.array([0.25, 0.25, 0.]) + * cell = openmoc.Cell() + * cell.setTranslation(translation) + * @endcode + * + * @param translation the array of translations + * @param num_axes the number of axes (this must always be 3) */ -int Cell::getNumSurfaces() const { - return _surfaces.size(); +void Cell::setTranslation(double* translation, int num_axes) { + + if (num_axes != 3) + log_printf(ERROR, "Unable to set translation for %d axes for Cell %d. " + "The translation array should be length 3.", num_axes, _id); + + for (int i=0; i < 3; i++) + _translation[i] = translation[i]; + + _translated = true; } /** - * @brief Return the std::map of Surface pointers and halfspaces (+/-1) for all - * surfaces bounding the Cell. - * @return std::map of Surface pointers and halfspaces + * @brief Set the Cell's number of rings. + * @param num_rings the number of rings in this Cell */ -std::map Cell::getSurfaces() const { - return _surfaces; +void Cell::setNumRings(int num_rings) { + if (num_rings < 0) + log_printf(ERROR, "Unable to give %d rings to Cell %d since this is " + "a negative number", num_rings, _id); + + _num_rings = num_rings; } /** - * @brief Sets the name of the Cell - * @param name the Cell name string + * @brief Set the Cell's number of sectors. + * @param num_sectors the number of sectors in this Cell */ -void Cell::setName(const char* name) { - int length = strlen(name); +void Cell::setNumSectors(int num_sectors) { + if (num_sectors < 0) + log_printf(ERROR, "Unable to give %d sectors to Cell %d since this is " + "a negative number", num_sectors, _id); - if (_name != NULL) - delete [] _name; + /* By default, a ring is considered to have a single sector in [0, 2*pi] */ + if (num_sectors == 1) + _num_sectors = 0; - /* Initialize a character array for the Cell's name */ - _name = new char[length+1]; + else + _num_sectors = num_sectors; +} - /* Copy the input character array Cell name to the class attribute name */ - for (int i=0; i <= length; i++) - _name[i] = name[i]; + +/** + * @brief Assign a parent Cell to this Cell. + * @details This is used by Cell cloning when applied for radial and + * angular discretization. + * @param parent a pointer to the parent Cell + */ +void Cell::setParent(Cell* parent) { + _parent = parent; } @@ -283,9 +972,7 @@ void Cell::addSurface(int halfspace, Surface* surface) { new_surf_half->_surface = surface; new_surf_half->_halfspace = halfspace; - _surfaces[surface->getId()] = *new_surf_half; - - findBoundingBox(); + _surfaces[surface->getId()] = new_surf_half; } @@ -295,88 +982,22 @@ void Cell::addSurface(int halfspace, Surface* surface) { */ void Cell::removeSurface(Surface* surface) { - if (_surfaces.find(surface->getId()) != _surfaces.end()) + if (_surfaces.find(surface->getId()) != _surfaces.end()) { + delete _surfaces[surface->getId()]; _surfaces.erase(surface->getId()); - - findBoundingBox(); + } } - /** - * @brief Finds and stores a bounding box for the entire geometry. + * @brief Add a neighboring Cell to this Cell's collection of neighbors. + * @param cell a pointer to the neighboring Cell */ -void Cell::findBoundingBox() { - - /* Set a default bounding box around the Cell */ - _min_x = -std::numeric_limits::infinity(); - _max_x = std::numeric_limits::infinity(); - _min_y = -std::numeric_limits::infinity(); - _max_y = std::numeric_limits::infinity(); - _min_z = -std::numeric_limits::infinity(); - _max_z = std::numeric_limits::infinity(); - - /* Loop over all Surfaces inside the Cell */ - std::map::iterator iter; - Surface* surface; - int halfspace; - double min_x, max_x, min_y, max_y, min_z, max_z; - - for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { - - surface = iter->second._surface; - halfspace = iter->second._halfspace; - - max_x = surface->getMaxX(halfspace); - max_y = surface->getMaxY(halfspace); - max_z = surface->getMaxZ(halfspace); - - min_x = surface->getMinX(halfspace); - min_y = surface->getMinY(halfspace); - min_z = surface->getMinZ(halfspace); - - if (max_x != std::numeric_limits::infinity() && max_x < _max_x) { - _max_x = max_x; - _max_x_bc = surface->getBoundaryType(); - } - if (max_y != std::numeric_limits::infinity() && max_y < _max_y) { - _max_y = max_y; - _max_y_bc = surface->getBoundaryType(); - } - if (max_z != std::numeric_limits::infinity() && max_z < _max_z) { - _max_z = max_z; - _max_z_bc = surface->getBoundaryType(); - } +void Cell::addNeighborCell(Cell* cell) { - if (min_x != -std::numeric_limits::infinity() && min_x > _min_x) { - _min_x = min_x; - _min_x_bc = surface->getBoundaryType(); - } - if (min_y != -std::numeric_limits::infinity() && min_y > _min_y) { - _min_y = min_y; - _min_y_bc = surface->getBoundaryType(); - } - if (min_z != -std::numeric_limits::infinity() && min_z > _min_z) { - _min_z = min_z; - _min_z_bc = surface->getBoundaryType(); - } - } - - /* If we could not find a bounds for any dimension, readjust - * it to +/- infinity */ - if (_max_x == -std::numeric_limits::infinity()) - _max_x = std::numeric_limits::infinity(); - if (_max_y == -std::numeric_limits::infinity()) - _max_y = std::numeric_limits::infinity(); - if (_max_z == -std::numeric_limits::infinity()) - _max_z = std::numeric_limits::infinity(); - - if (_min_x == std::numeric_limits::infinity()) - _min_x = -std::numeric_limits::infinity(); - if (_min_y == std::numeric_limits::infinity()) - _min_y = -std::numeric_limits::infinity(); - if (_min_z == std::numeric_limits::infinity()) - _min_z = -std::numeric_limits::infinity(); + /* Add the neighbor Cell if it is not already in the collection */ + if (std::find(_neighbors.begin(), _neighbors.end(), cell) == _neighbors.end()) + _neighbors.push_back(cell); } @@ -387,15 +1008,16 @@ void Cell::findBoundingBox() { * the Cell if it is on the same side of every Surface in the Cell. * @param point a pointer to a Point */ -bool Cell::cellContainsPoint(Point* point) { +bool Cell::containsPoint(Point* point) { /* Loop over all Surfaces inside the Cell */ - std::map::iterator iter; + std::map::iterator iter; for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { /* Return false if the Point is not in the correct Surface halfspace */ - if (iter->second._surface->evaluate(point) * iter->second._halfspace < -ON_SURFACE_THRESH) + if (iter->second->_surface->evaluate(point) * iter->second->_halfspace + < 0.0) return false; } @@ -411,41 +1033,34 @@ bool Cell::cellContainsPoint(Point* point) { * the Cell if it is on the same side of every Surface in the Cell. * @param coords a pointer to a localcoord */ -bool Cell::cellContainsCoords(LocalCoords* coords) { - return cellContainsPoint(coords->getPoint()); +bool Cell::containsCoords(LocalCoords* coords) { + return containsPoint(coords->getPoint()); } /** - * @brief Computes the minimum distance to a Surface from a Point with a given - * trajectory at a certain angle. + * @brief Computes the minimum distance to a Surface from a point with a given + * trajectory at a certain angle stored in a LocalCoords object. * @details If the trajectory will not intersect any of the Surfaces in the * Cell returns INFINITY. - * @param point the Point of interest - * @param angle the angle of the trajectory (in radians from \f$[0,2\pi]\f$) - * @param min_intersection a pointer to the intersection Point that is found + * @param coords a pointer to a localcoords */ -double Cell::minSurfaceDist(Point* point, double angle, - Point* min_intersection) { +double Cell::minSurfaceDist(LocalCoords* coords) { + double curr_dist; double min_dist = INFINITY; - double d; - Point intersection; - std::map::iterator iter; + std::map::iterator iter; /* Loop over all of the Cell's Surfaces */ for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { /* Find the minimum distance from this surface to this Point */ - d = iter->second._surface->getMinDistance(point, angle, &intersection); + curr_dist = iter->second->_surface->getMinDistance(coords); /* If the distance to Cell is less than current min distance, update */ - if (d < min_dist) { - min_dist = d; - min_intersection->setX(intersection.getX()); - min_intersection->setY(intersection.getY()); - } + if (curr_dist < min_dist) + min_dist = curr_dist; } return min_dist; @@ -453,129 +1068,53 @@ double Cell::minSurfaceDist(Point* point, double angle, /** - * @brief Constructor sets the user-specified and unique IDs for this CellBasic. - * @param id the user-specified optional Cell ID - * @param name the user-specified optional Cell name - * @param rings the number of equal volume rings to divide this Cell into - * (the default is zero) - * @param sectors the number of angular sectors to divide this Cell into - * (the default is zero) - */ -CellBasic::CellBasic(int id, const char* name, int rings, int sectors): - Cell(id, name) { - - _cell_type = MATERIAL; - setNumRings(rings); - setNumSectors(sectors); -} - - - -/** - * @brief Return the Material filling the CellBasic. - * @return the Material's pointer - */ -Material* CellBasic::getMaterial() { - return _material; -} - - -/** - * @brief Return the number of rings in the Cell. - * @return the number of rings - */ -int CellBasic::getNumRings() { - return _num_rings; -} - - -/** - * @brief Return the number of sectors in the Cell. - * @return the number of sectors - */ -int CellBasic::getNumSectors() { - return _num_sectors; -} - - -/** - * @brief Returns an empty std::map of Cell IDs and Cell pointers. - * @return empty std::map of Cell IDs and pointers - */ -std::map CellBasic::getAllCells() { - std::map cells; - return cells; -} - - -/** - * @brief Returns an empty std::map of nested Universe IDs and pointers - * @return empty std::map of Universe IDs and pointers - */ -std::map CellBasic::getAllUniverses() { - std::map universes; - return universes; -} - - -/** - * @brief Sets the Material filling this Cell. - * @param material the Material filling this Cell - */ -void CellBasic::setMaterial(Material* material) { - _material = material; -} - - -/** - * @brief Set the Cell's number of rings. - * @param num_rings the number of rings in this Cell - */ -void CellBasic::setNumRings(int num_rings) { - if (num_rings < 0) - log_printf(ERROR, "Unable to give %d rings to Cell %d since this is " - "a negative number", num_rings, _id); - - _num_rings = num_rings; -} - - -/** - * @brief Set the Cell's number of sectors. - * @param num_sectors the number of sectors in this Cell + * @brief Returns true if this Cell is filled with a fissionable Material. + * @details If the Cell is filled by a Material, this method will simply query + * the filling Material. If the Cell is filled by a Universe, this + * method will consider any Materials filling those Cells contained + * by the filling Universe. This method should not be called prior to + * the calling of the Geometry::computeFissionability() method. + * @return true if contains a fissionable Material */ -void CellBasic::setNumSectors(int num_sectors) { - if (num_sectors < 0) - log_printf(ERROR, "Unable to give %d sectors to Cell %d since this is " - "a negative number", num_sectors, _id); - - /* By default, a ring is considered to have a single sector in [0, 2*pi] */ - if (num_sectors == 1) - _num_sectors = 0; - +bool Cell::isFissionable() { + if (_fill != NULL) + if (_cell_type == FILL) + return ((Universe*)_fill)->isFissionable(); + else + return ((Material*)_fill)->isFissionable(); else - _num_sectors = num_sectors; + return false; } /** - * @brief Create a duplicate of the CellBasic. + * @brief Create a duplicate of the Cell. * @return a pointer to the clone */ -CellBasic* CellBasic::clone() { +Cell* Cell::clone() { /* Construct new Cell */ - CellBasic* new_cell = new CellBasic(); + Cell* new_cell = new Cell(); new_cell->setName(_name); new_cell->setNumRings(_num_rings); new_cell->setNumSectors(_num_sectors); - new_cell->setMaterial(_material); + new_cell->setParent(this); + + if (_cell_type == MATERIAL) + new_cell->setFill((Material*)_fill); + else + new_cell->setFill((Universe*)_fill); + + if (_rotated) + new_cell->setRotation(_rotation, 3, "radians"); + if (_translated) + new_cell->setTranslation(_translation, 3); /* Loop over all of this Cell's Surfaces and add them to the clone */ - std::map::iterator iter; + std::map::iterator iter; for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) - new_cell->addSurface(iter->second._halfspace, iter->second._surface); + new_cell->addSurface(iter->second->_halfspace, iter->second->_surface); return new_cell; } @@ -583,8 +1122,9 @@ CellBasic* CellBasic::clone() { /** * @brief Subdivides the Cell into clones for fuel pin angular sectors. + * @param subcells an empty vector to store all subcells */ -void CellBasic::sectorize() { +void Cell::sectorize(std::vector& subcells) { /* If the user didn't request any sectors, don't make any */ if (_num_sectors == 0) @@ -594,7 +1134,7 @@ void CellBasic::sectorize() { double delta_azim = 2. * M_PI / _num_sectors; double A, B; - /* A container for each of the bouding planes for the sector Cells */ + /* A container for each of the bounding planes for the sector Cells */ std::vector planes; log_printf(DEBUG, "Sectorizing Cell %d with %d sectors",_id, _num_sectors); @@ -603,12 +1143,12 @@ void CellBasic::sectorize() { for (int i=0; i < _num_sectors; i++) { /* Figure out the angle for this plane */ - azim_angle = i * delta_azim; + azim_angle = i * delta_azim + M_PI / 4.0; /* Instantiate the plane */ A = cos(azim_angle); B = sin(azim_angle); - Plane* plane = new Plane(A, B, 0.); + Plane* plane = new Plane(A, B, 0., 0.); planes.push_back(plane); log_printf(DEBUG, "Created sector Plane id = %d, angle = %f, A = %f, " @@ -618,8 +1158,8 @@ void CellBasic::sectorize() { /* Create sectors using disjoint halfspaces of pairing Planes */ for (int i=0; i < _num_sectors; i++) { - /* Create new CellBasic clone for this sector Cell */ - CellBasic* sector = clone(); + /* Create new Cell clone for this sector Cell */ + Cell* sector = clone(); sector->setNumSectors(0); sector->setNumRings(0); @@ -638,28 +1178,26 @@ void CellBasic::sectorize() { } /* Store the clone in the parent Cell's container of sector Cells */ - _sectors.push_back(sector); + subcells.push_back(sector); } - - /* Store all of the sectors in the parent Cell's subcells container */ - _subcells.clear(); - _subcells.insert(_subcells.end(), _sectors.begin(), _sectors.end()); } /** * @brief Subdivides the Cell into clones for fuel pin rings. + * @param subcells an empty vector to store all subcells + * @param max_radius the maximum allowable radius used in the subdivisions */ -void CellBasic::ringify() { +void Cell::ringify(std::vector& subcells, double max_radius) { /* If the user didn't request any rings, don't make any */ if (_num_rings == 0) return; - int num_circles = 0; - Circle* circle1 = NULL; - Circle* circle2 = NULL; - double radius1 = 0; + int num_zcylinders = 0; + ZCylinder* zcylinder1 = NULL; + ZCylinder* zcylinder2 = NULL; + double radius1 = max_radius; double radius2 = 0; double x1 = 0.; double y1 = 0.; @@ -667,304 +1205,277 @@ void CellBasic::ringify() { double y2 = 0.; int halfspace1 = 0; int halfspace2 = 0; - std::vector circles; + std::vector zcylinders; + std::vector rings; - /* See if the Cell contains 1 or 2 CIRCLE Surfaces */ - std::map::iterator iter1; + /* See if the Cell contains 1 or 2 ZCYLINDER Surfaces */ + std::map::iterator iter1; for (iter1=_surfaces.begin(); iter1 != _surfaces.end(); ++iter1) { - /* Determine if any of the Surfaces is a Circle */ - if (iter1->second._surface->getSurfaceType() == CIRCLE) { - int halfspace = iter1->second._halfspace; - Circle* circle = static_cast(iter1->second._surface); + /* Determine if any of the Surfaces is a ZCylinder */ + if (iter1->second->_surface->getSurfaceType() == ZCYLINDER) { + int halfspace = iter1->second->_halfspace; + ZCylinder* zcylinder = static_cast(iter1->second->_surface); - /* Outermost bounding Circle */ + /* Outermost bounding ZCylinder */ if (halfspace == -1) { halfspace1 = halfspace; - circle1 = circle; - radius1 = circle1->getRadius(); - x1 = circle1->getX0(); - y1 = circle1->getY0(); + zcylinder1 = zcylinder; + radius1 = zcylinder1->getRadius(); + x1 = zcylinder1->getX0(); + y1 = zcylinder1->getY0(); } - /* Innermost bounding circle */ + /* Innermost bounding zcylinder */ else if (halfspace == +1) { halfspace2 = halfspace; - circle2 = circle; - radius2 = circle2->getRadius(); - x2 = circle2->getX0(); - y2 = circle2->getY0(); + zcylinder2 = zcylinder; + radius2 = zcylinder2->getRadius(); + x2 = zcylinder2->getX0(); + y2 = zcylinder2->getY0(); } - num_circles++; + num_zcylinders++; } } /* Error checking */ - if (num_circles == 0) + if (num_zcylinders == 0) log_printf(ERROR, "Unable to ringify Cell %d since it does not " - "contain any CIRCLE type Surface(s)", _id); + "contain any ZCYLINDER type Surface(s)", _id); - if (num_circles > 2) + if (num_zcylinders > 2) log_printf(NORMAL, "Unable to ringify Cell %d since it " - "contains more than 2 CIRCLE Surfaces", _id); + "contains more than 2 ZCYLINDER Surfaces", _id); - if (x1 != x2 && num_circles == 2) + if (x1 != x2 && num_zcylinders == 2) log_printf(ERROR, "Unable to ringify Cell %d since it contains " - "Circle %d centered at x=%f and Circle %d at x=%f. " - "Both Circles must have the same center.", - _id, circle1->getId(), x1, circle2->getId(), x2); + "ZCylinder %d centered at x=%f and ZCylinder %d at x=%f. " + "Both ZCylinders must have the same center.", + _id, zcylinder1->getId(), x1, zcylinder2->getId(), x2); - if (y1 != y2 && num_circles == 2) + if (y1 != y2 && num_zcylinders == 2) log_printf(ERROR, "Unable to ringify Cell %d since it contains " - "Circle %d centered at y=%f and Circle %d at y=%f. " - "Both Circles must have the same center.", - _id, circle1->getId(), y1, circle2->getId(), y2); - - if (circle1 == NULL && circle2 != NULL) - log_printf(ERROR, "Unable to ringify Cell %d since it only contains " - "the positive halfpsace of Circle %d. Rings can only be " - "created for Cells on the interior (negative halfspace) " - "of a CIRCLE Surface.", _id, circle2->getId()); + "ZCylinder %d centered at y=%f and ZCylinder %d at y=%f. " + "Both ZCylinders must have the same center.", + _id, zcylinder1->getId(), y1, zcylinder2->getId(), y2); if (radius1 <= radius2) log_printf(ERROR, "Unable to ringify Cell %d since it contains 2 " - "disjoint CIRCLE Surfaces: halfspace %d for Circle %d " - "and halfspace %d for Circle %d. Switch the signs of " + "disjoint ZCYLINDER Surfaces: halfspace %d for ZCylinder %d " + "and halfspace %d for ZCylinder %d. Switch the signs of " "the 2 halfspaces for each Surface.", _id, halfspace1, - circle1->getId(), halfspace2, circle2->getId()); + zcylinder1->getId(), halfspace2, zcylinder2->getId()); + + /* Loop over ZCylinders and create a new Cell clone for each ring */ + std::vector::iterator iter2; + std::vector::iterator iter3; - /* Compute the area to fill with each equal volume ring */ - double area = M_PI * fabs(radius1*radius1 - radius2*radius2) / _num_rings; + /* Compute the increment, either by radius or area, to use to construct + * the concentric rings */ + double increment; - /* Generate successively smaller Circle Surfaces */ + /* If there is no outer bounding surface, make the rings have the same + * radius increment (e.g. moderator in a pin cell universe). */ + if (halfspace1 == 0) + increment = fabs(radius1 - radius2) / _num_rings; + + /* If there is an outer bounding surface, make the rings have the same + * area (e.g. fuel in a pin cell universe).*/ + else + increment = M_PI * fabs(radius1*radius1 - radius2*radius2) / _num_rings; + + /* Generate successively smaller ZCylinders */ for (int i=0; i < _num_rings-1; i++) { - radius2 = sqrt(radius1*radius1 - (area / M_PI)); - Circle* circle = new Circle(x1, y1, radius1); - circles.push_back(circle); + + /* Compute the outer radius of the next ring */ + if (halfspace1 == 0) + radius2 = radius1 - increment; + else + radius2 = sqrt(radius1 * radius1 - (increment / M_PI)); + + ZCylinder* zcylinder = new ZCylinder(x1, y1, radius1); + zcylinders.push_back(zcylinder); radius1 = radius2; } - /* Store smallest, innermost Circle */ - Circle* circle = new Circle(x1, y1, radius1); - circles.push_back(circle); + /* Store smallest, innermost ZCylinder */ + ZCylinder* zcylinder = new ZCylinder(x1, y1, radius1); + zcylinders.push_back(zcylinder); - /* Loop over Circles and create a new Cell clone for each ring */ - std::vector::iterator iter2; - std::vector::iterator iter3; + /* Create ring Cells with successively smaller ZCylinders */ + for (iter2 = zcylinders.begin(); iter2 != zcylinders.end(); ++iter2) { - for (iter2 = circles.begin(); iter2 != circles.end(); ++iter2) { - - /* Create Circles for each of the sectorized Cells */ - if (_sectors.size() != 0) { - for (iter3 = _sectors.begin(); iter3 != _sectors.end(); ++iter3) { - log_printf(DEBUG, "Creating a new ring in sector Cell %d", + /* Create ZCylinders for each of the sectorized Cells */ + if (subcells.size() != 0) { + for (iter3 = subcells.begin(); iter3 != subcells.end(); ++iter3) { + log_printf(DEBUG, "Creating a new ring in sector Cell ID=%d", (*iter3)->getId()); - /* Create a new CellBasic clone */ - CellBasic* ring = (*iter3)->clone(); + /* Create a new Cell clone */ + Cell* ring = (*iter3)->clone(); ring->setNumSectors(0); ring->setNumRings(0); - /* Add new bounding Circle surfaces to the clone */ - ring->addSurface(-1, (*iter2)); + /* Add ZCylinder only if this is not the outermost ring in an + * unbounded Cell (i.e. the moderator in a fuel pin cell) */ + if ((*iter2)->getRadius() < max_radius) + ring->addSurface(-1, (*iter2)); - /* Look ahead and check if we have an inner Circle to add */ - if (iter2+1 == circles.end()) { - _rings.push_back(ring); + /* Look ahead and check if we have an inner ZCylinder to add */ + if (iter2+1 == zcylinders.end()) { + rings.push_back(ring); continue; } else ring->addSurface(+1, *(iter2+1)); /* Store the clone in the parent Cell's container of ring Cells */ - _rings.push_back(ring); + rings.push_back(ring); } } - /* Create Circles for this un-sectorized Cell */ + /* Create ZCylinders for this un-sectorized Cell */ else { log_printf(DEBUG, "Creating new ring in un-sectorized Cell %d",_id); - /* Create a new CellBasic clone */ - CellBasic* ring = clone(); + /* Create a new Cell clone */ + Cell* ring = clone(); ring->setNumSectors(0); ring->setNumRings(0); - /* Add new bounding Circle Surfaces to the clone */ - ring->addSurface(-1, (*iter2)); + /* Add ZCylinder only if this is not the outermost ring in an + * unbounded Cell (i.e. the moderator in a fuel pin cell) */ + if ((*iter2)->getRadius() < max_radius) + ring->addSurface(-1, (*iter2)); - /* Look ahead and check if we have an inner Circle to add */ - if (iter2+1 == circles.end()) { - _rings.push_back(ring); + /* Look ahead and check if we have an inner ZCylinder to add */ + if (iter2+1 == zcylinders.end()) { + rings.push_back(ring); break; } else ring->addSurface(+1, *(iter2+1)); /* Store the clone in the parent Cell's container of ring Cells */ - _rings.push_back(ring); + rings.push_back(ring); } } /* Store all of the rings in the parent Cell's subcells container */ - _subcells.clear(); - _subcells.insert(_subcells.end(), _rings.begin(), _rings.end()); + subcells.clear(); + subcells.insert(subcells.end(), rings.begin(), rings.end()); } /** - * @brief Subdivides a Cell into rings and sectors. + * @brief Subdivides a Cell into rings and sectors aligned with the z-axis. * @details This method uses the Cell's clone method to produce a vector of * this Cell's subdivided ring and sector Cells. + * @param max_radius the maximum allowable radius used in the subdivisions * @return a vector of Cell pointers to the new subdivided Cells */ -std::vector CellBasic::subdivideCell() { - sectorize(); - ringify(); - return _subcells; -} - - -/** - * @brief Convert this CellBasic's attributes to a string format. - * @return a character array of this CellBasic's attributes - */ -std::string CellBasic::toString() { - - std::stringstream string; - - string << "Cell ID = " << _id - << ", name = " << _name - << ", type = MATERIAL" - << ", material id = " << _material->getId() - << ", # surfaces = " << getNumSurfaces() - << ", # rings = " << _num_rings - << ", # sectors = " << _num_sectors; - - - /* Append each of the surface ids to the string */ - std::map::iterator iter; - string << ", surface ids = "; - for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) - string << iter->first << ", "; +void Cell::subdivideCell(double max_radius) { - return string.str(); -} + /** A container of all Cell clones created for rings and sectors */ + std::vector subcells; + sectorize(subcells); + ringify(subcells, max_radius); -/** - * @brief Prints a string representation of all of the CellBasic's attributes - * to the console. - */ -void CellBasic::printString() { - log_printf(NORMAL, toString().c_str()); -} - + /* Put any ring / sector subcells in a new Universe fill */ + if (subcells.size() != 0) { -/** - * @brief CellFill constructor - * @param id the user-specified optional Cell ID - * @param name the user-specified optional Cell name - */ -CellFill::CellFill(int id, const char* name): Cell(id, name) { - _cell_type = FILL; -} + /* Create a new Universe to contain all of the subcells */ + Universe* new_fill = new Universe(); + /* Add each subcell to the new Universe fill */ + std::vector::iterator iter; + for (iter = subcells.begin(); iter != subcells.end(); ++iter) + new_fill->addCell(*iter); -/** - * @brief Return a pointer to the Universe filling this Cell. - * @return the Universe pointer - */ -Universe* CellFill::getFill() const { - return _fill; + /* Set the new Universe as the fill for this Cell */ + setFill(new_fill); + } } /** - * @brief Returns the std::map of Cell IDs and Cell pointers within any - * nested Universes filling this Cell. - * @return std::map of Cell IDs and pointers + * @brief Build a collection of neighboring Cells for optimized ray tracing. */ -std::map CellFill::getAllCells() { - - std::map cells; - - if (_cell_type == FILL && _fill != NULL) { - std::map nested_cells; +void Cell::buildNeighbors() { - if (_fill->getType() == SIMPLE) - nested_cells = _fill->getAllCells(); - else - nested_cells = static_cast(_fill)->getAllCells(); + Surface* surface; + int halfspace; - cells.insert(nested_cells.begin(), nested_cells.end()); + /* Add this Cell to all of the Surfaces in this Cell */ + std::map::iterator iter; + for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) { + surface = iter->second->_surface; + halfspace = iter->second->_halfspace; + surface->addNeighborCell(halfspace, this); } - return cells; -} - - -/** - * @brief Returns the std::map of all nested Universe IDs and Universe pointers - filling this Cell. - * @return std::map of Universe IDs and pointers - */ -std::map CellFill::getAllUniverses() { - - std::map universes; - - if (_cell_type == FILL && _fill != NULL) { - universes[_fill->getId()] = _fill; - std::map nested_universes; - if (_fill->getType() == SIMPLE) - nested_universes = static_cast(_fill)->getAllUniverses(); + /* Make recursive call to the Cell's fill Universe */ + if (_cell_type == FILL) { + Universe* fill = static_cast(_fill); + if (fill->getType() == SIMPLE) + static_cast(fill)->buildNeighbors(); else - nested_universes = static_cast(_fill)->getAllUniverses(); - universes.insert(nested_universes.begin(), nested_universes.end()); + static_cast(fill)->buildNeighbors(); } - - return universes; -} - - -/** - * @brief Set a pointer to the Universe filling this CellFill. - * @param universe the Universe's pointer - */ -void CellFill::setFill(Universe* universe) { - _fill = universe; } /** - * @brief Convert this CellFill's attributes to a string format. + * @brief Convert this Cell's attributes to a string format. * @return a character array of this Cell's attributes */ -std::string CellFill::toString() { +std::string Cell::toString() { std::stringstream string; string << "Cell ID = " << _id << ", name = " << _name - << ", type = FILL, " - << ", fill = " << _fill->getId() - << ", # surfaces = " << getNumSurfaces(); + << ", # rings = " << _num_rings + << ", # sectors = " << _num_sectors; + + if (_cell_type == FILL) { + string << ", type = FILL, " + << ", fill id = " << static_cast(_fill)->getId(); + } + else if(_cell_type == MATERIAL) { + string << ", type = MATERIAL" + << ", fill id = " << static_cast(_fill)->getId(); + } + else + string << ", type = UNFILLED"; + + if (_rotated) { + string << ", (rotation = " << getPhi() << ", "; + string << getTheta() << ", " << getPsi() << ")"; + } + if (_translated) { + string << ", (translation = " << _translation[0] << ", "; + string << _translation[1] << ", " << _translation[2] << ")"; + } + + string << ", # surfaces = " << getNumSurfaces(); - /** Add the IDs for the Surfaces in this Cell */ - std::map::iterator iter; - string << ", surface ids = "; + /** Add string data for the Surfaces in this Cell */ + std::map::iterator iter; + string << ", Surfaces: "; for (iter = _surfaces.begin(); iter != _surfaces.end(); ++iter) - string << iter->first << ", "; + string << iter->second->_surface->toString() << ", "; return string.str(); } /** - * @brief Prints a string representation of all of the CellFill's attributes + * @brief Prints a string representation of all of the Cell's attributes * to the console. */ -void CellFill::printString() { +void Cell::printString() { log_printf(NORMAL, toString().c_str()); } diff --git a/src/Cell.h b/src/Cell.h index 3a5107ce2..78d1d6490 100644 --- a/src/Cell.h +++ b/src/Cell.h @@ -10,12 +10,14 @@ #define CELL_H_ #ifdef __cplusplus -#include -#include -#include +#ifdef SWIG +#include "Python.h" +#endif #include "Material.h" #include "Surface.h" #include "Point.h" +#include +#include #endif /* Forward declarations to resolve circular dependencies */ @@ -24,6 +26,7 @@ class Surface; int cell_id(); void reset_cell_id(); +void maximize_cell_id(int cell_id); /** @@ -49,11 +52,14 @@ struct surface_halfspace { */ enum cellType { - /** A cell filled by a material */ + /** A cell filled by a Material */ MATERIAL, - /** A cell filled by a universe */ - FILL + /** A cell filled by a Universe */ + FILL, + + /** A cell not yet filled by anything */ + UNFILLED }; @@ -63,14 +69,11 @@ enum cellType { */ class Cell { -protected: +private: /** A static counter for the number of Cells */ static int _n; - /** A static counter for the number of times this Cell has been cloned */ - static int _num_clones; - /** A monotonically increasing unique ID for each Cell created */ int _uid; @@ -83,56 +86,71 @@ class Cell { /** The type of Cell (ie MATERIAL or FILL) */ cellType _cell_type; - /** The ID for the Universe within which this cell resides */ - int _universe; + /** A pointer to the Material or Universe filling this Cell */ + void* _fill; - /** Map of bounding Surface IDs with pointers and halfspaces (+/-1) */ - std::map _surfaces; + /** The volume / area of the Cell computed from overlapping segments */ + double _volume; - /** The minimum reachable x-coordinate within the Cell */ - double _min_x; + /** The total number of instances of this Cell in the Geometry */ + int _num_instances; - /** The maximum reachable x-coordinate within the Cell */ - double _max_x; + /* A boolean indicating whether to cell is rotated */ + bool _rotated; - /** The minimum reachable y-coordinate within the Cell */ - double _min_y; + /* An array with angles in degrees for rotations about x, y, and z */ + double _rotation[3]; - /** The maximum reachable y-coordinate within the Cell */ - double _max_y; + /* A rotation matrix defined in terms of the rotation angles */ + double _rotation_matrix[9]; - /** The minimum reachable z-coordinate within the Cell */ - double _min_z; + /* A boolean indicating whether to cell is translated */ + bool _translated; - /** The maximum reachable z-coordinate within the Cell */ - double _max_z; + /* An array with translations in x, y and z */ + double _translation[3]; - /** The boundary condition at the minimum reachable x-coordinate */ - boundaryType _min_x_bc; + /** The number of rings sub-dividing this Cell */ + int _num_rings; - /** The boundary condition at the maximum reachable x-coordinate */ - boundaryType _max_x_bc; + /** The number of sectors sub-dividing this Cell */ + int _num_sectors; - /** The boundary condition at the minimum reachable y-coordinate */ - boundaryType _min_y_bc; + /** A parent Cell if cloned by another Cell */ + Cell* _parent; - /** The boundary condition at the maximum reachable y-coordinate */ - boundaryType _max_y_bc; + /** Map of bounding Surface IDs with pointers and halfspaces (+/-1) */ + std::map _surfaces; - /** The boundary condition at the minimum reachable z-coordinate */ - boundaryType _min_z_bc; + /* Vector of neighboring Cells */ + std::vector _neighbors; - /** The boundary condition at the maximum reachable z-coordinate */ - boundaryType _max_z_bc; + void ringify(std::vector& subcells, double max_radius); + void sectorize(std::vector& subcells); public: - Cell(); Cell(int id=0, const char* name=""); virtual ~Cell(); int getUid() const; int getId() const; char* getName() const; cellType getType() const; + Material* getFillMaterial(); + Universe* getFillUniverse(); + double getVolume(); + int getNumInstances(); + bool isRotated(); + bool isTranslated(); + double getPhi(std::string units="degrees"); + double getTheta(std::string units="degrees"); + double getPsi(std::string units="degrees"); + double* getRotationMatrix(); + double* getTranslation(); + void retrieveRotation(double* rotations, int num_axes, + std::string units="degrees"); + void retrieveTranslation(double* translations, int num_axes); + int getNumRings(); + int getNumSectors(); double getMinX(); double getMaxX(); double getMinY(); @@ -143,119 +161,44 @@ class Cell { boundaryType getMaxXBoundaryType(); boundaryType getMinYBoundaryType(); boundaryType getMaxYBoundaryType(); - boundaryType getMinZBoundaryType(); - boundaryType getMaxZBoundaryType(); int getNumSurfaces() const; - std::map getSurfaces() const; - - /** - * @brief Returns the std::map of Cell IDs and Cell pointers within any - * nested Universes filling this Cell. - * @return std::map of Cell IDs and pointers - */ - virtual std::map getAllCells() =0; - - /** - * @brief Returns the std::map of Universe IDs and Universe pointers within - * any nested Universes filling this Universe. - * @return std::map of Universe IDs and pointers - */ - virtual std::map getAllUniverses() =0; - - void setName(const char* name); - void addSurface(int halfspace, Surface* surface); - void removeSurface(Surface* surface); - void findBoundingBox(); - - bool cellContainsPoint(Point* point); - bool cellContainsCoords(LocalCoords* coords); - double minSurfaceDist(Point* point, double angle, Point* min_intersection); - /** - * @brief Convert this CellFill's attributes to a string format. - * @return a character array of this Cell's attributes - */ - virtual std::string toString() =0; - - /** - * @brief Prints a string representation of all of the Cells's objects to - * the console. - */ - virtual void printString() =0; -}; - - -/** - * @class CellBasic Cell.h "src/Cell.h" - * @brief Represents a Cell filled with a Material. - */ -class CellBasic: public Cell { - -private: - - /** A pointer to the Material filling this Cell */ - Material* _material; - - /** The number of rings sub-dividing this Cell */ - int _num_rings; - - /** The number of sectors sub-dividing this Cell */ - int _num_sectors; - - /** A container of all CellBasic clones created for rings */ - std::vector _rings; - - /** A container of all CellBasic clones created for angular sectors */ - std::vector _sectors; - - /** A container of all CellBasic clones created for rings and sectors */ - std::vector _subcells; - - void ringify(); - void sectorize(); - -public: - CellBasic(int id=0, const char* name="", int rings=0, int sectors=0); + std::map getSurfaces() const; + std::vector getNeighbors() const; + bool hasParent(); + Cell* getParent(); + Cell* getOldestAncestor(); - Material* getMaterial(); - int getNumRings(); - int getNumSectors(); std::map getAllCells(); std::map getAllUniverses(); - void setMaterial(Material* material); + void setName(const char* name); + void setFill(Material* fill); + void setFill(Universe* fill); + void setVolume(double volume); + void incrementVolume(double volume); + void setNumInstances(int num_instances); + void incrementNumInstances(); + void setRotation(double* rotation, int num_axes, std::string units="degrees"); + void setTranslation(double* translation, int num_axes); void setNumRings(int num_rings); void setNumSectors(int num_sectors); + void setParent(Cell* parent); + void addSurface(int halfspace, Surface* surface); + void removeSurface(Surface* surface); + void addNeighborCell(Cell* cell); - CellBasic* clone(); - std::vector subdivideCell(); - - std::string toString(); - void printString(); -}; - - -/** - * @class CellFill Cell.h "src/Cell.h" - * @brief Represents a Cell filled with a Universe. - */ -class CellFill: public Cell { - -private: - - /** The pointer to the Universe filling this Cell */ - Universe* _fill; - -public: - CellFill(int id=0, const char* name=""); + bool isFissionable(); + bool containsPoint(Point* point); + bool containsCoords(LocalCoords* coords); + double minSurfaceDist(LocalCoords* coords); - Universe* getFill() const; - std::map getAllCells(); - std::map getAllUniverses(); - - void setFill(Universe* universe_fill); + Cell* clone(); + void subdivideCell(double max_radius); + void buildNeighbors(); std::string toString(); void printString(); }; + #endif /* CELL_H_ */ diff --git a/src/Cmfd.cpp b/src/Cmfd.cpp index acbe0b8fd..29279bd05 100644 --- a/src/Cmfd.cpp +++ b/src/Cmfd.cpp @@ -4,31 +4,28 @@ * @brief Constructor initializes boundaries and variables that describe * the Cmfd object. * @details The construcor initializes the many variables that describe - * the CMFD Mesh, the solve method, and flux type. If solve - * method is DIFFUSION, the fsr volumes, Materials, and fluxes - * are initialized. - * @param geometry pointer to the Geometry - * @param criteria convergence criteria on keff + * the CMFD mesh and are used to solve the nonlinear diffusion + * acceleration problem. */ Cmfd::Cmfd() { /* Initialize Geometry and Mesh-related attribute */ - _quad = NULL; - _SOR_factor = 1.0; + _polar_quad = NULL; + _geometry = NULL; + _materials = NULL; /* Global variables used in solving CMFD problem */ - _source_convergence_threshold = 1E-7; _num_x = 1; _num_y = 1; - _width = 0.; - _height = 0.; - _cell_width = 0.; - _cell_height = 0.; + _width_x = 0.; + _width_y = 0.; + _cell_width_x = 0.; + _cell_width_y = 0.; _flux_update_on = true; - _optically_thick = false; + _centroid_update_on = true; + _k_nearest = 3; _SOR_factor = 1.0; _num_FSRs = 0; - _relax_factor = 0.6; /* Energy group and polar angle problem parameters */ _num_moc_groups = 0; @@ -38,279 +35,303 @@ Cmfd::Cmfd() { /* Set matrices and arrays to NULL */ _A = NULL; _M = NULL; - _flux_temp = NULL; + _old_flux = NULL; + _new_flux = NULL; + _flux_ratio = NULL; _old_source = NULL; _new_source = NULL; _group_indices = NULL; _group_indices_map = NULL; + _user_group_indices = false; + _surface_currents = NULL; + _cell_locks = NULL; + _volumes = NULL; + _lattice = NULL; /* Initialize boundaries to be reflective */ - // _boundaries = new int[4]; _boundaries = new boundaryType[4]; - _boundaries[0] = REFLECTIVE; - _boundaries[1] = REFLECTIVE; - _boundaries[2] = REFLECTIVE; - _boundaries[3] = REFLECTIVE; + _boundaries[SURFACE_X_MIN] = REFLECTIVE; + _boundaries[SURFACE_X_MAX] = REFLECTIVE; + _boundaries[SURFACE_Y_MIN] = REFLECTIVE; + _boundaries[SURFACE_Y_MAX] = REFLECTIVE; } /** - * @brief Destructor deletes arrays of A and M row insertion arrays. + * @brief Destructor. */ Cmfd::~Cmfd() { - /* Delete matrix and vector objects */ + if (_cell_locks != NULL) + delete [] _cell_locks; - if (_M != NULL){ - for (int i = 0; i < _num_x*_num_y; i++) - delete [] _M[i]; + if (_boundaries != NULL) + delete [] _boundaries; - delete [] _M; - } + if (_group_indices != NULL) + delete [] _group_indices; - if (_A != NULL){ - for (int i = 0; i < _num_x*_num_y; i++) - delete [] _A[i]; + if (_group_indices_map != NULL) + delete [] _group_indices_map; - delete [] _A; - } + /* Delete the Matrix and Vector objects */ + if (_M != NULL) + delete _M; + + if (_A != NULL) + delete _A; + + if (_old_source != NULL) + delete _old_source; + + if (_new_source != NULL) + delete _new_source; if (_old_flux != NULL) - delete [] _old_flux; + delete _old_flux; if (_new_flux != NULL) - delete [] _new_flux; + delete _new_flux; - if (_flux_temp != NULL) - delete [] _flux_temp; + if (_flux_ratio != NULL) + delete _flux_ratio; - if (_old_source != NULL) - delete [] _old_source; + if (_surface_currents != NULL) + delete _surface_currents; - if (_new_source != NULL) - delete [] _new_source; + if (_volumes != NULL) + delete _volumes; + + /* Delete Cmfd materials array */ + if (_materials != NULL) { + for (int i=0; i < _num_x * _num_y; i++) + delete _materials[i]; + } + delete [] _materials; + + /* Delete the Cmfd lattice */ + if (_lattice != NULL) + delete _lattice; + + /* Clear the _cell_fsrs vector of vectors */ + std::vector< std::vector >::iterator iter1; + for (iter1 = _cell_fsrs.begin(); iter1 != _cell_fsrs.end(); ++iter1) + iter1->clear(); + _cell_fsrs.clear(); + + /* Clear the _k_nearest_stencils map of vectors */ + std::map > >::iterator iter2; + for (iter2 = _k_nearest_stencils.begin(); iter2 != _k_nearest_stencils.end(); + ++iter2) + iter2->second.clear(); + _k_nearest_stencils.clear(); } /** * @brief Set the number of Mesh cells in a row. - * @param number of Mesh cells in a row + * @param num_x Number of Mesh cells in a row */ -void Cmfd::setNumX(int num_x){ +void Cmfd::setNumX(int num_x) { if (num_x < 1) log_printf(ERROR, "The number of lattice cells in the x direction " - "must be > 0. Input value: %i", num_x); + "must be > 0. Input value: %d", num_x); _num_x = num_x; - if (_width != 0.) - _cell_width = _width / _num_x; + if (_width_x != 0.) + _cell_width_x = _width_x / _num_x; } /** * @brief Set the number of Mesh cells in a column - * @param number of Mesh cells in a column + * @param num_y Number of Mesh cells in a column */ -void Cmfd::setNumY(int num_y){ +void Cmfd::setNumY(int num_y) { if (num_y < 1) log_printf(ERROR, "The number of lattice cells in the y direction " - "must be > 0. Input value: %i", num_y); + "must be > 0. Input value: %d", num_y); _num_y = num_y; - if (_height != 0.) - _cell_height = _height / _num_y; + if (_width_y != 0.) + _cell_width_y = _width_y / _num_y; } /** * @brief Get the number of Mesh cells in a row. - * @return number of Mesh cells in a row + * @return The number of Mesh cells in a row */ -int Cmfd::getNumX(){ +int Cmfd::getNumX() { return _num_x; } /** * @brief Get the number of Mesh cells in a column - * @return number of Mesh cells in a column + * @return The number of Mesh cells in a column */ -int Cmfd::getNumY(){ +int Cmfd::getNumY() { return _num_y; } /** - * @brief Set Mesh width. - * @param width physical width of Mesh + * @brief Set Mesh width in the x-direction + * @param width Physical width of Mesh in the x-direction */ -void Cmfd::setWidth(double width){ - _width = width; +void Cmfd::setWidthX(double width) { + _width_x = width; if (_num_x != 0) - _cell_width = _width / _num_x; + _cell_width_x = _width_x / _num_x; } /** - * @brief Set Mesh height. - * @param height physical height of Mesh + * @brief Set Mesh width in the y-direction + * @param width Physical width of Mesh in the y-direction */ -void Cmfd::setHeight(double height){ - _height = height; +void Cmfd::setWidthY(double width) { + _width_y = width; if (_num_y != 0) - _cell_height = _height / _num_y; + _cell_width_y = _width_y / _num_y; } /** - * @brief Create cross-sections and fluxes for each Cmfd cell by + * @brief Collapse cross-sections and fluxes for each Cmfd cell by * energy condensing and volume averaging cross sections from * the MOC sweep. + * @details This method performs a cell-wise energy condensation and volume + * average of the cross sections of the fine, unstructured FSR mesh. + * The cross sections are condensed such that all reaction rates and + * the neutron production rate from fission are conserved. It is + * important to note that the volume averaging is performed before + * energy condensation in order to properly collapse the diffusion + * coefficients. */ -void Cmfd::computeXS(){ - - log_printf(INFO, "Computing CMFD cross-sections..."); +void Cmfd::collapseXS() { - /* Split corner currents to side surfaces */ - splitCorners(); + log_printf(INFO, "Collapsing cross-sections onto CMFD mesh..."); - /* Initialize variables for FSR properties*/ - FP_PRECISION volume, flux, abs, tot, nu_fis, chi, dif_coef; - FP_PRECISION* scat; + /* Split edge currents to side surfaces */ + splitEdgeCurrents(); - /* Initialize tallies for each parameter */ - FP_PRECISION abs_tally, nu_fis_tally, dif_tally, rxn_tally; - FP_PRECISION vol_tally, tot_tally, neut_prod_tally; - FP_PRECISION trans_tally_group, rxn_tally_group; - FP_PRECISION scat_tally[_num_cmfd_groups]; - FP_PRECISION chi_tally[_num_cmfd_groups]; +#pragma omp parallel + { - /* Pointers to material objects */ - Material* fsr_material; - Material* cell_material; + /* Initialize variables for FSR properties*/ + FP_PRECISION volume, flux, tot, nu_fis, chi; + FP_PRECISION* scat; - /* Loop over cmfd cells */ - #pragma omp parallel for private(volume, flux, abs, tot, nu_fis, chi, \ - dif_coef, scat, abs_tally, nu_fis_tally, dif_tally, rxn_tally, \ - vol_tally, tot_tally, scat_tally, fsr_material, cell_material, \ - neut_prod_tally, chi_tally, trans_tally_group, rxn_tally_group) - for (int i = 0; i < _num_x * _num_y; i++){ + /* Initialize tallies for each parameter */ + FP_PRECISION nu_fis_tally, rxn_tally; + FP_PRECISION vol_tally, tot_tally, neut_prod_tally; + FP_PRECISION scat_tally[_num_cmfd_groups]; + FP_PRECISION chi_tally[_num_cmfd_groups]; - cell_material = _materials[i]; - std::vector::iterator iter; + /* Pointers to material objects */ + Material* fsr_material; + Material* cell_material; - /* Loop over CMFD coarse energy groups */ - for (int e = 0; e < _num_cmfd_groups; e++) { + /* Loop over cmfd cells */ +#pragma omp for + for (int i = 0; i < _num_x * _num_y; i++) { - /* Zero tallies for this group */ - abs_tally = 0.0; - nu_fis_tally = 0.0; - dif_tally = 0.0; - rxn_tally = 0.0; - vol_tally = 0.0; - tot_tally = 0.0; - neut_prod_tally = 0.0; - - /* Zero each group-to-group scattering tally */ - for (int g = 0; g < _num_cmfd_groups; g++){ - scat_tally[g] = 0; - chi_tally[g] = 0.0; - } + cell_material = _materials[i]; + std::vector::iterator iter; - /* Loop over FSRs in cmfd cell to compute chi */ - for (iter = _cell_fsrs.at(i).begin(); - iter != _cell_fsrs.at(i).end(); ++iter){ - - fsr_material = _FSR_materials[*iter]; - volume = _FSR_volumes[*iter]; - - /* Chi tallies */ - for (int b = 0; b < _num_cmfd_groups; b++){ - chi = 0.0; - - /* Compute the chi for group b */ - for (int h = _group_indices[b]; h < _group_indices[b+1]; h++) - chi += fsr_material->getChi()[h]; - - for (int h = 0; h < _num_moc_groups; h++){ - chi_tally[b] += chi * fsr_material->getNuSigmaF()[h] * - _FSR_fluxes[(*iter)*_num_moc_groups+h] * volume; - neut_prod_tally += chi * fsr_material->getNuSigmaF()[h] * - _FSR_fluxes[(*iter)*_num_moc_groups+h] * volume; - } - } - } + /* Loop over CMFD coarse energy groups */ + for (int e = 0; e < _num_cmfd_groups; e++) { - /* Loop over MOC energy groups within this CMFD coarse group */ - for (int h = _group_indices[e]; h < _group_indices[e+1]; h++){ - - /* Reset transport xs tally for this MOC group */ - trans_tally_group = 0.0; - rxn_tally_group = 0.0; + /* Zero tallies for this group */ + nu_fis_tally = 0.0; + rxn_tally = 0.0; vol_tally = 0.0; + tot_tally = 0.0; + neut_prod_tally = 0.0; + + /* Zero each group-to-group scattering tally */ + for (int g = 0; g < _num_cmfd_groups; g++) { + scat_tally[g] = 0; + chi_tally[g] = 0.0; + } - /* Loop over FSRs in cmfd cell */ + /* Loop over FSRs in cmfd cell to compute chi */ for (iter = _cell_fsrs.at(i).begin(); - iter != _cell_fsrs.at(i).end(); ++iter){ + iter != _cell_fsrs.at(i).end(); ++iter) { fsr_material = _FSR_materials[*iter]; volume = _FSR_volumes[*iter]; - scat = fsr_material->getSigmaS(); - vol_tally += volume; - - /* Gets FSR volume, material, and cross sections */ - flux = _FSR_fluxes[(*iter)*_num_moc_groups+h]; - abs = fsr_material->getSigmaA()[h]; - tot = fsr_material->getSigmaT()[h]; - nu_fis = fsr_material->getNuSigmaF()[h]; - - /* Increment tallies for this group */ - abs_tally += abs * flux * volume; - tot_tally += tot * flux * volume; - nu_fis_tally += nu_fis * flux * volume; - rxn_tally += flux * volume; - trans_tally_group += tot * flux * volume; - rxn_tally_group += flux * volume; - - /* Scattering tallies */ - for (int g = 0; g < _num_moc_groups; g++){ - scat_tally[getCmfdGroup(g)] += - scat[g*_num_moc_groups+h] * flux * volume; + + /* Chi tallies */ + for (int b = 0; b < _num_cmfd_groups; b++) { + chi = 0.0; + + /* Compute the chi for group b */ + for (int h = _group_indices[b]; h < _group_indices[b + 1]; h++) + chi += fsr_material->getChiByGroup(h+1); + + for (int h = 0; h < _num_moc_groups; h++) { + chi_tally[b] += chi * fsr_material->getNuSigmaFByGroup(h+1) * + _FSR_fluxes[(*iter)*_num_moc_groups+h] * volume; + neut_prod_tally += chi * fsr_material->getNuSigmaFByGroup(h+1) * + _FSR_fluxes[(*iter)*_num_moc_groups+h] * volume; + } } } - /* Energy collapse diffusion coefficient */ - dif_tally += rxn_tally_group / - (3.0 * (trans_tally_group / rxn_tally_group)); - } + /* Loop over MOC energy groups within this CMFD coarse group */ + for (int h = _group_indices[e]; h < _group_indices[e+1]; h++) { + + /* Reset volume tally for this MOC group */ + vol_tally = 0.0; + + /* Loop over FSRs in cmfd cell */ + for (iter = _cell_fsrs.at(i).begin(); + iter != _cell_fsrs.at(i).end(); ++iter) { + + /* Gets FSR volume, material, and cross sections */ + fsr_material = _FSR_materials[*iter]; + volume = _FSR_volumes[*iter]; + scat = fsr_material->getSigmaS(); + flux = _FSR_fluxes[(*iter)*_num_moc_groups+h]; + tot = fsr_material->getSigmaTByGroup(h+1); + nu_fis = fsr_material->getNuSigmaFByGroup(h+1); + + /* Increment tallies for this group */ + tot_tally += tot * flux * volume; + nu_fis_tally += nu_fis * flux * volume; + rxn_tally += flux * volume; + vol_tally += volume; + + /* Scattering tallies */ + for (int g = 0; g < _num_moc_groups; g++) { + scat_tally[getCmfdGroup(g)] += + scat[g*_num_moc_groups+h] * flux * volume; + } + } + } - /* Set the Mesh cell properties with the tallies */ - _volumes[i] = vol_tally; - cell_material->setSigmaAByGroup(abs_tally / rxn_tally, e+1); - cell_material->setSigmaTByGroup(tot_tally / rxn_tally, e+1); - cell_material->setNuSigmaFByGroup(nu_fis_tally / rxn_tally, e+1); - cell_material->setDifCoefByGroup(dif_tally / rxn_tally, e+1); - _old_flux[i*_num_cmfd_groups+e] = rxn_tally / vol_tally; - - /* Set chi */ - if (neut_prod_tally != 0.0) - cell_material->setChiByGroup(chi_tally[e] / neut_prod_tally, e+1); - else - cell_material->setChiByGroup(0.0,e+1); - - log_printf(DEBUG, "cell: %i, group: %i, vol: %e, siga: %e, sigt: %e," - " nu_sigf: %e, dif_coef: %e, flux: %e, chi: %e", i, e, - vol_tally, abs_tally / rxn_tally, tot_tally / rxn_tally, - nu_fis_tally / rxn_tally, dif_tally / rxn_tally, - rxn_tally / vol_tally, cell_material->getChi()[e]); - - /* Set scattering xs */ - for (int g = 0; g < _num_cmfd_groups; g++){ - cell_material->setSigmaSByGroup(scat_tally[g] / rxn_tally, e+1, g+1); - log_printf(DEBUG, "scattering from %i to %i: %e", e, g, - scat_tally[g] / rxn_tally); + /* Set the Mesh cell properties with the tallies */ + _volumes->setValue(i, 0, vol_tally); + cell_material->setSigmaTByGroup(tot_tally / rxn_tally, e + 1); + cell_material->setNuSigmaFByGroup(nu_fis_tally / rxn_tally, e + 1); + _old_flux->setValue(i, e, rxn_tally / vol_tally); + + /* Set chi */ + if (neut_prod_tally != 0.0) + cell_material->setChiByGroup(chi_tally[e] / neut_prod_tally, e + 1); + else + cell_material->setChiByGroup(0.0, e + 1); + + /* Set scattering xs */ + for (int g = 0; g < _num_cmfd_groups; g++) { + cell_material->setSigmaSByGroup(scat_tally[g] / rxn_tally, e + 1, + g + 1); + } } } } @@ -318,606 +339,327 @@ void Cmfd::computeXS(){ /** - * @brief Compute the diffusion coefficients: - * \f$ D \f$ - straight diffusion coefficient - * \f$ \hat{D} \f$ - surface diffusion coefficient - * \f$ \tilde{D} \f$ - surface diffusion coefficient correction factor - * for each mesh while ensuring neutron balance is achieved. - * @param MOC iteration number - */ -void Cmfd::computeDs(int moc_iteration){ - - log_printf(INFO, "Computing CMFD diffusion coefficients..."); - - FP_PRECISION d, d_next, d_hat, d_tilde; - FP_PRECISION current, flux, flux_next, f, f_next; - FP_PRECISION length, length_perpen, next_length_perpen; - FP_PRECISION sense; - int next_surface; - int cell, cell_next; - - /* Loop over mesh cells in y direction */ - #pragma omp parallel for private(d, d_next, d_hat, d_tilde, current, flux, \ - flux_next, f, f_next, length, length_perpen, next_length_perpen, \ - sense, next_surface, cell, cell_next) - for (int y = 0; y < _num_y; y++){ - - /* Loop over Mesh cells in x direction */ - for (int x = 0; x < _num_x; x++){ - - cell = y*_num_x+x; - - /* Loop over Surfaces in a cell */ - for (int surface = 0; surface < 4; surface++){ - - /* Loop over groups */ - for (int e = 0; e < _num_cmfd_groups; e++){ - - /* Get diffusivity and flux for Mesh cell */ - d = _materials[cell]->getDifCoef()[e]; - flux = _old_flux[cell*_num_cmfd_groups+e]; - cell_next = getCellNext(cell, surface); - - /* Set halfspace sense of the Surface */ - if (surface == 0 || surface == 1) - sense = -1.0; - else - sense = 1.0; - - /* Set the length of this Surface and the perpendicular Surface */ - if (surface == 0 || surface== 2){ - length = _cell_height; - length_perpen = _cell_width; - } - else if (surface == 1 || surface == 3){ - length = _cell_width; - length_perpen = _cell_height; - } - - /* Compute the optical thickness correction factor */ - f = computeDiffCorrect(d, length_perpen); - - /* If Surface is on a boundary, choose appropriate BCs */ - if (cell_next == -1){ - - current = sense * _surface_currents[cell*_num_cmfd_groups*8 + - surface*_num_cmfd_groups + e]; - - /* REFLECTIVE BC */ - if (_boundaries[surface] == REFLECTIVE){ + * @brief Computes the diffusion coefficient for a given cmfd cell and cmfd + * energy group. + * @details This method computes the diffusion coefficient for a cmfd cell and + * cmfd energy group by spatially collapsing the total/transport xs + * in each FSR contained within the cmfd cell and then energy + * collapsing the diffusion coefficient (\f$1 / (3 * \Sigma_t)\f$) for + * all MOC groups in the given cmfd energy group. + * @param cmfd_cell A Cmfd cell + * @param group A Cmfd energy group + * @return The diffusion coefficient + */ +FP_PRECISION Cmfd::getDiffusionCoefficient(int cmfd_cell, int group) { - /* Set D's */ - d_hat = 0.0; - d_tilde = 0.0; - } + /* Pointers to material objects */ + Material* fsr_material; + Material* cell_material = _materials[cmfd_cell]; + std::vector::iterator iter; - /* VACUUM BC */ - else if (_boundaries[surface] == VACUUM){ + /* Zero tallies for this group */ + FP_PRECISION dif_tally = 0.0; + FP_PRECISION rxn_tally = 0.0; + FP_PRECISION trans_tally_group, rxn_tally_group; + FP_PRECISION tot, flux, volume; - /* Set D's */ - d_hat = 2 * d*f / length_perpen / (1 + 4 * d*f / - length_perpen); - d_tilde = (sense * d_hat * flux - current / length) / flux; - } - } + /* Loop over MOC energy groups within this CMFD coarse group */ + for (int h = _group_indices[group]; h < _group_indices[group+1]; h++) { - /* If Surface is an interface, use finite differencing */ - else{ + /* Reset transport and rxn tally for this MOC group */ + trans_tally_group = 0.0; + rxn_tally_group = 0.0; - /* Set properties for cell next to Surface */ - if (surface == 0){ - next_length_perpen = _cell_width; - next_surface = 2; - } - else if (surface == 1){ - next_length_perpen = _cell_height; - next_surface = 3; - } - else if (surface == 2){ - next_length_perpen = _cell_width; - next_surface = 0; - } - else if (surface == 3){ - next_length_perpen = _cell_height; - next_surface = 1; - } + /* Loop over FSRs in cmfd cell */ + for (iter = _cell_fsrs.at(cmfd_cell).begin(); + iter != _cell_fsrs.at(cmfd_cell).end(); ++iter) { - /* Set diffusion coefficient and flux for neighboring cell */ - d_next = _materials[cell_next]->getDifCoef()[e]; - flux_next = _old_flux[cell_next*_num_cmfd_groups + e]; - - /* Get optical thickness correction term for meshCellNext */ - f_next = computeDiffCorrect(d_next, next_length_perpen); - - /* Compute d_hat */ - d_hat = 2.0 * d * f * d_next * f_next / (length_perpen - * d * f + next_length_perpen * d_next*f_next); - - /* Compute net current */ - current = sense * _surface_currents[cell*_num_cmfd_groups*8 + - surface*_num_cmfd_groups + e] - sense - * _surface_currents[cell_next*_num_cmfd_groups*8 + - next_surface*_num_cmfd_groups + e]; - - /* Compute d_tilde */ - d_tilde = -(sense * d_hat * (flux_next - flux) + - current / length) / (flux_next + flux); - - /* If the magnitude of d_tilde is greater than the magnitude of - * d_hat, select new values d_tilde and d_hat to ensure the course - * mesh equations are guaranteed to be diagonally dominant */ - if (fabs(d_tilde) > fabs(d_hat) && moc_iteration != 0){ - - if (sense == -1){ - - /* If d_tilde is positive */ - if (1 - fabs(d_tilde)/d_tilde < 1e-8){ - d_hat = - current/(2*flux*length); - d_tilde = - current/(2*flux*length); - } - - /* If d_tilde is negative */ - else{ - d_hat = current/(2*flux_next*length); - d_tilde = - current/(2*flux_next*length); - } - } - else{ - - /* If d_tilde is positive */ - if (1 - fabs(d_tilde)/d_tilde < 1e-8){ - d_hat = - current/(2*flux_next*length); - d_tilde = - current/(2*flux_next*length); - } - - /* If d_tilde is negative */ - else{ - d_hat = current/(2*flux*length); - d_tilde = - current/(2*flux*length); - } - } - } - } + fsr_material = _FSR_materials[*iter]; + volume = _FSR_volumes[*iter]; + flux = _FSR_fluxes[(*iter)*_num_moc_groups+h]; + tot = fsr_material->getSigmaTByGroup(h+1); - /* Perform underrelaxation on d_tilde. If first MOC iteration, solve - * the diffusion problem without correcting currents */ - if (moc_iteration == 0) - d_tilde = 0.0; - else - d_tilde = - _materials[cell]->getDifTilde()[surface*_num_cmfd_groups + e] * - (1 - _relax_factor) + _relax_factor * d_tilde; - - /* Set d_hat and d_tilde */ - _materials[cell]->setDifHatByGroup(d_hat, e+1, surface); - _materials[cell]->setDifTildeByGroup(d_tilde, e+1, surface); - - log_printf(DEBUG, "cell: %i, group: %i, side: %i, flux: %f," - " current: %f, d: %f, dhat: %f, dtilde: %f", - y*_num_x + x, e, surface, flux, current, d, d_hat, - d_tilde); - } - } + /* Increment tallies for this group */ + rxn_tally += flux * volume; + trans_tally_group += tot * flux * volume; + rxn_tally_group += flux * volume; } + + /* Energy collapse diffusion coefficient */ + dif_tally += rxn_tally_group / + (3.0 * (trans_tally_group / rxn_tally_group)); } -} + return dif_tally / rxn_tally; +} -/** @brief CMFD solver that solves the diffusion problem. - * @return k-effective the solution eigenvalue - * @param MOC iteration number +/** + * @brief Compute the surface diffusion coefficient for a given cmfd cell, + * cell surface, and group. + * @details This method uses finite differencing to compute the surface + * diffusion coefficient (\f$ \hat{D} \f$) or surface diffusion + * coefficient correction (\f$ \tilde{D} \f$) for a given cmfd cell, + * cell surface, and cmfd energy group. If the MOC iteration is zero, + * (\f$ \tilde{D} \f$) is returned as zero. Since (\f$ \hat{D} \f$) and + * (\f$ \tilde{D} \f$) are dependent on each other, they must be + * computed together; therefore, the boolean correction is used to + * indicate which value is to be returned. + * @param cmfd_cell A Cmfd cell + * @param surface A surface of the Cmfd cell + * @param group A Cmfd energy group + * @param moc_iteration MOC iteration number + * @param correction Boolean indicating whether (\f$ \hat{D} \f$) or + * (\f$ \tilde{D} \f$) is to be returned + * @return The surface diffusion coefficient, (\f$ \hat{D} \f$) or + * (\f$ \tilde{D} \f$) */ -FP_PRECISION Cmfd::computeKeff(int moc_iteration){ - - log_printf(INFO, "Running diffusion solver..."); - - /* Create matrix and vector objects */ - if (_A == NULL){ - try{ - - /* Allocate memory for matrix and vector objects */ - _M = new FP_PRECISION*[_num_x*_num_y]; - _A = new FP_PRECISION*[_num_x*_num_y]; - _old_source = new FP_PRECISION[_num_x*_num_y*_num_cmfd_groups]; - _new_source = new FP_PRECISION[_num_x*_num_y*_num_cmfd_groups]; - _volumes = new FP_PRECISION[_num_x*_num_y]; - - for (int i = 0; i < _num_x*_num_y; i++){ - _M[i] = new FP_PRECISION[_num_cmfd_groups*_num_cmfd_groups]; - _A[i] = new FP_PRECISION[_num_cmfd_groups*(_num_cmfd_groups+4)]; - } - - /* Initialize flux and materials */ - initializeFlux(); - initializeMaterials(); +FP_PRECISION Cmfd::getSurfaceDiffusionCoefficient(int cmfd_cell, int surface, + int group, int moc_iteration, + bool correction) { + + FP_PRECISION dif_surf, dif_surf_corr; + FP_PRECISION current, current_out, current_in; + FP_PRECISION flux_next; + + /* Get diffusivity and flux for Mesh cell */ + FP_PRECISION dif_coef = getDiffusionCoefficient(cmfd_cell, group); + FP_PRECISION flux = _old_flux->getValue(cmfd_cell, group); + int cmfd_cell_next = getCellNext(cmfd_cell, surface); + FP_PRECISION delta_interface = getSurfaceWidth(surface); + FP_PRECISION delta = getPerpendicularSurfaceWidth(surface); + int sense = getSense(surface); + + /* Correct the diffusion coefficient with Larsen's effective diffusion + * coefficient correction factor */ + dif_coef *= computeLarsensEDCFactor(dif_coef, delta); + + /* If surface is on a boundary, choose appropriate BC */ + if (cmfd_cell_next == -1) { + + /* REFLECTIVE BC */ + if (_boundaries[surface] == REFLECTIVE) { + dif_surf = 0.0; + dif_surf_corr = 0.0; } - catch(std::exception &e){ - log_printf(ERROR, "Could not allocate memory for the CMFD mesh objects. " - "Backtrace:%s", e.what()); - } - } - /* Initialize variables */ - FP_PRECISION sum_new, sum_old, val, residual, scale_val; - int row; + /* VACUUM BC */ + else if (_boundaries[surface] == VACUUM) { - /* Convergence criteria on L2 norm of flux for linear solve */ - FP_PRECISION linear_solve_convergence_criteria = 1E-7; - - /* Compute the cross sections and surface diffusion coefficients */ - computeXS(); - computeDs(moc_iteration); + /* Compute the surface-averaged current leaving the cell */ + current_out = sense * _surface_currents->getValue + (cmfd_cell, surface*_num_cmfd_groups + group) / delta_interface; - /* Construct matrices */ - constructMatrices(); - - /* Compute and normalize the initial source */ - matrix_multiplication(_M, _old_flux, _old_source, _num_x*_num_y, - _num_cmfd_groups); - sum_old = pairwise_sum(_old_source, _num_x*_num_y*_num_cmfd_groups); - scale_val = (_num_x * _num_y * _num_cmfd_groups) / sum_old; - vector_scale(_old_source, scale_val, _num_x*_num_y*_num_cmfd_groups); - vector_copy(_old_flux, _new_flux, _num_x*_num_y*_num_cmfd_groups); - vector_scale(_new_flux, scale_val, _num_x*_num_y*_num_cmfd_groups); - sum_old = _num_x * _num_y * _num_cmfd_groups; - - /* Power iteration diffusion solver */ - for (int iter = 0; iter < 25000; iter++){ - - /* Solve phi = A^-1 * old_source */ - linearSolve(_A, _new_flux, _old_source, linear_solve_convergence_criteria); - - /* Compute the new source */ - matrix_multiplication(_M, _new_flux, _new_source, _num_x*_num_y, - _num_cmfd_groups); - sum_new = pairwise_sum(_new_source, _num_x*_num_y*_num_cmfd_groups); - - /* Compute and set keff */ - _k_eff = sum_new / sum_old; - - /* Scale the old source by keff */ - vector_scale(_old_source, _k_eff, _num_x*_num_y*_num_cmfd_groups); - - /* Compute the L2 norm of source error */ - residual = 0.0; - for (int i = 0; i < _num_x*_num_y*_num_cmfd_groups; i++){ - if (_new_source[i] != 0.0) - residual += pow((_new_source[i] - _old_source[i]) / _new_source[i], 2); + /* Set the surface diffusion coefficient and MOC correction */ + dif_surf = 2 * dif_coef / delta / (1 + 4 * dif_coef / delta); + dif_surf_corr = (sense * dif_surf * flux - current_out) / flux; } - - /* Compute the source RMS error */ - residual = sqrt(residual / (_num_x*_num_y*_num_cmfd_groups)); - - /* Normalize the new source to have an average value of 1.0 */ - scale_val = (_num_x * _num_y * _num_cmfd_groups) / sum_new; - vector_scale(_new_source, scale_val, _num_x*_num_y*_num_cmfd_groups); - vector_copy(_new_source, _old_source, _num_x*_num_y*_num_cmfd_groups); - - log_printf(INFO, "CMFD iter: %i, keff: %f, error: %f", - iter, _k_eff, residual); - - /* Check for convergence */ - if (residual < _source_convergence_threshold && iter > 10) - break; } - /* Rescale the old and new flux */ - rescaleFlux(); + /* If surface is an interface, use finite differencing */ + else{ - /* Update the MOC flux */ - updateMOCFlux(); + /* Get the surface index for the surface in the neighboring cell */ + int surface_next = (surface + NUM_FACES / 2) % NUM_FACES; - return _k_eff; -} + /* Set diffusion coefficient and flux for the neighboring cell */ + FP_PRECISION dif_coef_next = getDiffusionCoefficient(cmfd_cell_next, group); + flux_next = _old_flux->getValue(cmfd_cell_next, group); + /* Correct the diffusion coefficient with Larsen's effective diffusion + * coefficient correction factor */ + dif_coef_next *= computeLarsensEDCFactor(dif_coef_next, delta); -/** - * @brief Solve the linear system Ax=b using Gauss Seidel with SOR. - * @param pointer to A matrix - * @param pointer to x vector - * @param pointer to b vector - * @param flux convergence criteria - * @param the maximum number of iterations - */ -void Cmfd::linearSolve(FP_PRECISION** mat, FP_PRECISION* vec_x, - FP_PRECISION* vec_b, FP_PRECISION conv, int max_iter){ - - FP_PRECISION residual = 1E10; - int row, cell; - FP_PRECISION val; - int iter = 0; - - while (iter < max_iter){ - - /* Pass new flux to old flux */ - vector_copy(vec_x, _flux_temp, _num_x*_num_y*_num_cmfd_groups); - - /* Iteration over red cells */ - #pragma omp parallel for private(row, val, cell) - for (int y = 0; y < _num_y; y++){ - for (int x = y % 2; x < _num_x; x += 2){ - - cell = y*_num_x+x; - - for (int g = 0; g < _num_cmfd_groups; g++){ - - row = cell*_num_cmfd_groups + g; - val = 0.0; - - /* Previous flux term */ - val += (1.0 - _SOR_factor) * vec_x[row]; - - /* Source term */ - val += _SOR_factor*vec_b[row] / mat[cell][g*(_num_cmfd_groups+4)+g+2]; - - /* Left surface */ - if (x != 0) - val -= _SOR_factor * vec_x[row - _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; - - /* Bottom surface */ - if (y != 0) - val -= _SOR_factor * vec_x[row - _num_x * _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)+1] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; - - /* Group-to-group */ - for (int e = 0; e < _num_cmfd_groups; e++){ - if (e != g) - val -= _SOR_factor * vec_x[cell*_num_cmfd_groups+e] * - mat[cell][g*(_num_cmfd_groups+4)+2+e] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; - } + /* Compute the surface diffusion coefficient */ + dif_surf = 2.0 * dif_coef * dif_coef_next + / (delta * dif_coef + delta * dif_coef_next); - /* Right surface */ - if (x != _num_x - 1) - val -= _SOR_factor * vec_x[row + _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)+_num_cmfd_groups+2] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; + /* Get the outward current on surface */ + current_out = _surface_currents->getValue + (cmfd_cell, surface*_num_cmfd_groups + group); - /* Top surface */ - if (y != _num_y - 1) - val -= _SOR_factor * vec_x[row + _num_cmfd_groups*_num_x] * - mat[cell][g*(_num_cmfd_groups+4)+_num_cmfd_groups+3] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; + /* Get the inward current on the surface */ + current_in = _surface_currents->getValue + (cmfd_cell_next, surface_next*_num_cmfd_groups + group); - vec_x[row] = val; - } - } - } + /* Compute the surface-averaged net current across the surface */ + current = sense * (current_out - current_in) / delta_interface; - /* Iteration over black cells */ - #pragma omp parallel for private(row, val, cell) - for (int y = 0; y < _num_y; y++){ - for (int x = 1 - y % 2; x < _num_x; x += 2){ + /* Compute the surface diffusion coefficient correction */ + dif_surf_corr = -(sense * dif_surf * (flux_next - flux) + current) + / (flux_next + flux); - cell = y*_num_x+x; + /* If the magnitude of dif_surf_corr is greater than the magnitude of + * dif_surf, select new values dif_surf_corr and dif_surf to ensure the + * coarse mesh equations are guaranteed to be diagonally dominant */ + if (fabs(dif_surf_corr) > dif_surf && moc_iteration != 0) { - for (int g = 0; g < _num_cmfd_groups; g++){ + /* Get the sign of dif_surf_corr */ + int sign = (int) round(fabs(dif_surf_corr) / dif_surf_corr); - row = cell*_num_cmfd_groups + g; - val = 0.0; + /* Compute the surface diffusion coefficient while preserving the + * the surface-averaged net current across the surface and the signs + * of the surface diffusion coefficients. */ + if (sense == sign) + dif_surf = fabs(current / (2 * flux_next)); + else + dif_surf = fabs(current / (2 * flux)); - /* Previous flux term */ - val += (1.0 - _SOR_factor) * vec_x[row]; + /* Set dif_surf_corr to have the same magnitude as dif_surf, + * but the same sign as originially computed. */ + dif_surf_corr = sign * dif_surf; + } + } - /* Source term */ - val += _SOR_factor*vec_b[row] / mat[cell][g*(_num_cmfd_groups+4)+g+2]; + /* If it is the first MOC iteration, solve the straight diffusion problem + * with no MOC correction */ + if (moc_iteration == 0) + dif_surf_corr = 0.0; - /* Left surface */ - if (x != 0) - val -= _SOR_factor * vec_x[row - _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; + /* Determine which surface diffusion coefficient is corrected */ + if (correction) + return dif_surf_corr; + else + return dif_surf; +} - /* Bottom surface */ - if (y != 0) - val -= _SOR_factor * vec_x[row - _num_x * _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)+1] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; - /* Group-to-group */ - for (int e = 0; e < _num_cmfd_groups; e++){ - if (e != g) - val -= _SOR_factor * vec_x[cell*_num_cmfd_groups+e] * - mat[cell][g*(_num_cmfd_groups+4)+2+e] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; - } +/** + * @brief Solve the nonlinear diffusion acceleration problem to accelerate the + * convergence of the MOC problem. + * @details This method uses the information from the last MOC transport sweep + * and solves a simplified nonlinear diffusion problem. The diffusion + * problem is tightly converged and the solution is used to update the + * the solution of the MOC problem. + * @param moc_iteration MOC iteration number + * @return The dominant eigenvalue of the nonlinear diffusion problem + */ +FP_PRECISION Cmfd::computeKeff(int moc_iteration) { - /* Right surface */ - if (x != _num_x - 1) - val -= _SOR_factor * vec_x[row + _num_cmfd_groups] * - mat[cell][g*(_num_cmfd_groups+4)+_num_cmfd_groups+2] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; + log_printf(INFO, "Running diffusion solver..."); - /* Top surface */ - if (y != _num_y - 1) - val -= _SOR_factor * vec_x[row + _num_cmfd_groups*_num_x] * - mat[cell][g*(_num_cmfd_groups+4)+_num_cmfd_groups+3] / - mat[cell][g*(_num_cmfd_groups+4)+g+2]; + /* Create matrix and vector objects */ + if (_A == NULL) { + log_printf(ERROR, "Unable to compute k-eff in Cmfd since the Cmfd " + "linear algebra matrices and arrays have not been created."); + } - vec_x[row] = val; - } - } - } + /* Collapse the cross sections onto the CMFD mesh */ + collapseXS(); - /* Compute the average residual */ - residual = 0.0; - for (int i = 0; i < _num_x*_num_y*_num_cmfd_groups; i++){ - if (vec_x[i] != 0.0) - residual += pow((vec_x[i] - _flux_temp[i]) / vec_x[i], 2); - } - residual = pow(residual, 0.5) / (_num_x*_num_y*_num_cmfd_groups); + /* Construct matrices */ + constructMatrices(moc_iteration); - /* Increment the interations counter */ - iter++; + /* Copy old flux to new flux */ + _old_flux->copyTo(_new_flux); - log_printf(DEBUG, "GS iter: %i, res: %f", iter, residual); + /* Solve the eigenvalue problem */ + _k_eff = eigenvalueSolve(_A, _M, _new_flux, _source_convergence_threshold, + _SOR_factor); - if (residual < conv && iter > 10) - break; - } + /* Rescale the old and new flux */ + rescaleFlux(); - log_printf(DEBUG, "linear solver iterations: %i", iter); + /* Update the MOC flux */ + updateMOCFlux(); + + return _k_eff; } /** * @brief Rescale the initial and converged flux arrays. + * @details The diffusion problem is a generalized eigenvalue problem and + * therefore the solution is independent of flux level. This method + * rescales the input flux and converged flux to both have an average + * fission source of 1.0 in each group in each cell. */ -void Cmfd::rescaleFlux(){ - - FP_PRECISION sum_new, sum_old, scale_val; +void Cmfd::rescaleFlux() { /* Rescale the new and old flux to have an avg source of 1.0 */ - matrix_multiplication(_M, _new_flux, _new_source, _num_x*_num_y, - _num_cmfd_groups); - sum_new = pairwise_sum(_new_source, _num_x*_num_y*_num_cmfd_groups); - scale_val = _num_x*_num_y*_num_cmfd_groups / sum_new; - vector_scale(_new_flux, scale_val, _num_x*_num_y*_num_cmfd_groups); - matrix_multiplication(_M, _old_flux, _old_source, _num_x*_num_y, - _num_cmfd_groups); - sum_old = pairwise_sum(_old_source, _num_x*_num_y*_num_cmfd_groups); - scale_val = _num_x*_num_y*_num_cmfd_groups / sum_old; - vector_scale(_old_flux, scale_val, _num_x*_num_y*_num_cmfd_groups); + matrixMultiplication(_M, _new_flux, _new_source); + matrixMultiplication(_M, _old_flux, _old_source); + + _new_flux->scaleByValue(_num_x*_num_y*_num_cmfd_groups / + _new_source->getSum()); + _old_flux->scaleByValue(_num_x*_num_y*_num_cmfd_groups / + _old_source->getSum()); } -/** @brief Fill in the values in the A matrix, M matrix, and old - * scalar flux vector. +/** + * @brief Construct the loss + streaming matrix (A) and the fission gain + * matrix (M) in preparation for solving the eigenvalue problem. + * @details This method loops over all mesh cells and energy groups and + * accumulates the iteraction and streaming terms into their + * approipriate positions in the loss + streaming matrix and + * fission gain matrix. */ -void Cmfd::constructMatrices(){ +void Cmfd::constructMatrices(int moc_iteration) { log_printf(INFO,"Constructing matrices..."); - - FP_PRECISION value, volume; - int cell, row; - Material* material; - + /* Zero _A and _M matrices */ - matrix_zero(_M, _num_cmfd_groups*_num_cmfd_groups, _num_x*_num_y); - matrix_zero(_A, _num_cmfd_groups*(_num_cmfd_groups+4), _num_x*_num_y); - - /* Loop over cells */ - #pragma omp parallel for private(value, volume, cell, row, material) - for (int y = 0; y < _num_y; y++){ - for (int x = 0; x < _num_x; x++){ - - cell = y*_num_x + x; - material = _materials[cell]; - volume = _volumes[cell]; + _A->clear(); + _M->clear(); - /* Loop over groups */ - for (int e = 0; e < _num_cmfd_groups; e++){ - - row = cell*_num_cmfd_groups + e; - - /* Absorption term */ - value = material->getSigmaA()[e] * volume; - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; - - /* Out (1st) and in (2nd) scattering */ - for (int g = 0; g < _num_cmfd_groups; g++){ - if (e != g){ - value = material->getSigmaS()[g*_num_cmfd_groups + e] * volume; - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; - value = - material->getSigmaS()[e*_num_cmfd_groups + g] * volume; - _A[cell][e*(_num_cmfd_groups+4)+g+2] += value; - } - } +#pragma omp parallel + { - /* RIGHT SURFACE */ - - /* Set transport term on diagonal */ - value = (material->getDifHat()[2*_num_cmfd_groups + e] - - material->getDifTilde()[2*_num_cmfd_groups + e]) - * _cell_height; - - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; - - /* Set transport term on off diagonal */ - if (x != _num_x - 1){ - value = - (material->getDifHat()[2*_num_cmfd_groups + e] - + material->getDifTilde()[2*_num_cmfd_groups + e]) - * _cell_height; - - _A[cell][e*(_num_cmfd_groups+4)+_num_cmfd_groups+2] += value; - } + FP_PRECISION value, volume, delta; + FP_PRECISION dif_surf, dif_surf_corr; + int sense; + Material* material; - /* LEFT SURFACE */ + /* Loop over cells */ +#pragma omp for + for (int i = 0; i < _num_x*_num_y; i++) { - /* Set transport term on diagonal */ - value = (material->getDifHat()[e] - + material->getDifTilde()[e]) - * _cell_height; - + material = _materials[i]; + volume = _volumes->getValue(i, 0); - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; + /* Loop over groups */ + for (int e = 0; e < _num_cmfd_groups; e++) { - /* Set transport term on off diagonal */ - if (x != 0){ - value = - (material->getDifHat()[e] - - material->getDifTilde()[e]) - * _cell_height; - - _A[cell][e*(_num_cmfd_groups+4)] += value; - } + /* Net removal term */ + value = material->getSigmaTByGroup(e+1) * volume; + _A->incrementValue(i, e, i, e, value); - /* BOTTOM SURFACE */ - - /* Set transport term on diagonal */ - value = (material->getDifHat()[1*_num_cmfd_groups + e] - + material->getDifTilde()[1*_num_cmfd_groups + e]) - * _cell_width; - - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; - - /* Set transport term on off diagonal */ - if (y != 0){ - value = - (material->getDifHat()[1*_num_cmfd_groups + e] - - material->getDifTilde()[1*_num_cmfd_groups + e]) - * _cell_width; - - _A[cell][e*(_num_cmfd_groups+4)+1] += value; + /* Scattering gain from all groups */ + for (int g = 0; g < _num_cmfd_groups; g++) { + value = - material->getSigmaSByGroup(g+1, e+1) * volume; + _A->incrementValue(i, g, i, e, value); } - /* TOP SURFACE */ - - /* Set transport term on diagonal */ - value = (material->getDifHat()[3*_num_cmfd_groups + e] - - material->getDifTilde()[3*_num_cmfd_groups + e]) - * _cell_width; - - _A[cell][e*(_num_cmfd_groups+4)+e+2] += value; - - /* Set transport term on off diagonal */ - if (y != _num_y - 1){ - value = - (material->getDifHat()[3*_num_cmfd_groups + e] - + material->getDifTilde()[3*_num_cmfd_groups + e]) - * _cell_width; - - _A[cell][e*(_num_cmfd_groups+4)+_num_cmfd_groups+3] += value; - } + /* Streaming to neighboring cells */ + for (int s = 0; s < NUM_FACES; s++) { - /* Source term */ - for (int g = 0; g < _num_cmfd_groups; g++){ - value = material->getChi()[e] * material->getNuSigmaF()[g] - * volume; + sense = getSense(s); + delta = getSurfaceWidth(s); - _M[cell][e*_num_cmfd_groups+g] += value; - } + /* Set transport term on diagonal */ + dif_surf = getSurfaceDiffusionCoefficient( + i, s, e, moc_iteration, false); + dif_surf_corr = getSurfaceDiffusionCoefficient( + i, s, e, moc_iteration, true); - log_printf(DEBUG, "cell: %i, vol; %f", cell, volume); + /* Set the diagonal term */ + value = (dif_surf - sense * dif_surf_corr) * delta; + _A->incrementValue(i, e, i, e, value); - for (int i = 0; i < _num_cmfd_groups+4; i++) - log_printf(DEBUG, "i: %i, A value: %f", - i, _A[cell][e*(_num_cmfd_groups+4)+i]); + /* Set the off diagonal term */ + if (getCellNext(i, s) != -1) { + value = - (dif_surf + sense * dif_surf_corr) * delta; + _A->incrementValue(getCellNext(i, s), e, i, e, value); + } + } - for (int i = 0; i < _num_cmfd_groups; i++) - log_printf(DEBUG, "i: %i, M value: %f", - i, _M[cell][e*(_num_cmfd_groups)+i]); + /* Fission source term */ + for (int g = 0; g < _num_cmfd_groups; g++) { + value = material->getChiByGroup(e+1) + * material->getNuSigmaFByGroup(g+1) * volume; + _M->incrementValue(i, g, i, e, value); + } } } } @@ -928,33 +670,45 @@ void Cmfd::constructMatrices(){ /** * @brief Update the MOC flux in each FSR. + * @details This method uses the condensed flux from the last MOC transport + * sweep and the converged flux from the eigenvalue problem to + * update the MOC flux in each FSR. */ -void Cmfd::updateMOCFlux(){ +void Cmfd::updateMOCFlux() { log_printf(INFO, "Updating MOC flux..."); + /* Precompute the CMFD flux ratios */ +#pragma omp parallel for + for (int i = 0; i < _num_x * _num_y; i++) { + for (int e = 0; e < _num_cmfd_groups; e++) + _flux_ratio->setValue(i, e, _new_flux->getValue(i, e) + / _old_flux->getValue(i, e)); + } + /* Loop over mesh cells */ - #pragma omp parallel for - for (int i = 0; i < _num_x*_num_y; i++){ +#pragma omp parallel for + for (int i = 0; i < _num_x * _num_y; i++) { std::vector::iterator iter; /* Loop over CMFD groups */ - for (int e = 0; e < _num_cmfd_groups; e++){ + for (int e = 0; e < _num_cmfd_groups; e++) { - for (int h = _group_indices[e]; h < _group_indices[e+1]; h++){ + /* Loop over FRSs in mesh cell */ + for (iter = _cell_fsrs.at(i).begin(); + iter != _cell_fsrs.at(i).end(); ++iter) { - /* Loop over FRSs in mesh cell */ - for (iter = _cell_fsrs.at(i).begin(); - iter != _cell_fsrs.at(i).end(); ++iter) { + FP_PRECISION update_ratio = getUpdateRatio(i, e, *iter); + + for (int h = _group_indices[e]; h < _group_indices[e + 1]; h++) { - /* Set new flux in FSR */ - _FSR_fluxes[*iter*_num_moc_groups+h] = getFluxRatio(i,h) - * _FSR_fluxes[*iter*_num_moc_groups+h]; + /* Update FSR flux using ratio of old and new CMFD flux */ + _FSR_fluxes[*iter*_num_moc_groups + h] = update_ratio + * _FSR_fluxes[*iter*_num_moc_groups + h]; - log_printf(DEBUG, "Updating flux in FSR: %i, cell: %i, group: " - "%i, ratio: %f", *iter ,i, h, - getFluxRatio(i,h)); + log_printf(DEBUG, "Updating flux in FSR: %d, cell: %d, MOC group: " + "%d, CMFD group: %d, ratio: %f", *iter ,i, h, e, update_ratio); } } } @@ -963,75 +717,98 @@ void Cmfd::updateMOCFlux(){ /** - * @brief Compute diffusion correction factors to correct diffusion - * coefficients in optically thick mesh cells. - * @param old diffusion coefficient - * @param height of cell - * @return correction factor - */ -FP_PRECISION Cmfd::computeDiffCorrect(FP_PRECISION d, FP_PRECISION h){ - - if (_optically_thick){ - - /* Initialize variables */ - FP_PRECISION alpha, mu, expon; - FP_PRECISION rho, F; - rho = 0.0; - - /* Loop over polar angles */ - for (int p = 0; p < _quad->getNumPolarAngles(); p++){ - mu = cos(asin(_quad->getSinTheta(p))); - expon = exp(- h / (3 * d * mu)); - alpha = (1 + expon) / (1 - expon) - 2 * (3 * d * mu) / h; - rho += mu * _quad->getWeight(p) * alpha; - } - - /* Compute correction factor, F */ - F = 1.0 + h * rho / (2 * d); + * @brief Compute Larsen's effective diffusion coefficient correction factor. + * @details By conserving reaction and leakage rates within cells, CMFD + * guarantees preservation of area-averaged scalar fluxes and net + * surface currents from the MOC fixed source iteration if the CMFD + * equations can be converged. However, when the MOC mesh cell size + * becomes significantly larger than the neutron mean free path in that + * cell, the step characteristics no longer preserve the linear + * infinite medium solution to the transport equation. While the + * surface diffusion coefficient correction term in CMFD is guaranteed + * to preserve reaction rates and surface net currents for any choice + * of diffusion coefficient, convergence (and convergence rate) of the + * nonlinear iteration acceleration of CMFD is affected by the choice + * of diffusion coefficient. All flat source methods, when applied for + * thick optical meshes, artificially distribute neutrons in space. + * This is the reason that Larsen’s effective diffusion coefficient is + * useful in assuring that the CMFD acceleration equations have a + * diffusion coefficient (on the flux gradient term) that is + * consistent, not with the physical transport problem, but with the + * transport problem that is being accelerated by the CMFD equations. + * Larsen’s effective diffusion coefficient is precisely this term in + * the one-dimensional limit. The following publications provide + * further background on how this term is derived and used: + * + * [1] E. Larsen, "Infinite Medium Solutions to the transport + * equation, Sn discretization schemes, and the diffusion + * approximation", M&C 2001. + * [2] S. Shaner, "Transient Method of Characteristics via the + * Adiabatic, Theta, and Multigrid Amplitude Function Methods", + * Masters Thesis, MIT 2014. + * @param dif_coef Diffusion coefficient before applying correction factor + * @param delta Width of the cell in the direction of interest + * @return The diffusion coefficient correction factor + */ +FP_PRECISION Cmfd::computeLarsensEDCFactor(FP_PRECISION dif_coef, + FP_PRECISION delta) { - return F; + /* Initialize variables */ + FP_PRECISION alpha, mu, expon; + FP_PRECISION rho = 0.0; + + /* Loop over polar angles */ + for (int p = 0; p < _num_polar; p++) { + mu = cos(asin(_polar_quad->getSinTheta(p))); + expon = exp(-delta / (3 * dif_coef * mu)); + alpha = (1 + expon) / (1 - expon) - 2 * (3 * dif_coef * mu) / delta; + rho += mu * _polar_quad->getWeight(p) * alpha; } - else - return 1.0; + + /* Compute the correction factor */ + FP_PRECISION correction = 1.0 + delta * rho / (2 * dif_coef); + + return correction; } /** * @brief Set the FSR materials array pointer. - * @param pointer to FSR_materials array + * @param FSR_materials Pointer to FSR_materials array */ -void Cmfd::setFSRMaterials(Material** FSR_materials){ +void Cmfd::setFSRMaterials(Material** FSR_materials) { _FSR_materials = FSR_materials; } /** * @brief Set the pointer to the array of FSR_volumes. - * @param array of FSR volumes + * @param FSR_volumes Array of FSR volumes */ -void Cmfd::setFSRVolumes(FP_PRECISION* FSR_volumes){ +void Cmfd::setFSRVolumes(FP_PRECISION* FSR_volumes) { _FSR_volumes = FSR_volumes; } /** * @brief Set pointer to FSR flux array. - * @param pointer to FSR flux array + * @param scalar_flux Pointer to FSR flux array */ -void Cmfd::setFSRFluxes(FP_PRECISION* scalar_flux){ +void Cmfd::setFSRFluxes(FP_PRECISION* scalar_flux) { _FSR_fluxes = scalar_flux; } /** - * @brief Set successive over-relaxation relaxation factor. - * @param over-relaxation factor + * @brief Set the successive over-relaxation factor for the + * linear solve within the diffusion eigenvalue solve. + * @param SOR_factor Over-relaxation factor */ -void Cmfd::setSORRelaxationFactor(FP_PRECISION SOR_factor){ +void Cmfd::setSORRelaxationFactor(FP_PRECISION SOR_factor) { if (SOR_factor <= 0.0 || SOR_factor >= 2.0) - log_printf(ERROR, "The successive over-relaxation relaxation factor " - "must be > 0 and < 2. Input value: %i", SOR_factor); + log_printf(ERROR, "The successive over-relaxation factor " + "must be > 0 and < 2. Input value: %d", SOR_factor); _SOR_factor = SOR_factor; } @@ -1039,119 +816,115 @@ void Cmfd::setSORRelaxationFactor(FP_PRECISION SOR_factor){ /** * @brief Get the number of coarse CMFD energy groups. - * @return the number of CMFD energy groups + * @return The number of CMFD energy groups */ -int Cmfd::getNumCmfdGroups(){ +int Cmfd::getNumCmfdGroups() { return _num_cmfd_groups; } /** * @brief Get the CMFD group given an MOC group. - * @param group the MOC energy group - * @return the CMFD energy group + * @param group The MOC energy group + * @return The CMFD energy group */ -int Cmfd::getCmfdGroup(int group){ +int Cmfd::getCmfdGroup(int group) { return _group_indices_map[group]; } /** - * @brief Set the CMFD energy group structure. - * @details CMFD does not necessarily need to have the same energy group - * structure as the MOC problem. This function can be used to set + * @brief Set the CMFD energy group structure. + * @details CMFD does not necessarily need to have the same energy group + * structure as the MOC problem. This function can be used to set * a sparse energy group structure to speed up the CMFD solve. - * @param an array of the CMFD group boundaries - * @param the length of the group_indices array + * @param group_indices An array of the CMFD group boundaries + * @param length_group_indices The length of the group_indices array */ -void Cmfd::setGroupStructure(int* group_indices, int length_group_indices){ - +void Cmfd::setGroupStructure(int* group_indices, int length_group_indices) { + _num_cmfd_groups = length_group_indices - 1; - /* Allocate memory */ - if (_group_indices == NULL){ - _group_indices = new int[length_group_indices]; - } - - if (group_indices == NULL){ - for (int i = 0; i < length_group_indices; i++){ + /* Delete old group indices array if it exists */ + if (_group_indices != NULL) + delete [] _group_indices; + + /* Allocate memory for new group indices */ + _group_indices = new int[length_group_indices]; + + if (group_indices == NULL) { + for (int i = 0; i < length_group_indices; i++) { _group_indices[i] = i; } } else{ if (group_indices[0] != 1) - log_printf(ERROR, "The first value in group indices must be 1!"); + log_printf(ERROR, "The first value in group indices must be 1!"); /* Set first group indice to 0 */ _group_indices[0] = 0; - + /* Set MOC group bounds for rest of CMFD energy groups */ - for (int i = 1; i < length_group_indices; i++){ + for (int i = 1; i < length_group_indices; i++) { /* Check that the group indices are always increasing */ if (group_indices[i] <= group_indices[i-1]) log_printf(ERROR, "The group indices must be increasing!"); - + _group_indices[i] = group_indices[i] - 1; - log_printf(INFO, "group indices %i: %i", i, group_indices[i]); + log_printf(INFO, "group indices %d: %d", i, group_indices[i]); } } -} - - -/** - * @brief Initialize the flux arrays. - */ -void Cmfd::initializeFlux(){ - - /* Allocate memory for fluxes and volumes */ - try{ - _new_flux = new FP_PRECISION[_num_x*_num_y*_num_cmfd_groups]; - _old_flux = new FP_PRECISION[_num_x*_num_y*_num_cmfd_groups]; - _flux_temp = new FP_PRECISION[_num_x*_num_y*_num_cmfd_groups]; - } - catch(std::exception &e){ - log_printf(ERROR, "Could not allocate memory for the Mesh cell fluxes, " - "lengths, and volumes. Backtrace:%s", e.what()); - } - /* Set initial Mesh cell flux to 1.0 and allocate memory for FSR vectors */ - for (int y = 0; y < _num_y; y++){ - for (int x = 0; x < _num_x; x++){ - for (int g = 0; g < _num_cmfd_groups; g++){ - _new_flux[(y*_num_x+x)*_num_cmfd_groups + g] = 1.0; - _old_flux[(y*_num_x+x)*_num_cmfd_groups + g] = 1.0; - _flux_temp[(y*_num_x+x)*_num_cmfd_groups + g] = 1.0; - } - } - } + _user_group_indices = true; } /** * @brief Initialize the CMFD materials. */ -void Cmfd::initializeMaterials(){ +void Cmfd::initializeMaterials() { Material* material; + /* Delete old Cmfd surface currents vector if it exists */ + if (_materials != NULL) + delete [] _materials; + try{ _materials = new Material*[_num_x*_num_y]; - for (int y = 0; y < _num_y; y++){ - for (int x = 0; x < _num_x; x++){ - material = new Material(y*_num_x+x); + for (int y = 0; y < _num_y; y++) { + for (int x = 0; x < _num_x; x++) { + material = new Material(y*_num_x + x); material->setNumEnergyGroups(_num_cmfd_groups); - _materials[y*_num_x+x] = material; + _materials[y*_num_x + x] = material; } } } - catch(std::exception &e){ + catch(std::exception &e) { log_printf(ERROR, "Could not allocate memory for the Mesh cell materials. " "Backtrace:%s", e.what()); } } +/** + * @brief Initializes Cmfd surface currents Vector prior to first MOC iteration. + */ +void Cmfd::initializeCurrents() { + + /* Delete old Cmfd surface currents vector if it exists */ + if (_surface_currents != NULL) + delete _surface_currents; + + /* Allocate memory for the Cmfd Mesh surface currents Vectors */ + _surface_currents = new Vector(_cell_locks, _num_x, _num_y, + _num_cmfd_groups * NUM_SURFACES); + + return; +} + + /** * @brief Initializes the vector of vectors that links CMFD cells with FSRs. * @details This method is called by the geometry once the CMFD mesh has been @@ -1159,14 +932,12 @@ void Cmfd::initializeMaterials(){ * each CMFD cell that is used to store the FSR ids contained within * that cell. */ -void Cmfd::initializeCellMap(){ +void Cmfd::initializeCellMap() { /* Allocate memory for mesh cell FSR vectors */ - for (int y = 0; y < _num_y; y++){ - for (int x = 0; x < _num_x; x++){ - std::vector *fsrs = new std::vector; - _cell_fsrs.push_back(*fsrs); - } + for (int y = 0; y < _num_y; y++) { + for (int x = 0; x < _num_x; x++) + _cell_fsrs.push_back(std::vector()); } } @@ -1175,20 +946,28 @@ void Cmfd::initializeCellMap(){ * @brief Initialize and set array that links the MOC energy groups to the * CMFD energy groups. * @details This method initializes the _group_indices_map, which is a 1D array - * of length _num_moc_groups that maps the MOC energy groups to CMFD - * energy groups. The indices into _group_indices_map are the MOC - * energy groups and the values are the CMFD energy groups. + * of length _num_moc_groups that maps the MOC energy groups to CMFD + * energy groups. The indices into _group_indices_map are the MOC + * energy groups and the values are the CMFD energy groups. */ -void Cmfd::initializeGroupMap(){ +void Cmfd::initializeGroupMap() { + + /* Setup one-to-one fine-to-coarse group map if not specified by user */ + if (!_user_group_indices) { + setGroupStructure(NULL, _num_moc_groups+1); + _user_group_indices = false; + } + + /* Delete old group indices map if it exists */ + if (_group_indices_map != NULL) + delete [] _group_indices_map; + + /* Allocate memory for new group indices map */ + _group_indices_map = new int[_num_moc_groups]; - /* Allocate memory */ - if (_group_indices_map == NULL){ - _group_indices_map = new int[_num_moc_groups]; - } - /* Create group indices map */ - for (int e = 0; e < _num_cmfd_groups; e++){ - for (int h = _group_indices[e]; h < _group_indices[e+1]; h++){ + for (int e = 0; e < _num_cmfd_groups; e++) { + for (int h = _group_indices[e]; h < _group_indices[e + 1]; h++) { _group_indices_map[h] = e; } } @@ -1199,53 +978,44 @@ void Cmfd::initializeGroupMap(){ /** * @brief Find the cmfd surface that a LocalCoords object lies on. * @details If the coords is not on a surface, -1 is returned. Otherwise, - * the surface ID is returned. - * @param The CMFD cell ID that the local coords is in. - * @param The coords being evaluated. + * the surface ID is returned. + * @param cell_id The CMFD cell ID that the local coords is in. + * @param coords The coords being evaluated. * @return The surface ID. */ -int Cmfd::findCmfdSurface(int cell, LocalCoords* coords){ +int Cmfd::findCmfdSurface(int cell_id, LocalCoords* coords) { Point* point = coords->getHighestLevel()->getPoint(); - return _lattice->getLatticeSurface(cell, point); + return _lattice->getLatticeSurface(cell_id, point); } /** - * @brief Find the CMFD cell that a LocalCoords object is in. - * @param The coords being evaluated. + * @brief Find the CMFD cell that a LocalCoords object is in. + * @param coords The coords being evaluated. * @return The CMFD cell ID. */ -int Cmfd::findCmfdCell(LocalCoords* coords){ +int Cmfd::findCmfdCell(LocalCoords* coords) { Point* point = coords->getHighestLevel()->getPoint(); return _lattice->getLatticeCell(point); } -/** - * @brief The Lattice object used as the CMFD mesh. - * @param Pointer to the lattice object. - */ -void Cmfd::setLattice(Lattice* lattice){ - _lattice = lattice; -} - - /** * @brief The structure of the Lattice to be used as the CMFD mesh. - * @param The number of cells in the x direction. - * @param The number of cells in the y direction. + * @param num_x The number of cells in the x direction. + * @param num_y The number of cells in the y direction. */ -void Cmfd::setLatticeStructure(int num_x, int num_y){ +void Cmfd::setLatticeStructure(int num_x, int num_y) { setNumX(num_x); setNumY(num_y); } /** - * @brief Returns the Lattice object used as the CMFD mesh. + * @brief Returns the Lattice object used as the CMFD mesh. * @return A pointer to a Lattice object. */ -Lattice* Cmfd::getLattice(){ +Lattice* Cmfd::getLattice() { return _lattice; } @@ -1253,367 +1023,292 @@ Lattice* Cmfd::getLattice(){ /** * @brief Add an FSR ID to a vector that contains all the FSR IDs * contained within a CMFD mesh cell. - * @param The CMFD cell ID. - * @param The FSR ID. + * @param cell_id The CMFD cell ID. + * @param fsr_id The FSR ID. */ -void Cmfd::addFSRToCell(int cmfd_cell, int fsr_id){ - _cell_fsrs.at(cmfd_cell).push_back(fsr_id); +void Cmfd::addFSRToCell(int cell_id, int fsr_id) { + _cell_fsrs.at(cell_id).push_back(fsr_id); } /** * @brief Set the number of MOC energy groups. - * @param number of MOC energy groups + * @param num_groups Number of MOC energy groups */ -void Cmfd::setNumMOCGroups(int num_groups){ +void Cmfd::setNumMOCGroups(int num_groups) { _num_moc_groups = num_groups; } /** * @brief Get the number of MOC energy groups. - * @return the number of MOC energy groups + * @return The number of MOC energy groups */ -int Cmfd::getNumMOCGroups(){ +int Cmfd::getNumMOCGroups() { return _num_moc_groups; } /** * @brief Get the number of CMFD cells. - * @return the number of CMFD cells + * @return The number of CMFD cells */ -int Cmfd::getNumCells(){ - return _num_x*_num_y; +int Cmfd::getNumCells() { + return _num_x * _num_y; } /** - * @brief Set the pointer to the Mesh surface currents array. - * @param pointer to the surface currents array + * @brief Set the number of FSRs. + * @param num_fsrs The number of FSRs */ -void Cmfd::setSurfaceCurrents(FP_PRECISION* surface_currents){ - _surface_currents = surface_currents; +void Cmfd::setNumFSRs(int num_fsrs) { + _num_FSRs = num_fsrs; } /** - * @brief set the number of FSRs. - * @param the number of FSRs + * @brief Split the currents of the Mesh cell edges to the adjacent faces. + * @details This method takes the currents tallied across the edges (or corners) + * of a cmfd cell and splits them evenly across the adjacent faces + * (locations 1 and 2). In order to transport the current through to + * the diagonal cell, the current is also tallied on the surfaces of + * the adjacent cells (locations 3 and 4). Essentially, the tracks that + * cross through edges are split into two half-weight tracks as shown + * in the illustration below: + * + * | / + * | __/_ + * |/ / + * 3 / / + * /| / 4 + * ------------------/-+-/------------------ + * 1 / |/ + * / / 2 + * /___/| + * / | + * / | + * */ -void Cmfd::setNumFSRs(int num_fsrs){ - _num_FSRs = num_fsrs; -} - +void Cmfd::splitEdgeCurrents() { -/** @brief Split the currents of the Mesh cell corners to the nearby surfaces. - * @details left bottom corner -> bottom surface and left surface - * of mesh cell below; right bottom corner -> bottom surface - * and right surface of mesh cell below; right top corner -> - * right surface and top surface of mesh cell to the right; - * left top corner -> left surface and top surface of mesh - * cell to the left. The currents tallied on a corner is split - * equally to the adjoining surfaces. - */ -void Cmfd::splitCorners(){ + log_printf(INFO, "Splitting CMFD edge currents..."); - log_printf(INFO, "splitting corners..."); - int ncg = _num_cmfd_groups; + int nf = NUM_FACES; + int ne = NUM_EDGES; + int ns = NUM_SURFACES; - for (int x = 0; x < _num_x; x++){ - for (int y = 0; y < _num_y; y++){ - - /* Split the LEFT BOTTOM CORNER */ - - /* If cell is not on left or bottom geometry edge - * give to bottom surface and left surface of mesh cell below */ - if (x > 0 && y > 0){ - - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[((y-1)*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[(y*_num_x+x-1)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - } - } - /* If cell is on left geometry edge - * give to bottom surface and left surfaces */ - else if (x == 0 && y != 0){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[((y-1)*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - } - } - /* If cell is on bottom geometry edge - * give to bottom surface and left surfaces */ - else if (x != 0 && y == 0){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - _surface_currents[(y*_num_x+x-1)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e]; - } - } - - /* Split the RIGHT BOTTOM CORNER */ - - /* If cell is not on right or bottom geometry edge - * give to bottom surface and right surface of mesh cell below */ - if (x < _num_x - 1 && y > 0){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[((y-1)*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[(y*_num_x+x+1)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - } - } - /* If cell is on right geometry edge - * give to bottom surface and right surface */ - else if (x == _num_x - 1 && y > 0){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[((y-1)*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - } - } - /* If cell is on bottom geometry edge - * give to bottom surface and right surface */ - else if (x < _num_x - 1 && y == 0){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT BOTTOM current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - _surface_currents[(y*_num_x+x+1)*ncg*8 + 1*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e]; - } - } - - /* Split the RIGHT TOP CORNER */ - - /* If cell is not on right or top geometry edge - * give to right surface and top surface of mesh cell to the right */ - if (x < _num_x - 1 && y < _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[(y*_num_x+x+1)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[((y+1)*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - } - } - /* If cell is on right geometry edge - * give to right surface and top surface */ - else if (x == _num_x - 1 && y != _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[((y+1)*_num_x+x)*ncg*8 + 2*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - } - } - /* If cell is on top geometry edge - * give to right surface and top surface */ - else if (x != _num_x - 1 && y == _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, RIGHT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + 2*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - _surface_currents[(y*_num_x+x+1)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e]; - } - } - - /* Split the LEFT TOP CORNER */ - - /* If cell is not on left or top geometry edge - * give to left surface and top surface of mesh cell to the left */ - if (x > 0 && y < _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[(y*_num_x+x-1)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[((y+1)*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - } - } - /* If cell is on left geometry edge - * give to top surface and left surface */ - else if (x == 0 && y != _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[((y+1)*_num_x+x)*ncg*8 + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - } - } - /* If cell is on top geometry edge - * give to top surface and left surface */ - else if (x != 0 && y == _num_y - 1){ - for (int e = 0; e < ncg; e++){ - log_printf(DEBUG, "cell: %i, group: %i, LEFT TOP current: %f", - y*_num_x+x,e, _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]); - _surface_currents[(y*_num_x+x)*ncg*8 + e] += - _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[(y*_num_x+x)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; - _surface_currents[(y*_num_x+x-1)*ncg*8 + 3*ncg + e] += - 0.5 * _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e]; +#pragma omp parallel + { + + FP_PRECISION current; + std::vector surfaces; + std::vector::iterator iter; + int cell, surface; + +#pragma omp for + for (int i = 0; i < _num_x * _num_y; i++) { + for (int e = nf - 1; e < nf + ne; e++) { + + /* Get the surfaces to split this edge's current to */ + getEdgeSplitSurfaces(i, e, &surfaces); + + for (int g=0; g > ncg; g++) { + /* Divide edge current by 2 since we will split to 2 surfaces, + * which propagate through 2 surfaces */ + current = _surface_currents->getValue(i, e * ncg + g) / 2; + + /* Increment current for faces adjacent to this edge */ + for (iter = surfaces.begin(); iter != surfaces.end(); ++iter) { + cell = (*iter) / ns; + surface = (*iter) % ns; + _surface_currents->incrementValue(cell, surface * ncg + g, current); + } } } - - for (int e = 0; e < ncg; e++){ - _surface_currents[(y*_num_x+x)*ncg*8 + 4*ncg + e] = 0.0; - _surface_currents[(y*_num_x+x)*ncg*8 + 5*ncg + e] = 0.0; - _surface_currents[(y*_num_x+x)*ncg*8 + 6*ncg + e] = 0.0; - _surface_currents[(y*_num_x+x)*ncg*8 + 7*ncg + e] = 0.0; - } } } } /** - * @brief Get the ID of the Mesh cell next to given Mesh cell. - * @param current Mesh cell ID - * @param CMFD cell surface ID to look across for neighboring cell - * @return neighboring CMFD cell ID + * @brief Get the faces to split the currents of the Mesh cell edges. + * @details The process by which the current of tracks passing through edges + * is split is described in the comment for Cmfd::splitEdgeCurrents(). + * This method takes in the cell and edge that is being split as well + * as a std::vector used to store the IDs of surfaces that are crossed + * by the partial-weight tracks. This method properly accounts for + * crossings on the geometry boundaries by applying the corresponding + * boundary conditions to split the currents. + * @param cell The CMFD cell ID that the edge is in. + * @param edge The edge that the track crosses through. + * @param surfaces A std::vector that is populated with the IDs of surfaces that + * are crossed by partial-weight tracks. */ -int Cmfd::getCellNext(int cell_num, int surface_id){ - - int cell_next = -1; - - if (surface_id == 0){ - if (cell_num % _num_x != 0) - cell_next = cell_num - 1; +void Cmfd::getEdgeSplitSurfaces(int cell, int edge, + std::vector* surfaces) { + + surfaces->clear(); + int x = cell % _num_x; + int y = cell / _num_x; + int ns = NUM_SURFACES; + + if (edge == SURFACE_X_MIN_Y_MIN) { + surfaces->push_back(cell * ns + SURFACE_X_MIN); + surfaces->push_back(cell * ns + SURFACE_Y_MIN); + + if (x == 0) { + if (_boundaries[SURFACE_X_MIN] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_Y_MIN); + else if (_boundaries[SURFACE_X_MIN] == PERIODIC) + surfaces->push_back((cell + (_num_x - 1))* ns + SURFACE_Y_MIN); + } + else + surfaces->push_back((cell - 1) * ns + SURFACE_Y_MIN); + + if (y == 0) { + if (_boundaries[SURFACE_Y_MIN] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_X_MIN); + else if (_boundaries[SURFACE_Y_MIN] == PERIODIC) + surfaces->push_back((cell + _num_x * (_num_y - 1)) * ns + + SURFACE_X_MIN); + } + else + surfaces->push_back((cell - _num_x) * ns + SURFACE_X_MIN); } - - else if (surface_id == 1){ - if (cell_num / _num_x != 0) - cell_next = cell_num - _num_x; + else if (edge == SURFACE_X_MAX_Y_MIN) { + surfaces->push_back(cell * ns + SURFACE_X_MAX); + surfaces->push_back(cell * ns + SURFACE_Y_MIN); + + if (x == _num_x - 1) { + if (_boundaries[SURFACE_X_MAX] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_Y_MIN); + else if (_boundaries[SURFACE_X_MAX] == PERIODIC) + surfaces->push_back((cell - (_num_x - 1))* ns + SURFACE_Y_MIN); + } + else + surfaces->push_back((cell + 1) * ns + SURFACE_Y_MIN); + + if (y == 0) { + if (_boundaries[SURFACE_Y_MIN] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_X_MAX); + else if (_boundaries[SURFACE_Y_MIN] == PERIODIC) + surfaces->push_back((cell + _num_x * (_num_y - 1)) * ns + + SURFACE_X_MAX); + } + else + surfaces->push_back((cell - _num_x) * ns + SURFACE_X_MAX); } - - else if (surface_id == 2){ - if (cell_num % _num_x != _num_x - 1) - cell_next = cell_num + 1; + else if (edge == SURFACE_X_MIN_Y_MAX) { + surfaces->push_back(cell * ns + SURFACE_X_MIN); + surfaces->push_back(cell * ns + SURFACE_Y_MAX); + + if (x == 0) { + if (_boundaries[SURFACE_X_MIN] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_Y_MAX); + else if (_boundaries[SURFACE_X_MIN] == PERIODIC) + surfaces->push_back((cell + (_num_x - 1))* ns + SURFACE_Y_MAX); + } + else + surfaces->push_back((cell - 1) * ns + SURFACE_Y_MAX); + + if (y == _num_y - 1) { + if (_boundaries[SURFACE_Y_MAX] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_X_MIN); + else if (_boundaries[SURFACE_Y_MAX] == PERIODIC) + surfaces->push_back((cell - _num_x * (_num_y - 1)) * ns + + SURFACE_X_MIN); + } + else + surfaces->push_back((cell + _num_x) * ns + SURFACE_X_MIN); } - - else if (surface_id == 3){ - if (cell_num / _num_x != _num_y - 1) - cell_next = cell_num + _num_x; + else if (edge == SURFACE_X_MAX_Y_MAX) { + surfaces->push_back(cell * ns + SURFACE_X_MAX); + surfaces->push_back(cell * ns + SURFACE_Y_MAX); + + if (x == _num_x - 1) { + if (_boundaries[SURFACE_X_MAX] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_Y_MAX); + else if (_boundaries[SURFACE_X_MAX] == PERIODIC) + surfaces->push_back((cell - (_num_x - 1))* ns + SURFACE_Y_MAX); + } + else + surfaces->push_back((cell + 1) * ns + SURFACE_Y_MAX); + + if (y == _num_y - 1) { + if (_boundaries[SURFACE_Y_MAX] == REFLECTIVE) + surfaces->push_back(cell * ns + SURFACE_X_MAX); + else if (_boundaries[SURFACE_Y_MAX] == PERIODIC) + surfaces->push_back((cell - _num_x * (_num_y - 1)) * ns + + SURFACE_X_MAX); + } + else + surfaces->push_back((cell + _num_x) * ns + SURFACE_X_MAX); } - - return cell_next; } /** - * @brief Return whether optically thick diffusion correction factor is in use. - * @return whether optically thick diffusion correction factor is in use. + * @brief Get the ID of the Mesh cell next to a given Mesh cell across a + * given surface. + * @param cell_id Current Mesh cell ID + * @param surface_id CMFD cell surface ID to look across for neighboring cell + * @return Neighboring CMFD cell ID */ -bool Cmfd::isOpticallyThick(){ - return _optically_thick; -} +int Cmfd::getCellNext(int cell_id, int surface_id) { + int cell_next_id = -1; + int x = cell_id % _num_x; + int y = cell_id / _num_x; -/** - * @brief Set whether optically thick diffusion correction factor is in use. - * @param boolean indicating whether optically thick diffusion - * correction factor is in use. - */ -void Cmfd::setOpticallyThick(bool optically_thick){ - _optically_thick = optically_thick; -} - - -/** - * @brief Return the under-relaxation factor used in MOC updates. - * @return the MOC current under-relaxation factor - */ -FP_PRECISION Cmfd::getMOCRelaxationFactor(){ - return _relax_factor; -} - + if (surface_id == SURFACE_X_MIN) { + if (x != 0) + cell_next_id = cell_id - 1; + else if (_boundaries[SURFACE_X_MIN] == PERIODIC) + cell_next_id = cell_id + (_num_x - 1); + } + else if (surface_id == SURFACE_Y_MIN) { + if (y != 0) + cell_next_id = cell_id - _num_x; + else if (_boundaries[SURFACE_Y_MIN] == PERIODIC) + cell_next_id = cell_id + _num_x * (_num_y - 1); + } + else if (surface_id == SURFACE_X_MAX) { + if (x != _num_x - 1) + cell_next_id = cell_id + 1; + else if (_boundaries[SURFACE_X_MAX] == PERIODIC) + cell_next_id = cell_id - (_num_x - 1); + } + else if (surface_id == SURFACE_Y_MAX) { + if (y != _num_y - 1) + cell_next_id = cell_id + _num_x; + else if (_boundaries[SURFACE_Y_MAX] == PERIODIC) + cell_next_id = cell_id - _num_x * (_num_y - 1); + } -/** - * @brief Set the under-relaxation factor used in MOC updates. - * @param the MOC current under-relaxation factor - */ -void Cmfd::setMOCRelaxationFactor(FP_PRECISION relax_factor){ - _relax_factor = relax_factor; + return cell_next_id; } /** * @brief Set the CMFD boundary type for a given surface. - * @details The CMFD boundary is assumed to be rectangular with 4 - * boundary surfaces. The surfaces UIDs are 0 (left), - * 1 (bottom), 2 (right), and 3 (top). - * @param the CMFD surface UID. - * @param the boundaryType of the surface. + * @details The CMFD boundary is assumed to be rectangular with the + * surfaces identified by constants in the constants.h file. + * @param side The CMFD surface UID. + * @param boundary The boundaryType of the surface. */ -void Cmfd::setBoundary(int side, boundaryType boundary){ +void Cmfd::setBoundary(int side, boundaryType boundary) { _boundaries[side] = boundary; } /** * @brief Get the boundaryType for one side of the CMFD mesh. - * @param the CMFD mesh surface ID. - * @return the boundaryType for the surface. + * @param side The CMFD mesh surface ID. + * @return The boundaryType for the surface. */ -int Cmfd::getBoundary(int side){ +int Cmfd::getBoundary(int side) { return _boundaries[side]; } @@ -1621,71 +1316,101 @@ int Cmfd::getBoundary(int side){ /** * @brief Return the CMFD cell ID that an FSR lies in. * @details Note that a CMFD cell is not an actual Cell object; rather, a CMFD - * cell is just a way of describing each of the rectangular regions - * that make up a CMFD lattice. CMFD cells are numbered with 0 in the - * lower left corner and monotonically increasing from left to right. - * from left to right. For example, he indices for a 4 x 4 lattice are: + * cell is just a way of describing each of the rectangular regions + * that make up a CMFD lattice. CMFD cells are numbered with 0 in the + * lower left corner and monotonically increasing from left to right + * and from bottom to top. For example, the indices for a 4 x 4 + * lattice are: * 12 13 14 15 * 8 9 10 11 * 4 5 6 7 * 0 1 2 3 - * @param The FSR ID. + * @param fsr_id The FSR ID. * @return The CMFD cell ID. Return -1 if cell is not found. */ -int Cmfd::convertFSRIdToCmfdCell(int fsr_id){ +int Cmfd::convertFSRIdToCmfdCell(int fsr_id) { - std::vector::iterator iter; - for (int cell=0; cell < _num_x*_num_y; cell++){ + std::vector::iterator iter; + for (int cell_id=0; cell_id < _num_x * _num_y; cell_id++) { - for (iter = _cell_fsrs.at(cell).begin(); - iter != _cell_fsrs.at(cell).end(); ++iter){ - if (*iter == fsr_id) - return cell; - } + for (iter = _cell_fsrs.at(cell_id).begin(); + iter != _cell_fsrs.at(cell_id).end(); ++iter) { + if (*iter == fsr_id) + return cell_id; + } } - return -1; + return -1; } /** - * @brief Return a pointer to the vector of vectors that contains + * @brief Return a pointer to the vector of vectors that contains * the FSRs that lie in each cell. * @return Vector of vectors containing FSR IDs in each cell. */ -std::vector< std::vector > Cmfd::getCellFSRs(){ - return _cell_fsrs; +std::vector< std::vector >* Cmfd::getCellFSRs() { + return &_cell_fsrs; } - + /** - * @brief Set the vector of vectors that contains. - * the FSRs that lie in each cell. - * @param Vector of vectors containing FSR IDs in each cell. + * @brief Set the vector of vectors that contains the FSRs that lie in + * each cell. + * @param cell_fsrs Vector of vectors containing FSR IDs in each cell. */ -void Cmfd::setCellFSRs(std::vector< std::vector > cell_fsrs){ - _cell_fsrs = cell_fsrs; +void Cmfd::setCellFSRs(std::vector< std::vector >* cell_fsrs) { + + if (!_cell_fsrs.empty()) { + std::vector< std::vector >::iterator iter; + for (iter = _cell_fsrs.begin(); iter != _cell_fsrs.end(); ++iter) + iter->clear(); + _cell_fsrs.clear(); + } + + _cell_fsrs = *cell_fsrs; } /** * @brief Set flag indicating whether to update the MOC flux. - * @param Flag saying whether to update MOC flux. + * @param flux_update_on Boolean saying whether to update MOC flux. */ -void Cmfd::setFluxUpdateOn(bool flux_update_on){ +void Cmfd::setFluxUpdateOn(bool flux_update_on) { _flux_update_on = flux_update_on; } /** * @brief Get flag indicating whether to update the MOC flux. - * @return Flag saying whether to update MOC flux. + * @return Boolean saying whether to update MOC flux. */ -bool Cmfd::isFluxUpdateOn(){ +bool Cmfd::isFluxUpdateOn() { return _flux_update_on; } +/** + * @brief Set flag indicating whether to use FSR centroids to update + * the MOC flux. + * @param centroid_update_on Flag saying whether to use centroids to + * update MOC flux. + */ +void Cmfd::setCentroidUpdateOn(bool centroid_update_on) { + _centroid_update_on = centroid_update_on; +} + + +/** + * @brief Get flag indicating whether to use FSR centroids to update + * the MOC flux. + * @return Flag saying whether to use centroids to update MOC flux. + */ +bool Cmfd::isCentroidUpdateOn() { + return _centroid_update_on; +} + + /** * @brief Sets the threshold for CMFD source convergence (>0) * @param the threshold for source convergence @@ -1701,50 +1426,335 @@ void Cmfd::setSourceConvergenceThreshold(FP_PRECISION source_thresh) { /** - * @brief Sets the type of polar angle quadrature set to use (ie, TABUCHI - * or LEONARD). - * @param the polar angle quadrature type - * @param the number of polar angles + * @brief Sets the PolarQuad object in use by the MOC Solver. + * @param polar_quad A PolarQuad object pointer from the Solver + */ +void Cmfd::setPolarQuadrature(PolarQuad* polar_quad) { + _polar_quad = polar_quad; + _num_polar = polar_quad->getNumPolarAngles(); +} + + +/** + * @brief Generate the k-nearest neighbor CMFD cell stencil for each FSR. + * @details This method finds the k-nearest CMFD cell stencil for each FSR + * and saves the stencil, ordered from the closest-to-furthest + * CMFD cell, in the _k_nearest_stencils map. The stencil of cells + * surrounding the current cell is defined as: + * + * 6 7 8 + * 3 4 5 + * 0 1 2 + * + * where 4 is the given CMFD cell. If the cell is on the edge or corner + * of the geometry and there are less than k nearest neighbor cells, + * k is reduced to the number of neighbor cells for that instance. */ -void Cmfd::setPolarQuadrature(quadratureType quadrature_type, int num_polar) { +void Cmfd::generateKNearestStencils() { - /* Deletes the old Quadrature if one existed */ - if (_quad != NULL) - delete _quad; + if (!_centroid_update_on) + return; - _quad = new Quadrature(quadrature_type, num_polar); - _num_polar = num_polar; + std::vector< std::pair >::iterator stencil_iter; + std::vector::iterator fsr_iter; + Point* centroid; + int fsr_id; + + /* Loop over mesh cells */ + for (int i = 0; i < _num_x*_num_y; i++) { + + /* Loop over FRSs in mesh cell */ + for (fsr_iter = _cell_fsrs.at(i).begin(); + fsr_iter != _cell_fsrs.at(i).end(); ++fsr_iter) { + + fsr_id = *fsr_iter; + + /* Get centroid */ + centroid = _geometry->getFSRCentroid(fsr_id); + + /* Create new stencil */ + _k_nearest_stencils[fsr_id] = + std::vector< std::pair >(); + + /* Get distance to all cells that touch current cell */ + for (int j=0; j <= NUM_SURFACES; j++) + _k_nearest_stencils[fsr_id] + .push_back(std::make_pair + (int(j), getDistanceToCentroid(centroid, i, j))); + + /* Sort the distances */ + std::sort(_k_nearest_stencils[fsr_id].begin(), + _k_nearest_stencils[fsr_id].end(), stencilCompare); + + /* Remove ghost cells that are outside the geometry boundaries */ + stencil_iter = _k_nearest_stencils[fsr_id].begin(); + while (stencil_iter != _k_nearest_stencils[fsr_id].end()) { + if (stencil_iter->second == std::numeric_limits::max()) + stencil_iter = _k_nearest_stencils[fsr_id].erase(stencil_iter++); + else + ++stencil_iter; + } + + /* Resize stencil to be of size <= _k_nearest */ + _k_nearest_stencils[fsr_id].resize + (std::min(_k_nearest, int(_k_nearest_stencils[fsr_id].size()))); + } + } + + /* Precompute (1.0 - cell distance / total distance) of each FSR centroid to + * its k-nearest CMFD cells */ + FP_PRECISION total_distance; + for (int i=0; i < _num_FSRs; i++) { + total_distance = 1.e-10; + + /* Compute the total distance of each FSR centroid to its k-nearest CMFD + * cells */ + for (stencil_iter = _k_nearest_stencils[i].begin(); + stencil_iter < _k_nearest_stencils[i].end(); ++stencil_iter) + total_distance += stencil_iter->second; + + /* Reset the second stencil value to + * (1.0 - cell_distance / total_distance) */ + for (stencil_iter = _k_nearest_stencils[i].begin(); + stencil_iter < _k_nearest_stencils[i].end(); ++stencil_iter) + stencil_iter->second = 1.0 - stencil_iter->second / total_distance; + } } /** - * @brief Get the new to old flux ratio for a CMFD cell. - * @param the CMFD cell ID - * @param the MOC energy group - * @return the flux ratio + * @brief Get the ID of the Mesh cell given a stencil ID and Mesh cell ID. + * @details The stencil of cells surrounding the current cell is defined as: + * + * 6 7 8 + * 3 4 5 + * 0 1 2 + * + * @param cell_id Current Mesh cell ID + * @param stencil_id CMFD cell stencil ID + * @return Neighboring CMFD cell ID */ -FP_PRECISION Cmfd::getFluxRatio(int cmfd_cell, int moc_group){ +int Cmfd::getCellByStencil(int cell_id, int stencil_id) { + + int cell_next_id = -1; + int x = cell_id % _num_x; + int y = cell_id / _num_x; + + if (stencil_id == 0) { + if (x != 0 && y != 0) + cell_next_id = cell_id - _num_x - 1; + } + else if (stencil_id == 1) { + if (y != 0) + cell_next_id = cell_id - _num_x; + else if (_boundaries[SURFACE_Y_MIN] == PERIODIC) + cell_next_id = cell_id + _num_x * (_num_y - 1); + } + else if (stencil_id == 2) { + if (x != _num_x - 1 && y != 0) + cell_next_id = cell_id - _num_x + 1; + } + else if (stencil_id == 3) { + if (x != 0) + cell_next_id = cell_id - 1; + else if (_boundaries[SURFACE_X_MIN] == PERIODIC) + cell_next_id = cell_id + (_num_x - 1); + } + else if (stencil_id == 4) { + cell_next_id = cell_id; + } + else if (stencil_id == 5) { + if (x != _num_x - 1) + cell_next_id = cell_id + 1; + else if (_boundaries[SURFACE_X_MAX] == PERIODIC) + cell_next_id = cell_id - (_num_x - 1); + } + else if (stencil_id == 6) { + if (x != 0 && y != _num_y - 1) + cell_next_id = cell_id + _num_x - 1; + } + else if (stencil_id == 7) { + if (y != _num_y - 1) + cell_next_id = cell_id + _num_x; + else if (_boundaries[SURFACE_Y_MAX] == PERIODIC) + cell_next_id = cell_id - _num_x * (_num_y - 1); + } + else if (stencil_id == 8) { + if (x != _num_x - 1 && y != _num_y - 1) + cell_next_id = cell_id + _num_x + 1; + } + + return cell_next_id; +} + + +/** + * @brief Get the ratio used to update the FSR flux after converging CMFD. + * @details This method takes in a cmfd cell, a MOC energy group, and a FSR + * and returns the ratio used to update the FSR flux. There are two + * methods that can be used to update the flux, conventional and + * k-nearest centroid updating. The k-nearest centroid updating uses + * the k-nearest cells (with k between 1 and 9) of the current CMFD + * cell and the 8 neighboring CMFD cells. The stencil of cells + * surrounding the current cell is defined as: + * + * 6 7 8 + * 3 4 5 + * 0 1 2 + * + * where 4 is the given CMFD cell. If the cell is on the edge or corner + * of the geometry and there are less than k nearest neighbor cells, + * k is reduced to the number of neighbor cells for that instance. + * @param cell_id The cmfd cell ID containing the FSR. + * @param group The CMFD energy group being updated. + * @param fsr The fsr being updated. + * @return the ratio used to update the FSR flux. + */ +FP_PRECISION Cmfd::getUpdateRatio(int cell_id, int group, int fsr) { + + FP_PRECISION ratio = 0.0; + std::vector< std::pair >::iterator iter; + int cell_next_id; + + if (_centroid_update_on) { + + /* Compute the ratio for all the surrounding cells */ + for (iter = _k_nearest_stencils[fsr].begin(); + iter != _k_nearest_stencils[fsr].end(); ++iter) { + + if (iter->first != 4) { + cell_next_id = getCellByStencil(cell_id, iter->first); + ratio += iter->second * _flux_ratio->getValue(cell_next_id, group); + } + } + + /* INTERNAL */ + if (_k_nearest_stencils[fsr].size() == 1) + ratio += _flux_ratio->getValue(cell_id, group); + else{ + ratio += _k_nearest_stencils[fsr][0].second * + _flux_ratio->getValue(cell_id, group); + ratio /= (_k_nearest_stencils[fsr].size() - 1); + } + } + else + ratio = _flux_ratio->getValue(cell_id, group); - int cmfd_group = _group_indices_map[moc_group]; - FP_PRECISION old_flux = _old_flux[cmfd_cell*_num_cmfd_groups + cmfd_group]; - FP_PRECISION new_flux = _new_flux[cmfd_cell*_num_cmfd_groups + cmfd_group]; - FP_PRECISION ratio = new_flux / old_flux; return ratio; } +/** + * @brief Get the distances from an FSR centroid to a given cmfd cell. + * @details This method takes in a FSR centroid, a cmfd cell, and a stencil index + * to a cell located in the 9-point stencil encompassing the cmfd + * cell an all its possible neighbors. The CMFD cell stencil is: + * + * 6 7 8 + * 3 4 5 + * 0 1 2 + * + * where 4 is the given CMFD cell. If a CMFD edge or corner cells is + * given and the stencil indexed cell lies outside the geometry, the + * maximum allowable FP_PRECISION value is returned. + * @param centroid The numerical centroid an FSR in the cell. + * @param cell_id The cmfd cell containing the FSR. + * @param stencil_index The index of the cell in the stencil that we want to + * get the distance from. + * @return the distance from the CMFD cell centroid to the FSR centroid. + */ +FP_PRECISION Cmfd::getDistanceToCentroid(Point* centroid, int cell_id, + int stencil_index) { + + int x = cell_id % _num_x; + int y = cell_id / _num_x; + FP_PRECISION dist_x, dist_y; + bool found = false; + FP_PRECISION centroid_x = centroid->getX(); + FP_PRECISION centroid_y = centroid->getY(); + + /* LOWER LEFT CORNER */ + if (x > 0 && y > 0 && stencil_index == 0) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x - 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y - 0.5)*_cell_width_y), 2.0); + found = true; + } + + /* BOTTOM SIDE */ + else if (y > 0 && stencil_index == 1) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y - 0.5)*_cell_width_y),2.0); + found = true; + } + + /* LOWER RIGHT CORNER */ + else if (x < _num_x - 1 && y > 0 && stencil_index == 2) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 1.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y - 0.5)*_cell_width_y), 2.0); + found = true; + } + + /* LEFT SIDE */ + else if (x > 0 && stencil_index == 3) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x - 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 0.5)*_cell_width_y), 2.0); + found = true; + } + + /* CURRENT */ + else if (stencil_index == 4) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 0.5)*_cell_width_y), 2.0); + found = true; + } + + /* RIGHT SIDE */ + else if (x < _num_x - 1 && stencil_index == 5) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 1.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 0.5)*_cell_width_y), 2.0); + found = true; + } + + /* UPPER LEFT CORNER */ + else if (x > 0 && y < _num_y - 1 && stencil_index == 6) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x - 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 1.5)*_cell_width_y), 2.0); + found = true; + } + + /* TOP SIDE */ + else if (y < _num_y - 1 && stencil_index == 7) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 0.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 1.5)*_cell_width_y), 2.0); + found = true; + } + + /* UPPER RIGHT CORNER */ + else if (x < _num_x - 1 && y < _num_y - 1 && stencil_index == 8) { + dist_x = pow(centroid_x - (-_width_x/2.0 + (x + 1.5)*_cell_width_x), 2.0); + dist_y = pow(centroid_y - (-_width_y/2.0 + (y + 1.5)*_cell_width_y), 2.0); + found = true; + } + + if (found) + return pow(dist_x + dist_y, 0.5); + else + return std::numeric_limits::max(); +} + + /** * @brief Update the MOC boundary fluxes. * @details The MOC boundary fluxes are updated using the P0 approximation. * With this approximation, the boundary fluxes are updated using * the ratio of new to old flux for the cell that the outgoing flux * from the track enters. - * @param 2D array of Tracks - * @param array of boundary fluxes - * @return the number of Tracks + * @param tracks 2D array of Tracks + * @param boundary_flux Array of boundary fluxes + * @return The number of Tracks */ -void Cmfd::updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, - int num_tracks){ +void Cmfd::updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, + int num_tracks) { segment* segments; segment* curr_segment; @@ -1752,13 +1762,13 @@ void Cmfd::updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, int bc; FP_PRECISION* track_flux; FP_PRECISION ratio; - int cmfd_cell; - + int cell_id; + log_printf(INFO, "updating boundary flux"); /* Loop over Tracks */ for (int i=0; i < num_tracks; i++) { - + num_segments = tracks[i]->getNumSegments(); segments = tracks[i]->getSegments(); @@ -1766,27 +1776,247 @@ void Cmfd::updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, bc = (int)tracks[i]->getBCOut(); curr_segment = &segments[0]; track_flux = &boundary_flux[i*2*_num_moc_groups*_num_polar]; - cmfd_cell = convertFSRIdToCmfdCell(curr_segment->_region_id); - - if (bc){ + cell_id = convertFSRIdToCmfdCell(curr_segment->_region_id); + + if (bc) { for (int e=0; e < _num_moc_groups; e++) { for (int p=0; p < _num_polar; p++) { - track_flux[p*_num_moc_groups+e] *= getFluxRatio(cmfd_cell, e); + track_flux[p*_num_moc_groups + e] *= _flux_ratio->getValue + (cell_id, e); } } } /* Update boundary flux in backwards direction */ bc = (int)tracks[i]->getBCIn(); - curr_segment = &segments[num_segments-1]; + curr_segment = &segments[num_segments - 1]; track_flux = &boundary_flux[(i*2 + 1)*_num_moc_groups*_num_polar]; - - if (bc){ + + if (bc) { for (int e=0; e < _num_moc_groups; e++) { for (int p=0; p < _num_polar; p++) { - track_flux[p*_num_moc_groups+e] *= getFluxRatio(cmfd_cell, e); + track_flux[p*_num_moc_groups + e] *= _flux_ratio->getValue + (cell_id, e); } } } } } + + +/** @brief Set a pointer to the Geometry. + * @param goemetry A pointer to a Geometry object. + */ +void Cmfd::setGeometry(Geometry* geometry) { + _geometry = geometry; +} + + +/** @brief Set a number of k-nearest neighbor cells to use in updating + * the FSR flux. + * @param k_nearest The number of nearest neighbor CMFD cells. + */ +void Cmfd::setKNearest(int k_nearest) { + + if (_k_nearest < 1 || k_nearest > 9) + log_printf(ERROR, "Unable to set CMFD k-nearest to %d. k-nearest " + "must be between 1 and 9.", k_nearest); + else + _k_nearest = k_nearest; +} + + +/** + * @brief Zero the surface currents for each mesh cell and energy + * group. + */ +void Cmfd::zeroCurrents() { + _surface_currents->clear(); +} + + +/** + * @brief Tallies the current contribution from this segment across the + * the appropriate CMFD mesh cell surface. + * @param curr_segment The current Track segment + * @param track_flux The outgoing angular flux for this segment + * @param polar_weights Array of polar weights for some azimuthal angle + * @param fwd Boolean indicating direction of integration along segment + */ +void Cmfd::tallyCurrent(segment* curr_segment, FP_PRECISION* track_flux, + FP_PRECISION* polar_weights, bool fwd) { + + int surf_id, cell_id; + int ncg = _num_cmfd_groups; + FP_PRECISION currents[_num_cmfd_groups]; + memset(currents, 0.0, sizeof(FP_PRECISION) * _num_cmfd_groups); + + if (fwd) { + if (curr_segment->_cmfd_surface_fwd != -1) { + + surf_id = curr_segment->_cmfd_surface_fwd % NUM_SURFACES; + cell_id = curr_segment->_cmfd_surface_fwd / NUM_SURFACES; + + for (int e=0; e < _num_moc_groups; e++) { + + int g = getCmfdGroup(e); + + for (int p=0; p < _num_polar; p++) + currents[g] += track_flux(p, e) * polar_weights[p] / 2.; + } + + /* Increment currents */ + _surface_currents->incrementValues + (cell_id, surf_id*ncg, (surf_id+1)*ncg - 1, currents); + } + } + else { + if (curr_segment->_cmfd_surface_bwd != -1) { + + surf_id = curr_segment->_cmfd_surface_bwd % NUM_SURFACES; + cell_id = curr_segment->_cmfd_surface_bwd / NUM_SURFACES; + + for (int e=0; e < _num_moc_groups; e++) { + + int g = getCmfdGroup(e); + + for (int p=0; p < _num_polar; p++) + currents[g] += track_flux(p, e) * polar_weights[p] / 2.; + } + + /* Increment currents */ + _surface_currents->incrementValues + (cell_id, surf_id*ncg, (surf_id+1)*ncg - 1, currents); + } + } +} + + +/** + * @brief Initialize the Matrix and Vector objects, k-nearest stencils, the + * CMFD cell currents and MOC materials. + */ +void Cmfd::initialize() { + + int num_cells = getNumCells(); + + /* Delete old Matrix and Vector objects if they exist */ + if (_M != NULL) + delete _M; + if (_A != NULL) + delete _A; + if (_old_source != NULL) + delete _old_source; + if (_new_source != NULL) + delete _new_source; + if (_old_flux != NULL) + delete _old_flux; + if (_new_flux != NULL) + delete _new_flux; + if (_flux_ratio != NULL) + delete _flux_ratio; + if (_volumes != NULL) + delete _volumes; + if (_cell_locks != NULL) + delete [] _cell_locks; + + try{ + + /* Allocate array of OpenMP locks for each CMFD cell */ + _cell_locks = new omp_lock_t[num_cells]; + + /* Loop over all cells to initialize OpenMP locks */ +#pragma omp parallel for schedule(guided) + for (int r=0; r < num_cells; r++) + omp_init_lock(&_cell_locks[r]); + + /* Allocate memory for matrix and vector objects */ + _M = new Matrix(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _A = new Matrix(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _old_source = new Vector(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _new_source = new Vector(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _old_flux = new Vector(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _new_flux = new Vector(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _flux_ratio = new Vector(_cell_locks, _num_x, _num_y, _num_cmfd_groups); + _volumes = new Vector(_cell_locks, _num_x, _num_y, 1); + + /* Initialize k-nearest stencils, currents, flux, and materials */ + generateKNearestStencils(); + initializeCurrents(); + initializeMaterials(); + } + catch(std::exception &e) { + log_printf(ERROR, "Could not allocate memory for the CMFD mesh objects. " + "Backtrace:%s", e.what()); + } +} + + +/** + * @brief Initialize the CMFD lattice. + */ +void Cmfd::initializeLattice(Point* offset) { + + /* Delete old lattice if it exists */ + if (_lattice != NULL) + delete _lattice; + + /* Initialize the lattice */ + _lattice = new Lattice(); + _lattice->setNumX(_num_x); + _lattice->setNumY(_num_y); + _lattice->setWidth(_cell_width_x, _cell_width_y); + _lattice->setOffset(offset->getX(), offset->getY(), 0.0); +} + + +/** + * @brief Returns the width of a given surface + * @param surface A surface index, from 0 to NUM_SURFACES - 1 + * @return The surface width + */ +FP_PRECISION Cmfd::getSurfaceWidth(int surface) { + + FP_PRECISION width; + + if (surface == SURFACE_X_MIN || surface == SURFACE_X_MAX) + width = _cell_width_y; + else + width = _cell_width_x; + + return width; +} + + +/** + * @brief Returns the width of the surface perpendicular to a given surface + * @param surface A surface index, from 0 to NUM_SURFACES - 1 + * @return The perpendicular surface width + */ +FP_PRECISION Cmfd::getPerpendicularSurfaceWidth(int surface) { + + if (surface == SURFACE_X_MIN || surface == SURFACE_X_MAX) + return _cell_width_x; + else + return _cell_width_y; +} + + +/** + * @brief Returns the sense of a given surface + * @details The sense of minimum surfaces (e.g. SURFACE_X_MIN) is defined to be + * -1 while maximum surfaces (e.g. SURFACE_X_MAX) are defined to have a + * sense of +1. This is based on the current exiting a cell from a + * minimum surface being in the direction of negative net current and + * the current leaving a cell from a maximum surface being in the + * direction of positive net current. + * @param surface A surface index, from 0 to NUM_SURFACES - 1 + * @return The sense of the surface + */ +int Cmfd::getSense(int surface) { + + if (surface == SURFACE_X_MIN || surface == SURFACE_Y_MIN) + return -1; + else + return 1; +} diff --git a/src/Cmfd.h b/src/Cmfd.h index 9c836d7d3..6ca72ed16 100644 --- a/src/Cmfd.h +++ b/src/Cmfd.h @@ -10,23 +10,31 @@ #ifdef __cplusplus #define _USE_MATH_DEFINES -#include -#include -#include -#include -#include -#include -#include -#include -#include "Quadrature.h" +#ifdef SWIG +#include "Python.h" +#endif #include "log.h" -#include "Timer.h" #include "Universe.h" #include "Track.h" +#include "PolarQuad.h" #include "linalg.h" -#include "pairwise_sum.h" +#include "Geometry.h" #endif +/** Forward declaration of Geometry class */ +class Geometry; + +/** Comparitor for sorting k-nearest stencil std::pair objects */ +inline bool stencilCompare(const std::pair& firstElem, + const std::pair& secondElem) { + return firstElem.second < secondElem.second; +} + +#undef track_flux + +/** Indexing macro for the angular fluxes for each polar angle and energy + * group for either the forward or reverse direction for a given Track */ +#define track_flux(p,e) (track_flux[(p)*_num_moc_groups + (e)]) /** * @class Cmfd Cmfd.h "src/Cmfd.h" @@ -36,35 +44,37 @@ class Cmfd { private: - /** Pointer to polar Quadrature object */ - Quadrature* _quad; + /** Pointer to polar quadrature object */ + PolarQuad* _polar_quad; + + /** Pointer to geometry object */ + Geometry* _geometry; /** The keff eigenvalue */ FP_PRECISION _k_eff; /** The A (destruction) matrix */ - FP_PRECISION** _A; + Matrix* _A; /** The M (production) matrix */ - FP_PRECISION** _M; + Matrix* _M; /** The old source vector */ - FP_PRECISION* _old_source; + Vector* _old_source; /** The new source vector */ - FP_PRECISION* _new_source; + Vector* _new_source; - /** Vector representing the flux for each cmfd cell and cmfd enegy group at + /** Vector representing the flux for each cmfd cell and cmfd enegy group at * the end of a CMFD solve */ - FP_PRECISION* _new_flux; + Vector* _new_flux; - /** Vector representing the flux for each cmfd cell and cmfd enegy group at + /** Vector representing the flux for each cmfd cell and cmfd enegy group at * the beginning of a CMFD solve */ - FP_PRECISION* _old_flux; + Vector* _old_flux; - /** Vector representing the flux during the previous iteration of a - * cmfd solve */ - FP_PRECISION* _flux_temp; + /** Vector representing the ratio of the new to old CMFD flux */ + Vector* _flux_ratio; /** Gauss-Seidel SOR relaxation factor */ FP_PRECISION _SOR_factor; @@ -94,6 +104,9 @@ class Cmfd { /** Map of MOC groups to CMFD groups */ int* _group_indices_map; + /** If the user specified fine-to-coarse group indices */ + bool _user_group_indices; + /** Number of FSRs */ int _num_FSRs; @@ -106,65 +119,91 @@ class Cmfd { /** The FSR scalar flux in each energy group */ FP_PRECISION* _FSR_fluxes; - /** Array of CMFD cell volumes */ - FP_PRECISION* _volumes; + /** Vector of CMFD cell volumes */ + Vector* _volumes; /** Array of material pointers for CMFD cell materials */ Material** _materials; /** Physical dimensions of the geometry and each CMFD cell */ - double _width; - double _height; - double _cell_width; - double _cell_height; + double _width_x; + double _width_y; + double _cell_width_x; + double _cell_width_y; /** Array of geometry boundaries */ - // int* _boundaries; boundaryType* _boundaries; - /** Array of surface currents for each CMFD cell */ - FP_PRECISION* _surface_currents; + /** Vector of surface currents for each CMFD cell */ + Vector* _surface_currents; /** Vector of vectors of FSRs containing in each cell */ std::vector< std::vector > _cell_fsrs; - /** MOC flux update relaxation factor */ - FP_PRECISION _relax_factor; - - /** Flag indicating whether to use optically thick correction factor */ - bool _optically_thick; - /** Pointer to Lattice object representing the CMFD mesh */ Lattice* _lattice; /** Flag indicating whether to update the MOC flux */ bool _flux_update_on; + /** Flag indicating whether to use centroid updating (default true) */ + bool _centroid_update_on; + + /** Number of cells used in updating MOC flux (default 3) */ + int _k_nearest; + + /** Map storing the k-nearest stencil for each fsr */ + std::map > > + _k_nearest_stencils; + + /** OpenMP mutual exclusion locks for atomic CMFD cell operations */ + omp_lock_t* _cell_locks; + + /* Private worker functions */ + FP_PRECISION computeLarsensEDCFactor(FP_PRECISION dif_coef, + FP_PRECISION delta); + void constructMatrices(int moc_iteration); + void collapseXS(); + void updateMOCFlux(); + void rescaleFlux(); + void splitEdgeCurrents(); + void getEdgeSplitSurfaces(int cell, int edge, std::vector* surfaces); + void initializeMaterials(); + void initializeCurrents(); + void generateKNearestStencils(); + + /* Private getter functions */ + int getCellNext(int cell_id, int surface_id); + int getCellByStencil(int cell_id, int stencil_id); + FP_PRECISION getUpdateRatio(int cell_id, int moc_group, int fsr); + FP_PRECISION getDistanceToCentroid(Point* centroid, int cell_id, + int stencil_index); + FP_PRECISION getSurfaceDiffusionCoefficient(int cmfd_cell, int surface, + int group, int moc_iteration, + bool correction); + FP_PRECISION getDiffusionCoefficient(int cmfd_cell, int group); + FP_PRECISION getSurfaceWidth(int surface); + FP_PRECISION getPerpendicularSurfaceWidth(int surface); + int getSense(int surface); + public: Cmfd(); virtual ~Cmfd(); /* Worker functions */ - void constructMatrices(); - void computeDs(int moc_iteration); - void computeXS(); - void updateMOCFlux(); - FP_PRECISION computeDiffCorrect(FP_PRECISION d, FP_PRECISION h); FP_PRECISION computeKeff(int moc_iteration); + void initialize(); void initializeCellMap(); void initializeGroupMap(); - void initializeFlux(); - void initializeMaterials(); - void rescaleFlux(); - void linearSolve(FP_PRECISION** mat, FP_PRECISION* vec_x, FP_PRECISION* vec_b, - FP_PRECISION conv, int max_iter=10000); - void splitCorners(); - int getCellNext(int cell_num, int surface_id); + void initializeLattice(Point* offset); int findCmfdCell(LocalCoords* coords); - int findCmfdSurface(int cell, LocalCoords* coords); - void addFSRToCell(int cmfd_cell, int fsr_id); - void updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, + int findCmfdSurface(int cell_id, LocalCoords* coords); + void addFSRToCell(int cell_id, int fsr_id); + void zeroCurrents(); + void tallyCurrent(segment* curr_segment, FP_PRECISION* track_flux, + FP_PRECISION* polar_weights, bool fwd); + void updateBoundaryFlux(Track** tracks, FP_PRECISION* boundary_flux, int num_tracks); /* Get parameters */ @@ -172,41 +211,38 @@ class Cmfd { int getNumMOCGroups(); int getNumCells(); int getCmfdGroup(int group); - bool isOpticallyThick(); - FP_PRECISION getMOCRelaxationFactor(); int getBoundary(int side); Lattice* getLattice(); int getNumX(); int getNumY(); int convertFSRIdToCmfdCell(int fsr_id); - std::vector< std::vector > getCellFSRs(); + std::vector< std::vector >* getCellFSRs(); bool isFluxUpdateOn(); - FP_PRECISION getFluxRatio(int cmfd_cell, int moc_group); + bool isCentroidUpdateOn(); /* Set parameters */ void setSORRelaxationFactor(FP_PRECISION SOR_factor); - void setWidth(double width); - void setHeight(double height); + void setGeometry(Geometry* geometry); + void setWidthX(double width); + void setWidthY(double width); void setNumX(int num_x); void setNumY(int num_y); - void setSurfaceCurrents(FP_PRECISION* surface_currents); void setNumFSRs(int num_fsrs); void setNumMOCGroups(int num_moc_groups); - void setOpticallyThick(bool thick); - void setMOCRelaxationFactor(FP_PRECISION relax_factor); void setBoundary(int side, boundaryType boundary); - void setLattice(Lattice* lattice); void setLatticeStructure(int num_x, int num_y); void setFluxUpdateOn(bool flux_update_on); + void setCentroidUpdateOn(bool centroid_update_on); void setGroupStructure(int* group_indices, int length_group_indices); void setSourceConvergenceThreshold(FP_PRECISION source_thresh); - void setPolarQuadrature(quadratureType quadrature_type, int num_polar); - + void setPolarQuadrature(PolarQuad* polar_quad); + void setKNearest(int k_nearest); + /* Set FSR parameters */ void setFSRMaterials(Material** FSR_materials); void setFSRVolumes(FP_PRECISION* FSR_volumes); void setFSRFluxes(FP_PRECISION* scalar_flux); - void setCellFSRs(std::vector< std::vector > cell_fsrs); + void setCellFSRs(std::vector< std::vector >* cell_fsrs); }; #endif /* CMFD_H_ */ diff --git a/src/ExpEvaluator.cpp b/src/ExpEvaluator.cpp new file mode 100644 index 000000000..e8f3e848c --- /dev/null +++ b/src/ExpEvaluator.cpp @@ -0,0 +1,215 @@ +#include "ExpEvaluator.h" + + +/** + * @brief Constructor initializes array pointers to NULL. + * @details The constructor sets the interpolation scheme as the default + * for computing exponentials. + */ +ExpEvaluator::ExpEvaluator() { + _interpolate = true; + _exp_table = NULL; + _polar_quad = NULL; + _max_optical_length = MAX_OPTICAL_LENGTH; + _exp_precision = EXP_PRECISION; +} + + +/** + * @brief Destructor deletes table for linear interpolation of exponentials + */ +ExpEvaluator::~ExpEvaluator() { + if (_exp_table != NULL) + delete [] _exp_table; +} + + +/** + * @brief Set the PolarQuad to use when computing exponentials. + * @param polar_quad a PolarQuad object pointer + */ +void ExpEvaluator::setPolarQuadrature(PolarQuad* polar_quad) { + _polar_quad = polar_quad; + _two_times_num_polar = 2 * _polar_quad->getNumPolarAngles(); +} + + +/** + * @brief Sets the maximum optical length covered in the exponential + * interpolation table. + * @param max_optical_length the maximum optical length + */ +void ExpEvaluator::setMaxOpticalLength(FP_PRECISION max_optical_length) { + + if (max_optical_length <= 0) + log_printf(ERROR, "Cannot set max optical length to %f because it " + "must be positive.", max_optical_length); + + _max_optical_length = max_optical_length; +} + + +/** + * @brief Sets the maximum acceptable approximation error for exponentials. + * @details This routine only affects the construction of the linear + * interpolation table for exponentials, if in use. By default, + * a value of 1E-5 is used for the table, as recommended by the + * analysis of Yamamoto in his 2004 paper on the subject. + * @param exp_precision the maximum exponential approximation error + */ +void ExpEvaluator::setExpPrecision(FP_PRECISION exp_precision) { + + if (exp_precision <= 0) + log_printf(ERROR, "Cannot set exp precision to %f because it " + "must be positive.", exp_precision); + + _exp_precision = exp_precision; +} + + +/** + * @brief Use linear interpolation to compute exponentials. + */ +void ExpEvaluator::useInterpolation() { + _interpolate = true; +} + + +/** + * @brief Use the exponential intrinsic exp(...) to compute exponentials. + */ +void ExpEvaluator::useIntrinsic() { + _interpolate = false; +} + + +/** + * @brief Gets the maximum optical length covered with the exponential + * interpolation table. + * @return max_optical_length the maximum optical length + */ +FP_PRECISION ExpEvaluator::getMaxOpticalLength() { + return _max_optical_length; +} + + +/** + * @brief Gets the maximum acceptable approximation error for exponentials. + * @return the maximum exponential approximation error + */ +FP_PRECISION ExpEvaluator::getExpPrecision() { + return _exp_precision; +} + + +/** + * @brief Returns true if using linear interpolation to compute exponentials. + * @return true if so, false otherwise + */ +bool ExpEvaluator::isUsingInterpolation() { + return _interpolate; +} + + +/** + * @brief Returns the exponential table spacing. + * @return exponential table spacing + */ +FP_PRECISION ExpEvaluator::getTableSpacing() { + + if (_exp_table == NULL) + log_printf(ERROR, "Unable to return the exponential table spacing " + "since it has not yet been initialized"); + + return 1.0 / _inverse_exp_table_spacing; +} + + +/** + * @brief Get the number of entries in the exponential interpolation table. + * @param entries in the interpolation table + * + */ +int ExpEvaluator::getTableSize() { + + if (_exp_table == NULL) + log_printf(ERROR, "Unable to return exponential table size " + "since it has not yet been initialized"); + + return _table_size; +} + + +/** + * @brief Returns a pointer to the exponential interpolation table. + * @return pointer to the exponential interpolation table + */ +FP_PRECISION* ExpEvaluator::getExpTable() { + + if (_exp_table == NULL) + log_printf(ERROR, "Unable to return exponential table " + "since it has not yet been initialized"); + + return _exp_table; +} + + +/** + * @brief If using linear interpolation, builds the table for each polar angle. + * @param tolerance the minimum acceptable interpolation accuracy + */ +void ExpEvaluator::initialize() { + + /* If no exponential table is needed, return */ + if (!_interpolate) + return; + + log_printf(INFO, "Initializing exponential interpolation table..."); + + /* Set size of interpolation table */ + int num_polar = _polar_quad->getNumPolarAngles(); + int num_array_values = _max_optical_length * sqrt(1. / (8. * _exp_precision)); + FP_PRECISION exp_table_spacing = _max_optical_length / num_array_values; + + /* Increment the number of vaues in the array to ensure that a tau equal to + * max_optical_length resides as the final entry in the table */ + num_array_values += 1; + + /* Compute the reciprocal of the table entry spacing */ + _inverse_exp_table_spacing = 1.0 / exp_table_spacing; + + /* Allocate array for the table */ + if (_exp_table != NULL) + delete [] _exp_table; + + _table_size = 2 * num_polar * num_array_values; + _exp_table = new FP_PRECISION[_table_size]; + + FP_PRECISION expon; + FP_PRECISION intercept; + FP_PRECISION slope; + FP_PRECISION sin_theta; + FP_PRECISION tau; + + /* Create exponential linear interpolation table */ + for (int i=0; i < num_array_values; i++) { + for (int p=0; p < num_polar; p++) { + sin_theta = _polar_quad->getSinTheta(p); + + /* Use the optical length at the start of the interval for the first value + * to avoid exponential values greater than one. */ + if (i == 0) + tau = i * exp_table_spacing; + + /* Use the optical length at the interval mid-point to reduce error. */ + else + tau = (i + 0.5) * exp_table_spacing; + + expon = exp(- tau / sin_theta); + intercept = expon * (1 + tau / sin_theta); + slope = - expon / sin_theta; + _exp_table[_two_times_num_polar * i + 2 * p] = slope; + _exp_table[_two_times_num_polar * i + 2 * p + 1] = intercept; + } + } +} diff --git a/src/ExpEvaluator.h b/src/ExpEvaluator.h new file mode 100644 index 000000000..d41210712 --- /dev/null +++ b/src/ExpEvaluator.h @@ -0,0 +1,111 @@ +/** + * @file ExpEvaluator.h + * @brief The ExpEvaluator class. + * @date April 9, 2015. + * @author William Boyd, MIT, Course 22 (wboyd@mit.edu) + */ + +#ifndef EXPEVALUATOR_H_ +#define EXPEVALUATOR_H_ + +#ifdef __cplusplus +#define _USE_MATH_DEFINES +#include "log.h" +#include "PolarQuad.h" +#include +#endif + + +/** + * @class ExpEvaluator ExpEvaluator.h "src/ExpEvaluator.h" + * @brief This is a class for evaluating exponentials. + * @details The ExpEvaluator includes different algorithms to evaluate + * exponentials with varying degrees of accuracy and speed. This + * is a helper class for the Solver and its subclasses and it not + * intended to be initialized as a standalone object. + */ +class ExpEvaluator { + +private: + + /** A boolean indicating whether or not to use linear interpolation */ + bool _interpolate; + + /** The inverse spacing for the exponential linear interpolation table */ + FP_PRECISION _inverse_exp_table_spacing; + + /** The number of entries in the exponential linear interpolation table */ + int _table_size; + + /** The exponential linear interpolation table */ + FP_PRECISION* _exp_table; + + /** The PolarQuad object of interest */ + PolarQuad* _polar_quad; + + /** Twice the number of polar angles */ + int _two_times_num_polar; + + /** The maximum optical length a track is allowed to have */ + FP_PRECISION _max_optical_length; + + /** The maximum acceptable approximation error for exponentials */ + FP_PRECISION _exp_precision; + +public: + + ExpEvaluator(); + virtual ~ExpEvaluator(); + + void setPolarQuadrature(PolarQuad* polar_quad); + void setMaxOpticalLength(FP_PRECISION max_optical_length); + void setExpPrecision(FP_PRECISION exp_precision); + void useInterpolation(); + void useIntrinsic(); + + FP_PRECISION getMaxOpticalLength(); + FP_PRECISION getExpPrecision(); + bool isUsingInterpolation(); + FP_PRECISION getTableSpacing(); + int getTableSize(); + FP_PRECISION* getExpTable(); + + void initialize(); + FP_PRECISION computeExponential(FP_PRECISION tau, int polar); +}; + + +/** + * @brief Computes the exponential term for a optical length and polar angle. + * @details This method computes \f$ 1 - exp(-\tau/sin(\theta_p)) \f$ + * for some optical path length and polar angle. This method + * uses either a linear interpolation table (default) or the + * exponential intrinsic exp(...) function. + * @param tau the optical path length (e.g., sigma_t times length) + * @param polar the polar angle index + * @return the evaluated exponential + */ +inline FP_PRECISION ExpEvaluator::computeExponential(FP_PRECISION tau, + int polar) { + + FP_PRECISION exponential; + + /* Evaluate the exponential using the lookup table - linear interpolation */ + if (_interpolate) { + tau = std::min(tau, (_max_optical_length)); + int index = floor(tau * _inverse_exp_table_spacing); + index *= _two_times_num_polar; + exponential = (1. - (_exp_table[index + 2 * polar] * tau + + _exp_table[index + 2 * polar + 1])); + } + + /* Evalute the exponential using the intrinsic exp(...) function */ + else { + FP_PRECISION sintheta = _polar_quad->getSinTheta(polar); + exponential = 1.0 - exp(- tau / sintheta); + } + + return exponential; +} + +#endif /* EXPEVALUATOR_H_ */ diff --git a/src/Geometry.cpp b/src/Geometry.cpp index de68b6ecd..6c4a5d2a0 100644 --- a/src/Geometry.cpp +++ b/src/Geometry.cpp @@ -7,7 +7,7 @@ */ void reset_auto_ids() { reset_material_id(); - reset_surf_id(); + reset_surface_id(); reset_cell_id(); reset_universe_id(); } @@ -18,17 +18,8 @@ void reset_auto_ids() { */ Geometry::Geometry() { - _num_FSRs = 0; - - _max_seg_length = 0; - _min_seg_length = std::numeric_limits::infinity(); - /* Initialize CMFD object to NULL */ _cmfd = NULL; - - /* initialize _num_FSRs lock */ - _num_FSRs_lock = new omp_lock_t; - omp_init_lock(_num_FSRs_lock); } @@ -37,30 +28,64 @@ Geometry::Geometry() { */ Geometry::~Geometry() { - /* Free FSR maps if they were initialized */ - if (_num_FSRs != 0) { + /* Free FSR maps if they were initialized */ + if (_FSR_keys_map.size() != 0) { + fsr_data **values = _FSR_keys_map.values(); + + for (int i=0; i<_FSR_keys_map.size(); i++) + delete values[i]; + delete[] values; + _FSR_keys_map.clear(); _FSRs_to_keys.clear(); - _FSRs_to_material_IDs.clear(); } + + /* Remove all Materials in the Geometry */ + std::map materials = getAllMaterials(); + std::map cells = getAllCells(); + std::map universes = getAllUniverses(); + std::map::iterator m_iter; + std::map::iterator c_iter; + std::map::iterator u_iter; + + /* Remove all Materials in the Geometry */ + for (m_iter = materials.begin(); m_iter != materials.end(); ++m_iter) + delete m_iter->second; + + /* Remove all Cells in the Geometry */ + for (c_iter = cells.begin(); c_iter != cells.end(); ++c_iter) + delete c_iter->second; + + /* Remove all Universes in the Geometry */ + for (u_iter = universes.begin(); u_iter != universes.end(); ++u_iter) + delete u_iter->second; +} + + +/** + * @brief Returns the total width in the x-direction of the Geometry in cm. + * @return the total width of the Geometry in the x-direction (cm) + */ +double Geometry::getWidthX() { + return (getMaxX() - getMinX()); } /** - * @brief Returns the total height (y extent) of the Geometry in cm. - * @return the total height of the Geometry (cm) + * @brief Returns the total width in the y-direction of the Geometry in cm. + * @return the total width of the Geometry in the y-direction (cm) */ -double Geometry::getHeight() { +double Geometry::getWidthY() { return (getMaxY() - getMinY()); } /** - * @brief Returns the total width (x extent) of the Geometry in cm. - * @return the total width of the Geometry (cm) + * @brief Returns the total width in the z-direction of the Geometry in cm. + * @return the total width of the Geometry in the z-direction (cm) */ -double Geometry::getWidth() { - return (getMaxX() - getMinX()); +double Geometry::getWidthZ() { + return (getMaxZ() - getMinZ()); } @@ -158,44 +183,14 @@ boundaryType Geometry::getMaxYBoundaryType() { } -/** - * @brief Returns the boundary conditions (REFLECTIVE or VACUUM) at the - * minimum z-coordinate in the Geometry. - * @return the boundary conditions for the minimum z-coordinate in the Geometry - */ -boundaryType Geometry::getMinZBoundaryType() { - return _root_universe->getMinZBoundaryType(); -} - - -/** - * @brief Returns the boundary conditions (REFLECTIVE or VACUUM) at the - * maximum z-coordinate in the Geometry. - * @return the boundary conditions for the maximum z-coordinate in the Geometry - */ -boundaryType Geometry::getMaxZBoundaryType() { - return _root_universe->getMaxZBoundaryType(); -} - - /** * @brief Returns the number of flat source regions in the Geometry. * @return number of FSRs */ int Geometry::getNumFSRs() { - return _num_FSRs; + return _FSRs_to_keys.size(); } - -/** - * @brief Sets the number of flat source regions (FSRs) in the Geometry. - * @param num_fsrs number of FSRs - */ -void Geometry::setNumFSRs(int num_fsrs) { - _num_FSRs = num_fsrs; -} - - /** * @brief Returns the number of energy groups for each Material's nuclear data. * @return the number of energy groups @@ -227,14 +222,7 @@ int Geometry::getNumEnergyGroups() { * @return the number of Materials */ int Geometry::getNumMaterials() { - - std::map all_materials; - - if (_all_materials.size() == 0) - all_materials = getAllMaterials(); - else - all_materials = _all_materials; - + std::map all_materials = getAllMaterials(); int num_materials = all_materials.size(); return num_materials; } @@ -249,7 +237,7 @@ int Geometry::getNumCells() { int num_cells = 0; if (_root_universe != NULL) { - std::map all_cells = _root_universe->getAllCells(); + std::map all_cells = getAllCells(); num_cells = all_cells.size(); } @@ -258,20 +246,34 @@ int Geometry::getNumCells() { /** - * @brief Return the max Track segment length computed during segmentation (cm) - * @return max Track segment length (cm) + * @brief Return a std::map container of Surface IDs (keys) with Surfaces + * pointers (values). + * @return a std::map of Surfaces indexed by Surface ID in the geometry */ -double Geometry::getMaxSegmentLength() { - return _max_seg_length; -} +std::map Geometry::getAllSurfaces() { + Cell* cell; + Surface* surf; + std::map all_surfs; + std::map surfs; + std::map::iterator c_iter; + std::map::iterator s_iter; -/** - * @brief Return the min Track segment length computed during segmentation (cm) - * @return min Track segment length (cm) - */ -double Geometry::getMinSegmentLength() { - return _min_seg_length; + if (_root_universe != NULL) { + std::map all_cells = getAllCells(); + + for (c_iter = all_cells.begin(); c_iter != all_cells.end(); ++c_iter) { + cell = (*c_iter).second; + surfs = cell->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = (*s_iter).second->_surface; + all_surfs[surf->getId()] = surf; + } + } + } + + return all_surfs; } @@ -287,15 +289,17 @@ std::map Geometry::getAllMaterials() { Material* material; if (_root_universe != NULL) { - std::map all_cells = _root_universe->getAllCells(); + std::map all_cells = getAllMaterialCells(); std::map::iterator iter; for (iter = all_cells.begin(); iter != all_cells.end(); ++iter) { cell = (*iter).second; if (cell->getType() == MATERIAL) { - material = static_cast(cell)->getMaterial(); - all_materials[material->getId()] = material; + material = cell->getFillMaterial(); + + if (material != NULL) + all_materials[material->getId()] = material; } } } @@ -304,6 +308,22 @@ std::map Geometry::getAllMaterials() { } +/** + * @brief Return a std::map container of Cell IDs (keys) with Cells + * pointers (values). + * @return a std::map of Cells indexed by Cell ID in the geometry + */ +std::map Geometry::getAllCells() { + + std::map all_cells; + + if (_root_universe != NULL) + all_cells = _root_universe->getAllCells(); + + return all_cells; +} + + /** * @brief Return a std::map container of Cell IDs (keys) with Cells * pointers (values). @@ -315,7 +335,7 @@ std::map Geometry::getAllMaterialCells() { Cell* cell; if (_root_universe != NULL) { - std::map all_cells = _root_universe->getAllCells(); + std::map all_cells = getAllCells(); std::map::iterator iter; for (iter = all_cells.begin(); iter != all_cells.end(); ++iter) { @@ -330,6 +350,22 @@ std::map Geometry::getAllMaterialCells() { } +/** + * @brief Return a std::map container of Universe IDs (keys) with Unierses + * pointers (values). + * @return a std::map of Universes indexed by Universe ID in the geometry + */ +std::map Geometry::getAllUniverses() { + + std::map all_universes; + + if (_root_universe != NULL) + all_universes = _root_universe->getAllUniverses(); + + return all_universes; +} + + /** * @brief Returns the Universe at the root node in the CSG tree. * @return the root Universe @@ -343,7 +379,7 @@ Universe* Geometry::getRootUniverse() { * @brief Returns a pointer to the CMFD object. * @return A pointer to the CMFD object */ -Cmfd* Geometry::getCmfd(){ +Cmfd* Geometry::getCmfd() { return _cmfd; } @@ -361,7 +397,7 @@ void Geometry::setRootUniverse(Universe* root_universe) { * @brief Sets the pointer to a CMFD object used for acceleration. * @param cmfd a pointer to the CMFD object */ -void Geometry::setCmfd(Cmfd* cmfd){ +void Geometry::setCmfd(Cmfd* cmfd) { _cmfd = cmfd; } @@ -383,12 +419,12 @@ void Geometry::setCmfd(Cmfd* cmfd){ * @param coords pointer to a LocalCoords object * @return returns a pointer to a Cell if found, NULL if no Cell found */ -CellBasic* Geometry::findCellContainingCoords(LocalCoords* coords) { +Cell* Geometry::findCellContainingCoords(LocalCoords* coords) { Universe* univ = coords->getUniverse(); Cell* cell; - if (universe_id == 0){ + if (univ->getId() == _root_universe->getId()) { if (!withinBounds(coords)) return NULL; } @@ -398,7 +434,7 @@ CellBasic* Geometry::findCellContainingCoords(LocalCoords* coords) { else cell = static_cast(univ)->findCell(coords); - return static_cast(cell); + return cell; } @@ -418,65 +454,49 @@ CellBasic* Geometry::findCellContainingCoords(LocalCoords* coords) { * each LocalCoord in the linked list for the Lattice or Universe * that it is in. * @param coords pointer to a LocalCoords object - * @param angle the angle for a trajectory projected from the LocalCoords * @return returns a pointer to a cell if found, NULL if no cell found */ -CellBasic* Geometry::findFirstCell(LocalCoords* coords, double angle) { - double delta_x = cos(angle) * TINY_MOVE; - double delta_y = sin(angle) * TINY_MOVE; - coords->adjustCoords(delta_x, delta_y); +Cell* Geometry::findFirstCell(LocalCoords* coords) { + coords->adjustCoords(TINY_MOVE); return findCellContainingCoords(coords); } /** * @brief Find the Material for a flat source region ID. - * @details This method finds the fsr_id within the - * _FSR_to_material_IDs map and returns the corresponding - * pointer to the Material object. * @param fsr_id a FSR id * @return a pointer to the Material that this FSR is in */ Material* Geometry::findFSRMaterial(int fsr_id) { - - std::map all_materials; - - if (_all_materials.size() == 0) - all_materials = getAllMaterials(); - else - all_materials = _all_materials; - - return all_materials[_FSRs_to_material_IDs.at(fsr_id)]; + Cell* cell = findCellContainingFSR(fsr_id); + return cell->getFillMaterial(); } /** - * @brief Finds the next Cell for a LocalCoords object along a trajectory - * defined by some angle (in radians from 0 to Pi). + * @brief Finds the next Cell for a LocalCoords object. * @details The method will update the LocalCoords passed in as an argument * to be the one at the boundary of the next Cell crossed along the * given trajectory. It will do this by finding the minimum distance - * to the surfaces at all levels of the coords hierarchy. - * If the LocalCoords is outside the bounds of the Geometry or on - * the boundaries this method will return NULL; otherwise it will - * return a pointer to the Cell that the LocalCoords will reach - * next along its trajectory. + * to the surfaces at all levels of the coords hierarchy. If the + * LocalCoords is outside the bounds of the Geometry or on the + * boundaries this method will return NULL; otherwise it will return + * a pointer to the Cell that the LocalCoords will reach next along + * its trajectory. * @param coords pointer to a LocalCoords object - * @param angle the angle of the trajectory * @return a pointer to a Cell if found, NULL if no Cell found */ -CellBasic* Geometry::findNextCell(LocalCoords* coords, double angle) { +Cell* Geometry::findNextCell(LocalCoords* coords) { Cell* cell = NULL; double dist; double min_dist = std::numeric_limits::infinity(); - Point surf_intersection; - /* Find the current Cell */ - cell = findCellContainingCoords(coords); + /* Get highest level coords */ + coords = coords->getHighestLevel(); - /* Get lowest level coords */ - coords = coords->getLowestLevel(); + /* Get the current Cell */ + cell = coords->getLowestLevel()->getCell(); /* If the current coords is not in any Cell, return NULL */ if (cell == NULL) @@ -485,7 +505,7 @@ CellBasic* Geometry::findNextCell(LocalCoords* coords, double angle) { /* If the current coords is inside a Cell, look for next Cell */ else { - /* Ascend universes until at the highest level. + /* Descend universes until at the lowest level. * At each universe/lattice level get distance to next * universe or lattice cell. Recheck min_dist. */ while (coords != NULL) { @@ -494,38 +514,38 @@ CellBasic* Geometry::findNextCell(LocalCoords* coords, double angle) { * nearest lattice cell boundary */ if (coords->getType() == LAT) { Lattice* lattice = coords->getLattice(); - dist = lattice->minSurfaceDist(coords->getPoint(), angle); + dist = lattice->minSurfaceDist(coords); } /* If we reach a LocalCoord in a Universe, find the distance to the * nearest cell surface */ - else{ - Universe* universe = coords->getUniverse(); - dist = universe->minSurfaceDist(coords->getPoint(), angle); + else { + Cell* cell = coords->getCell(); + dist = cell->minSurfaceDist(coords); } /* Recheck min distance */ min_dist = std::min(dist, min_dist); - /* Ascend one level */ - if (coords->getUniverse() == _root_universe) - break; - else{ - coords = coords->getPrev(); - coords->prune(); - } + /* Descend one level */ + if (coords->getNext() == NULL) + break; + else + coords = coords->getNext(); } + coords = coords->getHighestLevel(); + coords->prune(); + /* Check for distance to nearest CMFD mesh cell boundary */ - if (_cmfd != NULL){ + if (_cmfd != NULL) { Lattice* lattice = _cmfd->getLattice(); - dist = lattice->minSurfaceDist(coords->getPoint(), angle); + dist = lattice->minSurfaceDist(coords); min_dist = std::min(dist, min_dist); } /* Move point and get next cell */ - double delta_x = cos(angle) * (min_dist + TINY_MOVE); - double delta_y = sin(angle) * (min_dist + TINY_MOVE); - coords->adjustCoords(delta_x, delta_y); + coords->adjustCoords(min_dist + TINY_MOVE); + return findCellContainingCoords(coords); } } @@ -539,57 +559,58 @@ CellBasic* Geometry::findNextCell(LocalCoords* coords, double angle) { */ int Geometry::findFSRId(LocalCoords* coords) { - int fsr_id = 0; + int fsr_id; LocalCoords* curr = coords; curr = coords->getLowestLevel(); - std::hash key_hash_function; /* Generate unique FSR key */ - std::size_t fsr_key_hash = key_hash_function(getFSRKey(coords)); + std::string fsr_key = getFSRKey(coords); /* If FSR has not been encountered, update FSR maps and vectors */ - if (_FSR_keys_map.find(fsr_key_hash) == _FSR_keys_map.end()){ - - /* Get the cell that contains coords */ - CellBasic* cell = findCellContainingCoords(curr); - - /* Get the lock */ - omp_set_lock(_num_FSRs_lock); - - /* Recheck to see if FSR has been added to maps after getting the lock */ - if (_FSR_keys_map.find(fsr_key_hash) != _FSR_keys_map.end()) - fsr_id = _FSR_keys_map.at(fsr_key_hash)._fsr_id; - else{ + if (!_FSR_keys_map.contains(fsr_key)) { + + /* Try to get a clean copy of the fsr_id, adding the FSR data + if necessary where -1 indicates the key was already added */ + fsr_id = _FSR_keys_map.insert_and_get_count(fsr_key, NULL); + if (fsr_id == -1) + { + fsr_data volatile* fsr; + do { + fsr = _FSR_keys_map.at(fsr_key); + } while (fsr == NULL); + fsr_id = fsr->_fsr_id; + } + else { - /* Add FSR information to FSR key map and FSR_to vectors */ - fsr_id = _num_FSRs; + /* Add FSR information to FSR key map and FSR_to vectors */ fsr_data* fsr = new fsr_data; fsr->_fsr_id = fsr_id; + _FSR_keys_map.update(fsr_key, fsr); Point* point = new Point(); - point->setCoords(coords->getHighestLevel()->getX(), - coords->getHighestLevel()->getY()); + point->setCoords(coords->getHighestLevel()->getX(), + coords->getHighestLevel()->getY(), + coords->getHighestLevel()->getZ()); + + /* Get the cell that contains coords */ + Cell* cell = findCellContainingCoords(curr); fsr->_point = point; - _FSR_keys_map[fsr_key_hash] = *fsr; - _FSRs_to_keys.push_back(fsr_key_hash); - _FSRs_to_material_IDs.push_back(cell->getMaterial()->getId()); - - /* If CMFD acceleration is on, add FSR to CMFD cell */ - if (_cmfd != NULL){ - int cmfd_cell = _cmfd->findCmfdCell(coords->getHighestLevel()); - _cmfd->addFSRToCell(cmfd_cell, fsr_id); - } + fsr->_mat_id = cell->getFillMaterial()->getId(); - /* Increment FSR counter */ - _num_FSRs++; + /* If CMFD acceleration is on, add FSR CMFD cell to FSR data */ + if (_cmfd != NULL) + fsr->_cmfd_cell = _cmfd->findCmfdCell(coords->getHighestLevel()); } + } - /* Release lock */ - omp_unset_lock(_num_FSRs_lock); + /* If FSR has already been encountered, get the fsr id from map */ + else { + fsr_data volatile* fsr; + do { + fsr = _FSR_keys_map.at(fsr_key); + } while (fsr == NULL); + fsr_id = fsr->_fsr_id; } - /* If FSR has already been encountered, get the fsr id from map */ - else - fsr_id = _FSR_keys_map.at(fsr_key_hash)._fsr_id; return fsr_id; } @@ -605,16 +626,14 @@ int Geometry::getFSRId(LocalCoords* coords) { int fsr_id = 0; std::string fsr_key; - std::hash key_hash_function; try{ fsr_key = getFSRKey(coords); - fsr_id = _FSR_keys_map.at(key_hash_function(fsr_key))._fsr_id; + fsr_id = _FSR_keys_map.at(fsr_key)->_fsr_id; } catch(std::exception &e) { log_printf(ERROR, "Could not find FSR ID with key: %s. Try creating " - "geometry with finer track laydown. " - "Backtrace:%s", fsr_key.c_str(), e.what()); + "geometry with finer track spacing", fsr_key.c_str()); } return fsr_id; @@ -631,11 +650,30 @@ Point* Geometry::getFSRPoint(int fsr_id) { Point* point; try{ - point = _FSR_keys_map.at(_FSRs_to_keys.at(fsr_id))._point; + point = _FSR_keys_map.at(_FSRs_to_keys.at(fsr_id))->_point; + } + catch(std::exception &e) { + log_printf(ERROR, "Could not find characteristic point in FSR: %d", fsr_id); + } + + return point; +} + + +/** + * @brief Return the centroid for a given FSR ID + * @param fsr_id the FSR ID + * @return the FSR's centroid + */ +Point* Geometry::getFSRCentroid(int fsr_id) { + + Point* point; + + try{ + point = _FSR_keys_map.at(_FSRs_to_keys.at(fsr_id))->_centroid; } catch(std::exception &e) { - log_printf(ERROR, "Could not find characteristic point in FSR: %i. " - "Backtrace:%s", fsr_id, e.what()); + log_printf(ERROR, "Could not find centroid in FSR: %d.", fsr_id); } return point; @@ -660,7 +698,7 @@ std::string Geometry::getFSRKey(LocalCoords* coords) { std::ostringstream curr_level_key; /* If CMFD is on, get CMFD latice cell and write to key */ - if (_cmfd != NULL){ + if (_cmfd != NULL) { curr_level_key << _cmfd->getLattice()->getLatX(curr->getPoint()); key << "CMFD = (" << curr_level_key.str() << ", "; curr_level_key.str(std::string()); @@ -670,7 +708,7 @@ std::string Geometry::getFSRKey(LocalCoords* coords) { /* Descend the linked list hierarchy until the lowest level has * been reached */ - while(curr != NULL){ + while (curr != NULL) { /* Clear string stream */ curr_level_key.str(std::string()); @@ -685,9 +723,12 @@ std::string Geometry::getFSRKey(LocalCoords* coords) { key << curr_level_key.str() << ", "; curr_level_key.str(std::string()); curr_level_key << curr->getLatticeY(); + key << curr_level_key.str() << ", "; + curr_level_key.str(std::string()); + curr_level_key << curr->getLatticeZ(); key << curr_level_key.str() << ") : "; } - else{ + else { /* write universe ID to key */ curr_level_key << curr->getUniverse()->getId(); key << "UNIV = " << curr_level_key.str() << " : "; @@ -713,8 +754,9 @@ std::string Geometry::getFSRKey(LocalCoords* coords) { /** - * @brief Subidivides all Cells in the Geometry into rings and angular sectors. - * @details This method is called by the Geometry::initializeFlatSourceRegions() + * @brief Subdivides all Cells in the Geometry into rings and angular sectors + * aligned with the z-axis. + * @details This method is called by the Geometry::initializeFSRs() * method but may also be called by the user in Python if needed: * * @code @@ -723,17 +765,14 @@ std::string Geometry::getFSRKey(LocalCoords* coords) { */ void Geometry::subdivideCells() { - std::map all_universes = _root_universe->getAllUniverses(); - std::map::iterator iter; - - std::map::iterator iter1; - std::map cells; + /* Compute the max radius as the distance from the center to a corner + * of the geometry. */ + double dx = getWidthX() / 2.0; + double dy = getWidthY() / 2.0; + double max_radius = sqrt(dx*dx + dy*dy); - /* Loop over all Universe in the Geometry and instruct each to inform - * their Cells to subdivide into rings and sectors as specified by - * the user during Cell instantiation */ - for (iter = all_universes.begin(); iter != all_universes.end(); ++iter) - (*iter).second->subdivideCells(); + /* Recursively subdivide Cells into rings and sectors */ + _root_universe->subdivideCells(max_radius); } @@ -743,19 +782,16 @@ void Geometry::subdivideCells() { * @details This method is intended to be called by the user before initiating * source iteration. This method first subdivides all Cells by calling * the Geometry::subdivideCells() method. Then it initializes the CMFD - * object. + * object. + * @brief neighbor_cells whether to use neighbor cell optimizations */ -void Geometry::initializeFlatSourceRegions() { - +void Geometry::initializeFSRs(bool neighbor_cells) { /* Subdivide Cells into sectors and rings */ subdivideCells(); - /* Create map of Material IDs to Material pointers */ - _all_materials = getAllMaterials(); - - /* Initialize CMFD */ - if (_cmfd != NULL) - initializeCmfd(); + /* Build collections of neighbor Cells for optimized ray tracing */ + if (neighbor_cells) + _root_universe->buildNeighbors(); } @@ -766,157 +802,148 @@ void Geometry::initializeFlatSourceRegions() { * intersection points with FSRs as the Track crosses through the * Geometry and creates segment structs and adds them to the Track. * @param track a pointer to a track to segmentize - * @param max_optical_length the maximum optical length a segment is allowed to - * have */ -void Geometry::segmentize(Track* track, FP_PRECISION max_optical_length) { +void Geometry::segmentize(Track* track) { /* Track starting Point coordinates and azimuthal angle */ double x0 = track->getStart()->getX(); double y0 = track->getStart()->getY(); + double z0 = track->getStart()->getZ(); double phi = track->getPhi(); + double delta_x, delta_y; /* Length of each segment */ - FP_PRECISION segment_length; - Material* segment_material; + FP_PRECISION length; + Material* material; int fsr_id; - FP_PRECISION* sigma_t; - int min_num_segments; int num_segments; - int num_groups; /* Use a LocalCoords for the start and end of each segment */ - LocalCoords segment_start(x0, y0); - LocalCoords segment_end(x0, y0); - segment_start.setUniverse(_root_universe); - segment_end.setUniverse(_root_universe); + LocalCoords start(x0, y0, z0); + LocalCoords end(x0, y0, z0); + start.setUniverse(_root_universe); + end.setUniverse(_root_universe); + start.setPhi(phi); + end.setPhi(phi); /* Find the Cell containing the Track starting Point */ - Cell* curr = findFirstCell(&segment_end, phi); + Cell* curr = findFirstCell(&end); Cell* prev; /* If starting Point was outside the bounds of the Geometry */ if (curr == NULL) - log_printf(ERROR, "Could not find a Cell containing the start Point " - "of this Track: %s", track->toString().c_str()); + log_printf(ERROR, "Could not find a material-filled Cell containing the " + "start Point of this Track: %s", track->toString().c_str()); /* While the end of the segment's LocalCoords is still within the Geometry, * move it to the next Cell, create a new segment, and add it to the * Geometry */ while (curr != NULL) { - segment_end.copyCoords(&segment_start); + end.copyCoords(&start); + end.setPhi(phi); /* Find the next Cell along the Track's trajectory */ prev = curr; - curr = findNextCell(&segment_end, phi); - - /* Checks to make sure that new Segment does not have the same start - * and end Points */ - if (segment_start.getX() == segment_end.getX() && - segment_start.getY() == segment_end.getY()) { - - log_printf(ERROR, "Created a Track segment with the same start and end " - "point: x = %f, y = %f", segment_start.getX(), - segment_start.getY()); - } - - /* Find the segment length between the segment's start and end points */ - segment_length = FP_PRECISION(segment_end.getPoint() - ->distanceToPoint(segment_start.getPoint())); - segment_material = static_cast(prev)->getMaterial(); - sigma_t = segment_material->getSigmaT(); - - /* Find the ID of the FSR that contains the segment */ - fsr_id = findFSRId(&segment_start); - - /* Compute the number of Track segments to cut this segment into to ensure - * that it's length is small enough for the exponential table */ - min_num_segments = 1; - num_groups = segment_material->getNumEnergyGroups(); - for (int g=0; g < num_groups; g++) { - num_segments = ceil(segment_length * sigma_t[g] / max_optical_length); - if (num_segments > min_num_segments) - min_num_segments = num_segments; - } + curr = findNextCell(&end); - /* "Cut up" Track segment into sub-segments such that the length of each - * does not exceed the size of the exponential table in the Solver */ - for (int i=0; i < min_num_segments; i++) { + /* Checks that segment does not have the same start and end Points */ + if (start.getX() == end.getX() && start.getY() == end.getY()) + log_printf(ERROR, "Created segment with same start and end " + "point: x = %f, y = %f", start.getX(), start.getY()); - /* Create a new Track segment */ - segment* new_segment = new segment; - new_segment->_material = segment_material; - new_segment->_length = segment_length / FP_PRECISION(min_num_segments); + /* Find the segment length, Material and FSR ID */ + length = FP_PRECISION(end.getPoint()->distanceToPoint(start.getPoint())); + material = prev->getFillMaterial(); + fsr_id = findFSRId(&start); - /* Update the max and min segment lengths */ - if (segment_length > _max_seg_length) - _max_seg_length = segment_length; - if (segment_length < _min_seg_length) - _min_seg_length = segment_length; + /* Create a new Track segment */ + segment* new_segment = new segment; + new_segment->_material = material; + new_segment->_length = length; + new_segment->_region_id = fsr_id; - log_printf(DEBUG, "segment start x = %f, y = %f, segment end " - "x = %f, y = %f", segment_start.getX(), segment_start.getY(), - segment_end.getX(), segment_end.getY()); + log_printf(DEBUG, "segment start x = %f, y = %f; end x = %f, y = %f", + start.getX(), start.getY(), end.getX(), end.getY()); - new_segment->_region_id = fsr_id; + /* Save indicies of CMFD Mesh surfaces that the Track segment crosses */ + if (_cmfd != NULL) { - /* Save indicies of CMFD Mesh surfaces that the Track segment crosses */ - if (_cmfd != NULL){ + /* Find cmfd cell that segment lies in */ + int cmfd_cell = _cmfd->findCmfdCell(&start); - /* Find cmfd cell that segment lies in */ - int cmfd_cell = _cmfd->findCmfdCell(&segment_start); + /* Reverse nudge from surface to determine whether segment start or end + * points lie on a CMFD surface. */ + start.adjustCoords(-TINY_MOVE); + end.adjustCoords(-TINY_MOVE); - /* Reverse nudge from surface to determine whether segment start or end - * points lie on a cmfd surface. */ - double delta_x = cos(phi) * TINY_MOVE; - double delta_y = sin(phi) * TINY_MOVE; - segment_start.adjustCoords(-delta_x, -delta_y); - segment_end.adjustCoords(-delta_x, -delta_y); - - if (i == min_num_segments-1) - new_segment->_cmfd_surface_fwd = - _cmfd->findCmfdSurface(cmfd_cell, &segment_end); - else - new_segment->_cmfd_surface_fwd = -1; - - if (i == 0) - new_segment->_cmfd_surface_bwd = - _cmfd->findCmfdSurface(cmfd_cell, &segment_start); - else - new_segment->_cmfd_surface_bwd = -1; - - /* Re-nudge segments from surface. */ - segment_start.adjustCoords(delta_x, delta_y); - segment_end.adjustCoords(delta_x, delta_y); - - } - - /* Add the segment to the Track */ - track->addSegment(new_segment); + new_segment->_cmfd_surface_fwd = _cmfd->findCmfdSurface(cmfd_cell, &end); + new_segment->_cmfd_surface_bwd = + _cmfd->findCmfdSurface(cmfd_cell, &start); + /* Re-nudge segments from surface */ + start.adjustCoords(TINY_MOVE); + end.adjustCoords(TINY_MOVE); } + + /* Add the segment to the Track */ + track->addSegment(new_segment); } log_printf(DEBUG, "Created %d segments for Track: %s", track->getNumSegments(), track->toString().c_str()); /* Truncate the linked list for the LocalCoords */ - segment_start.prune(); - segment_end.prune(); + start.prune(); + end.prune(); +} - log_printf(DEBUG, "Track %d max. segment length: %f", - track->getUid(), _max_seg_length); - log_printf(DEBUG, "Track %d min. segment length: %f", - track->getUid(), _min_seg_length); - return; +/** + * @brief Initialize key and material ID vectors for lookup by FSR ID + * @detail This function initializes and sets reverse lookup vectors by FSR ID. + * This is called after the FSRs have all been identified and allocated + * during segmentation. This function must be called after + * Geometry::segmentize() has completed. It should not be called if tracks + * are loaded from a file. + */ +void Geometry::initializeFSRVectors() { + + /* get keys and values from map */ + std::string *key_list = _FSR_keys_map.keys(); + fsr_data **value_list = _FSR_keys_map.values(); + + /* allocate vectors */ + int num_FSRs = _FSR_keys_map.size(); + _FSRs_to_keys = std::vector(num_FSRs); + + /* fill vectors key and material ID information */ +#pragma omp parallel for + for (int i=0; i < num_FSRs; i++) { + std::string key = key_list[i]; + fsr_data* fsr = value_list[i]; + int fsr_id = fsr->_fsr_id; + _FSRs_to_keys.at(fsr_id) = key; + } + + /* add cmfd information serially */ + if (_cmfd != NULL) { + for (int i=0; i < num_FSRs; i++) { + fsr_data* fsr = value_list[i]; + int fsr_id = fsr->_fsr_id; + _cmfd->addFSRToCell(fsr->_cmfd_cell, fsr_id); + } + } + + /* Delete key and value lists */ + delete[] key_list; + delete[] value_list; } /** * @brief Determines the fissionability of each Universe within this Geometry. - * @details A Universe is determined fissionable if it contains a CellBasic + * @details A Universe is determined fissionable if it contains a Cell * filled by a Material with a non-zero fission cross-section. Note * that this method recurses through all Universes at each level in * the nested Universe hierarchy. Users should only call this method @@ -985,27 +1012,54 @@ void Geometry::computeFissionability(Universe* univ) { /** * @brief Converts this Geometry's attributes to a character array. - * @details This method calls the toString() method for all Materials, - * Surfaces, Cell, Universes and Lattices contained by the Geometry. + * @details This method calls the toString() method for all Surfaces, + * Cells, Universes and Lattices contained by the Geometry. + * Since this routine provides the metadata used by the + * TrackGenerator to discriminate between geometries when + * exporting / importing binary track files. * @return a character array of this Geometry's class attributes */ std::string Geometry::toString() { std::stringstream string; - std::map all_cells = _root_universe->getAllCells(); - std::map all_universes = _root_universe->getAllUniverses(); + std::map cells = getAllCells(); + std::map universes = getAllUniverses(); + std::map surfaces; std::map::iterator cell_iter; std::map::iterator univ_iter; + std::map::iterator surf_iter; + /** Add string data for all Cells */ string << "\n\tCells:\n\t\t"; - for (cell_iter = all_cells.begin(); cell_iter != all_cells.end(); ++cell_iter) - string << cell_iter->second->toString() << "\n\t\t"; + for (cell_iter = cells.begin(); cell_iter != cells.end(); ++cell_iter) { + string << "Cell ID = " << cell_iter->second->getId(); + string << ", name = " << cell_iter->second->getName(); + + if (cell_iter->second->isRotated()) { + string << ", (rotation = " << cell_iter->second->getPhi() << ", "; + string << cell_iter->second->getTheta() << ", "; + string << cell_iter->second->getPsi() << ")"; + } + if (cell_iter->second->isTranslated()) { + double* translation = cell_iter->second->getTranslation(); + string << ", (translation = " << translation[0] << ", "; + string << translation[1] << ", " << translation[2] << ")"; + } + + string << ", # surfaces = " << cell_iter->second->getNumSurfaces(); + + /** Add string data for the Surfaces in this Cell */ + surfaces = cell_iter->second->getSurfaces(); + string << ", Surfaces: "; + for (surf_iter = surfaces.begin(); surf_iter != surfaces.end(); ++surf_iter) + string << surf_iter->second->_surface->toString() << ", "; + } + /** Add string data for all Universes */ string << "\n\tUniverses:\n\t\t"; - for (univ_iter = all_universes.begin(); - univ_iter != all_universes.end(); ++univ_iter) + for (univ_iter = universes.begin(); univ_iter != universes.end(); ++univ_iter) string << univ_iter->second->toString() << "\n\t\t"; std::string formatted_string = string.str(); @@ -1030,53 +1084,35 @@ void Geometry::printString() { * @brief This is a method that initializes the CMFD Lattice and sets * CMFD parameters. */ -void Geometry::initializeCmfd(){ - - /* Get information about geometry and CMFD mesh */ - int num_x = _cmfd->getNumX(); - int num_y = _cmfd->getNumY(); - double height = getHeight(); - double width = getWidth(); - double cell_width = width / num_x; - double cell_height = height / num_y; - - /* Create CMFD lattice and set properties */ - Lattice* lattice = new Lattice(); - lattice->setWidth(cell_width, cell_height); - lattice->setNumX(num_x); - lattice->setNumY(num_y); - lattice->setOffset(getMinX() + getWidth()/2.0, - getMinY() + getHeight()/2.0); - _cmfd->setLattice(lattice); - +void Geometry::initializeCmfd() { /* Set CMFD mesh boundary conditions */ - _cmfd->setBoundary(0, getMinXBoundaryType()); - _cmfd->setBoundary(1, getMinYBoundaryType()); - _cmfd->setBoundary(2, getMaxXBoundaryType()); - _cmfd->setBoundary(3, getMaxYBoundaryType()); + _cmfd->setBoundary(SURFACE_X_MIN, getMinXBoundaryType()); + _cmfd->setBoundary(SURFACE_Y_MIN, getMinYBoundaryType()); + _cmfd->setBoundary(SURFACE_X_MAX, getMaxXBoundaryType()); + _cmfd->setBoundary(SURFACE_Y_MAX, getMaxYBoundaryType()); /* Set CMFD mesh dimensions and number of groups */ - _cmfd->setWidth(width); - _cmfd->setHeight(height); - _cmfd->setNumMOCGroups(getNumEnergyGroups()); - - /* If user did not set CMFD group structure, create CMFD group - * structure that is the same as the MOC group structure */ - if (_cmfd->getNumCmfdGroups() == 0) - _cmfd->setGroupStructure(NULL, getNumEnergyGroups()+1); + _cmfd->setWidthX(getWidthX()); + _cmfd->setWidthY(getWidthY()); - /* Intialize CMFD Maps */ + /* Intialize CMFD cell map */ _cmfd->initializeCellMap(); - _cmfd->initializeGroupMap(); + + /* Initialize the CMFD lattice */ + Point offset; + offset.setX(getMinX() + getWidthX()/2.0); + offset.setY(getMinY() + getWidthY()/2.0); + + _cmfd->initializeLattice(&offset); } /** - * @brief Returns the map that maps FSR keys to FSR IDs - * @return _FSR_keys_map map of FSR keys to FSR IDs + * @brief Returns a pointer to the map that maps FSR keys to FSR IDs + * @return pointer to _FSR_keys_map map of FSR keys to FSR IDs */ -std::unordered_map Geometry::getFSRKeysMap(){ +ParallelHashMap& Geometry::getFSRKeysMap() { return _FSR_keys_map; } @@ -1085,71 +1121,62 @@ std::unordered_map Geometry::getFSRKeysMap(){ * @brief Returns the vector that maps FSR IDs to FSR key hashes * @return _FSR_keys_map map of FSR keys to FSR IDs */ -std::vector Geometry::getFSRsToKeys(){ +std::vector& Geometry::getFSRsToKeys() { return _FSRs_to_keys; } /** - * @brief Return a vector indexed by flat source region IDs which contain - * the corresponding Material IDs. - * @return an integer vector of FSR-to-Material IDs indexed by FSR ID + * @brief Determins whether a point is within the bounding box of the geometry. + * @param coords a populated LocalCoords linked list + * @return boolean indicating whether the coords is within the geometry */ -std::vector Geometry::getFSRsToMaterialIDs() { - if (_num_FSRs == 0) - log_printf(ERROR, "Unable to return the FSR-to-Material map array since " - "the Geometry has not initialized FSRs."); +bool Geometry::withinBounds(LocalCoords* coords) { + + double x = coords->getX(); + double y = coords->getY(); + double z = coords->getZ(); - return _FSRs_to_material_IDs; + if (x < getMinX() || x > getMaxX() || y < getMinY() || y > getMaxY() + || z < getMinZ() || z > getMaxZ()) + return false; + else + return true; } /** - * @brief Sets the _FSR_keys_map map + * @brief Sets the centroid for an FSR * @details The _FSR_keys_map stores a hash of a std::string representing * the Lattice/Cell/Universe hierarchy for a unique region - * and the associated FSR data. fsr_data is a struct that contains - * a unique FSR id and a Point located in the highest level Universe - * that is contained in the FSR. This method is used when the tracks - * are read from file to avoid unnecessary segmentation. - * @param FSR_keys_map map of FSR keys to FSR data + * and the associated FSR data. _centroid is a point that represents + * the numerical centroid of an FSR computed using all segments + * contained in the FSR. This method is used by the TrackGenerator + * to set the centroid after segments have been created. It is + * important to note that this method is a helper function for the + * TrackGenerator and should not be explicitly called by the user. + * @param fsr a FSR ID + * @param centroid a Point representing the FSR centroid */ -void Geometry::setFSRKeysMap(std::unordered_map - FSR_keys_map){ - _FSR_keys_map = FSR_keys_map; +void Geometry::setFSRCentroid(int fsr, Point* centroid) { + _FSR_keys_map.at(_FSRs_to_keys[fsr])->_centroid = centroid; } /** - * @brief Sets the _FSRs_to_keys vector - * @param FSRs_to_keys vector of FSR key hashes indexed by FSR IDs + * @brief Finds the Cell containing a given fsr ID. + * @param fsr_id an FSR ID. */ -void Geometry::setFSRsToKeys(std::vector FSRs_to_keys){ - _FSRs_to_keys = FSRs_to_keys; -} +Cell* Geometry::findCellContainingFSR(int fsr_id) { + Point* point = _FSR_keys_map.at(_FSRs_to_keys[fsr_id])->_point; + LocalCoords* coords = new LocalCoords(point->getX(), point->getY(), + point->getZ()); + coords->setUniverse(_root_universe); + Cell* cell = findCellContainingCoords(coords); -/** - * @brief Sets the _FSRs_to_material_IDs vector - * @param FSRs_to_material_IDs vector mapping FSR IDs to cells - */ -void Geometry::setFSRsToMaterialIDs(std::vector FSRs_to_material_IDs){ - _FSRs_to_material_IDs = FSRs_to_material_IDs; -} - + coords->prune(); + delete coords; -/** - * @brief Determins whether a point is within the bounding box of the geometry. - * @param coords a populated LocalCoords linked list - * @return boolean indicating whether the coords is within the geometry - */ -bool Geometry::withinBounds(LocalCoords* coords){ - - double x = coords->getX(); - double y = coords->getY(); - - if (x < getMinX() || x > getMaxX() || y < getMinY() || y > getMaxY()) - return false; - else - return true; + return cell; } diff --git a/src/Geometry.h b/src/Geometry.h index 6fcc4b167..a5315e713 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -9,7 +9,10 @@ #define GEOMETRY_H_ #ifdef __cplusplus -#include +#ifdef SWIG +#include "Python.h" +#endif +#include "Cmfd.h" #include #include #include @@ -17,12 +20,11 @@ #include #include #include -#include "Cmfd.h" -#ifndef CUDA - #include -#endif +#include "ParallelHashMap.h" #endif +/** Forward declaration of Cmfd class */ +class Cmfd; /** * @struct fsr_data @@ -36,9 +38,32 @@ struct fsr_data { /** The FSR ID */ int _fsr_id; - /** Characteristic point in Universe 0 that lies in FSR */ + /** The CMFD Cell */ + int _cmfd_cell; + + /** The Material ID */ + int _mat_id; + + /** Characteristic point in Root Universe that lies in FSR */ Point* _point; + /** Global numerical centroid in Root Universe */ + Point* _centroid; + + /** Constructor for FSR data initializes centroids and points to NULL */ + fsr_data() { + _centroid = NULL; + _point = NULL; + } + + /** Destructor for fsr_data */ + ~fsr_data() { + if (_point != NULL) + delete _point; + + if (_centroid != NULL) + delete _centroid; + } }; void reset_auto_ids(); @@ -57,43 +82,27 @@ class Geometry { private: - omp_lock_t* _num_FSRs_lock; + /** The boundary conditions at the x-min surface of the bounding box + * containing the Geometry. */ + boundaryType _x_min_bc; - /** The boundary conditions at the top of the bounding box containing - * the Geometry. False is for vacuum and true is for reflective BCs. */ - boundaryType _top_bc; + /** The boundary conditions at the y-min surface of the bounding box + * containing the Geometry. */ + boundaryType _y_min_bc; - /** The boundary conditions at the top of the bounding box containing - * the Geometry. False is for vacuum and true is for reflective BCs. */ - boundaryType _bottom_bc; + /** The boundary conditions at the x-max surface of the bounding box + * containing the Geometry. */ + boundaryType _x_max_bc; - /** The boundary conditions at the top of the bounding box containing - * the Geometry. False is for vacuum and true is for reflective BCs. */ - boundaryType _left_bc; - - /** The boundary conditions at the top of the bounding box containing - * the Geometry. False is for vacuum and true is for reflective BCs. */ - boundaryType _right_bc; - - /** The total number of FSRs in the Geometry */ - int _num_FSRs; + /** The boundary conditions at the y-max surface of the bounding box + * containing the Geometry. */ + boundaryType _y_max_bc; /** An map of FSR key hashes to unique fsr_data structs */ -#ifndef CUDA - std::unordered_map _FSR_keys_map; -#endif + ParallelHashMap _FSR_keys_map; /** An vector of FSR key hashes indexed by FSR ID */ - std::vector _FSRs_to_keys; - - /** A vector of Material IDs indexed by FSR IDs */ - std::vector _FSRs_to_material_IDs; - - /** The maximum Track segment length in the Geometry */ - double _max_seg_length; - - /** The minimum Track segment length in the Geometry */ - double _min_seg_length; + std::vector _FSRs_to_keys; /* The Universe at the root node in the CSG tree */ Universe* _root_universe; @@ -104,8 +113,8 @@ class Geometry { /* A map of all Material in the Geometry for optimization purposes */ std::map _all_materials; - CellBasic* findFirstCell(LocalCoords* coords, double angle); - CellBasic* findNextCell(LocalCoords* coords, double angle); + Cell* findFirstCell(LocalCoords* coords); + Cell* findNextCell(LocalCoords* coords); public: @@ -113,8 +122,9 @@ class Geometry { virtual ~Geometry(); /* Get parameters */ - double getWidth(); - double getHeight(); + double getWidthX(); + double getWidthY(); + double getWidthZ(); double getMinX(); double getMaxX(); double getMinY(); @@ -125,48 +135,41 @@ class Geometry { boundaryType getMaxXBoundaryType(); boundaryType getMinYBoundaryType(); boundaryType getMaxYBoundaryType(); - boundaryType getMinZBoundaryType(); - boundaryType getMaxZBoundaryType(); Universe* getRootUniverse(); int getNumFSRs(); int getNumEnergyGroups(); int getNumMaterials(); int getNumCells(); std::map getAllMaterials(); + std::map getAllSurfaces(); + std::map getAllCells(); std::map getAllMaterialCells(); + std::map getAllUniverses(); void setRootUniverse(Universe* root_universe); - double getMaxSegmentLength(); - double getMinSegmentLength(); Cmfd* getCmfd(); - std::vector getFSRsToKeys(); - std::vector getFSRsToMaterialIDs(); + std::vector& getFSRsToKeys(); int getFSRId(LocalCoords* coords); Point* getFSRPoint(int fsr_id); + Point* getFSRCentroid(int fsr_id); std::string getFSRKey(LocalCoords* coords); -#ifndef CUDA - std::unordered_map getFSRKeysMap(); -#endif + ParallelHashMap& getFSRKeysMap(); /* Set parameters */ - void setFSRsToMaterialIDs(std::vector FSRs_to_material_IDs); - void setFSRsToKeys(std::vector FSRs_to_keys); - void setNumFSRs(int num_fsrs); void setCmfd(Cmfd* cmfd); - -#ifndef CUDA - void setFSRKeysMap(std::unordered_map FSR_keys_map); -#endif + void setFSRCentroid(int fsr, Point* centroid); /* Find methods */ - CellBasic* findCellContainingCoords(LocalCoords* coords); + Cell* findCellContainingCoords(LocalCoords* coords); Material* findFSRMaterial(int fsr_id); int findFSRId(LocalCoords* coords); + Cell* findCellContainingFSR(int fsr_id); /* Other worker methods */ void subdivideCells(); - void initializeFlatSourceRegions(); - void segmentize(Track* track, FP_PRECISION max_optical_length); + void initializeFSRs(bool neighbor_cells=false); + void segmentize(Track* track); + void initializeFSRVectors(); void computeFissionability(Universe* univ=NULL); std::string toString(); diff --git a/src/LocalCoords.cpp b/src/LocalCoords.cpp index 3be8a2e47..6d7083ec6 100644 --- a/src/LocalCoords.cpp +++ b/src/LocalCoords.cpp @@ -5,8 +5,12 @@ * @param x the x-coordinate * @param y the y-coordinate */ -LocalCoords::LocalCoords(double x, double y) { - _coords.setCoords(x, y); +LocalCoords::LocalCoords(double x, double y, double z) { + _coords.setCoords(x, y, z); + _phi = 0.; + _universe = NULL; + _lattice = NULL; + _cell = NULL; _next = NULL; _prev = NULL; } @@ -73,6 +77,16 @@ int LocalCoords::getLatticeY() const { } +/** + * @brief Return the third index of the Lattice cell within which this + * LocalCoords resides. + * @return the third Lattice cell index + */ +int LocalCoords::getLatticeZ() const { + return _lattice_z; +} + + /** * @brief Returns the x-coordinate for this LocalCoords location. * @return the x-coordinate of this LocalCoords location @@ -91,6 +105,24 @@ double LocalCoords::getY() const { } +/** + * @brief Returns the z-coordinate for this LocalCoords location. + * @return the z-coordinate of this LocalCoords location + */ +double LocalCoords::getZ() const { + return _coords.getZ(); +} + + +/** + * @brief Returns the direction angle in radians with respect to the x-axis. + * @return the direction angle in radians + */ +double LocalCoords::getPhi() const { + return _phi; +} + + /** * @brief Returns a pointer to the Point containing the coordinates for this * LocalCoord. @@ -158,9 +190,9 @@ void LocalCoords::setLattice(Lattice* lattice) { /** - * @brief Sets the row index for the Lattice cell within which this + * @brief Sets the x index for the Lattice cell within which this * LocalCoords resides. - * @param lattice_x the row Lattice cell index + * @param lattice_x the x Lattice cell index */ void LocalCoords::setLatticeX(int lattice_x) { _lattice_x = lattice_x; @@ -168,15 +200,25 @@ void LocalCoords::setLatticeX(int lattice_x) { /** - * @brief Sets the column index for the Lattice cell within which this + * @brief Sets the y index for the Lattice cell within which this * LocalCoords resides. - * @param lattice_y the column Lattice cell index + * @param lattice_y the y Lattice cell index */ void LocalCoords::setLatticeY(int lattice_y) { _lattice_y = lattice_y; } +/** + * @brief Sets the z index for the Lattice cell within which this + * LocalCoords resides. + * @param lattice_z the z Lattice cell index + */ +void LocalCoords::setLatticeZ(int lattice_z) { + _lattice_z = lattice_z; +} + + /** * @brief Set the x-coordinate for this LocalCoords. * @param x the x-coordinate @@ -195,6 +237,33 @@ void LocalCoords::setY(double y) { } +/** + * @brief Set the z-coordinate for this Localcoords. + * @param z the z-coordinate + */ +void LocalCoords::setZ(double z) { + _coords.setZ(z); +} + + +/** + * @brief Set the direction angle in radians for this LocalCoords. + * @param angle the direction angle in radians + */ +void LocalCoords::setPhi(double phi) { + _phi = phi; +} + + +/** + * @brief Increment the direction angle in radians for this LocalCoords. + * @param phi the incremental direction angle in radians + */ +void LocalCoords::incrementPhi(double phi) { + _phi += phi; +} + + /** * @brief Sets the pointer to the LocalCoords on the next lower nested Universe * level. @@ -258,27 +327,16 @@ LocalCoords* LocalCoords::getHighestLevel() { * the linked list. * @details This method will traverse the entire linked list and apply the * translation to each element. - * @param delta_x amount we wish to move x by - * @param delta_y amount we wish to move y by + * @param delta amount we wish to move the point by */ -void LocalCoords::adjustCoords(double delta_x, double delta_y) { - - /* Forward direction along linked list */ - LocalCoords* curr = this; - while (curr != NULL) { - curr->setX(curr->getX() + delta_x); - curr->setY(curr->getY() + delta_y); - curr = curr->getNext(); - } - - /* Reverse direction along linked list */ - curr = _prev; - while (curr != NULL) { - curr->setX(curr->getX() + delta_x); - curr->setY(curr->getY() + delta_y); - curr = curr->getPrev(); - } - return; +void LocalCoords::adjustCoords(double delta) { + double new_x = getX() + cos(_phi) * delta; + double new_y = getY() + sin(_phi) * delta; + setX(new_x); + setY(new_y); + + if (_next != NULL) + _next->adjustCoords(delta); } @@ -296,7 +354,8 @@ void LocalCoords::updateMostLocal(Point* point) { /* Translate coordinates by appropriate amount */ double delta_x = point->getX() - curr->getX(); double delta_y = point->getY() - curr->getY(); - adjustCoords(delta_x, delta_y); + double delta = sqrt(delta_x*delta_x + delta_y*delta_y); + adjustCoords(delta); return; } @@ -343,6 +402,8 @@ void LocalCoords::copyCoords(LocalCoords* coords) { while (curr1 != NULL) { curr2->setX(curr1->getX()); curr2->setY(curr1->getY()); + curr2->setZ(curr1->getZ()); + curr2->setPhi(curr1->getPhi()); curr2->setUniverse(curr1->getUniverse()); if (curr1->getType() == UNIV) { @@ -353,13 +414,14 @@ void LocalCoords::copyCoords(LocalCoords* coords) { curr2->setLattice(curr1->getLattice()); curr2->setLatticeX(curr1->getLatticeX()); curr2->setLatticeY(curr1->getLatticeY()); + curr2->setLatticeZ(curr1->getLatticeZ()); curr2->setType(LAT); } curr1 = curr1->getNext(); if (curr1 != NULL && curr2->getNext() == NULL) { - LocalCoords* new_coords = new LocalCoords(0.0, 0.0); + LocalCoords* new_coords = new LocalCoords(0.0, 0.0, 0.0); curr2->setNext(new_coords); new_coords->setPrev(curr2); curr2 = new_coords; @@ -391,24 +453,29 @@ std::string LocalCoords::toString() { if (curr->getType() == UNIV) { string << " UNIVERSE, x = " << curr->getX() << ", y = " << curr->getY() + << ", z = " << curr->getZ() << ", universe = " << curr->getUniverse()->getId() << ", cell = " << curr->getCell()->getId(); } - else if (curr->getType() == LAT){ + else if (curr->getType() == LAT) { string << " LATTICE, x = " << curr->getX() << ", y = " << curr->getY() + << ", z = " << curr->getZ() << ", universe = " << curr->getUniverse()->getId() << ", lattice = " << curr->getLattice()->getId() << ", lattice_x = " << curr->getLatticeX() - << ", lattice_y = " << curr->getLatticeY(); + << ", lattice_y = " << curr->getLatticeY() + << ", lattice_z = " << curr->getLatticeZ(); } else { string << " NONE, x = " << curr->getX() << ", y = " << curr->getY() + << ", z = " << curr->getZ() << ", universe = " << curr->getUniverse()->getId() << ", lattice = " << curr->getLattice()->getId() << ", lattice_x = " << curr->getLatticeX() << ", lattice_y = " << curr->getLatticeY() + << ", lattice_z = " << curr->getLatticeZ() << ", cell = " << curr->getCell(); } diff --git a/src/LocalCoords.h b/src/LocalCoords.h index b461ef583..06a0747d0 100644 --- a/src/LocalCoords.h +++ b/src/LocalCoords.h @@ -9,6 +9,9 @@ #define LOCALCOORDS_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif #include "Point.h" #include "Universe.h" #include "Cell.h" @@ -60,9 +63,16 @@ class LocalCoords { * resides */ int _lattice_y; - /** A Point representing the 2D coordinates of this LocalCoords */ + /** The third index of the Lattice cell within which this LocalCoords + * resides */ + int _lattice_z; + + /** A Point representing the 3D coordinates of this LocalCoords */ Point _coords; + /** The direction angle in radians with respect to the x-axis */ + double _phi; + /** A pointer to the LocalCoords at the next lower nested Universe level */ LocalCoords* _next; @@ -70,7 +80,7 @@ class LocalCoords { LocalCoords* _prev; public: - LocalCoords(double x, double y); + LocalCoords(double x, double y, double z); virtual ~LocalCoords(); coordType getType(); Universe* getUniverse() const; @@ -78,8 +88,11 @@ class LocalCoords { Lattice* getLattice() const; int getLatticeX() const; int getLatticeY() const; + int getLatticeZ() const; double getX() const; double getY() const; + double getZ() const; + double getPhi() const; Point* getPoint(); LocalCoords* getNext() const; LocalCoords* getPrev() const; @@ -90,14 +103,18 @@ class LocalCoords { void setLattice(Lattice* lattice); void setLatticeX(int lattice_x); void setLatticeY(int lattice_y); + void setLatticeZ(int lattice_z); void setX(double x); void setY(double y); + void setZ(double z); + void setPhi(double phi); + void incrementPhi(double phi); void setNext(LocalCoords *next); void setPrev(LocalCoords* coords); LocalCoords* getLowestLevel(); LocalCoords* getHighestLevel(); - void adjustCoords(double delta_x, double delta_y); + void adjustCoords(double delta); void updateMostLocal(Point* point); void prune(); void copyCoords(LocalCoords* coords); diff --git a/src/Material.cpp b/src/Material.cpp index 5f092238d..be4be2782 100644 --- a/src/Material.cpp +++ b/src/Material.cpp @@ -1,6 +1,6 @@ #include "Material.h" -static int auto_id = 10000; +static int auto_id = DEFAULT_INIT_ID; /** @@ -23,7 +23,22 @@ int material_id() { * @brief Resets the auto-generated unique Material ID counter to 10000. */ void reset_material_id() { - auto_id = 10000; + auto_id = DEFAULT_INIT_ID; +} + + +/** + * @brief Maximize the auto-generated unique Material ID counter. + * @details This method updates the auto-generated unique Material ID + * counter if the input parameter is greater than the present + * value. This is useful for the OpenCG compatibility module + * to ensure that the auto-generated Material IDs do not + * collide with those created in OpenCG. + * @param material_id the id assigned to the auto-generated counter + */ +void maximize_material_id(int material_id) { + if (material_id > auto_id) + auto_id = material_id; } @@ -45,16 +60,18 @@ Material::Material(int id, const char* name) { _name = NULL; setName(name); + _volume = 0.; + _num_instances = 0; + + /* Initialize a dummy number groups */ + _num_groups = -1; + _sigma_t = NULL; - _sigma_a = NULL; _sigma_s = NULL; _sigma_f = NULL; _nu_sigma_f = NULL; _chi = NULL; - _dif_coef = NULL; - _dif_hat = NULL; - _dif_tilde = NULL; - _buckling = NULL; + _fiss_matrix = NULL; _fissionable = false; @@ -77,9 +94,6 @@ Material::~Material() { if (_sigma_t != NULL) MM_FREE(_sigma_t); - if (_sigma_a != NULL) - MM_FREE(_sigma_a); - if (_sigma_s != NULL) MM_FREE(_sigma_s); @@ -92,20 +106,8 @@ Material::~Material() { if (_chi != NULL) MM_FREE(_chi); - /* Whomever SIMD'izes OpenMOC will need to properly free these - * using mm_free if they are vector aligned */ - if (_dif_coef != NULL) - delete [] _dif_coef; - - if (_dif_hat != NULL) - delete [] _dif_hat; - - if (_dif_tilde != NULL) - delete [] _dif_tilde; - - if (_buckling != NULL) - delete [] _buckling; - + if (_fiss_matrix != NULL) + MM_FREE(_fiss_matrix); } /* Data is not vector aligned */ @@ -113,9 +115,6 @@ Material::~Material() { if (_sigma_t != NULL) delete [] _sigma_t; - if (_sigma_a != NULL) - delete [] _sigma_a; - if (_sigma_s != NULL) delete [] _sigma_s; @@ -128,17 +127,8 @@ Material::~Material() { if (_chi != NULL) delete [] _chi; - if (_dif_coef != NULL) - delete [] _dif_coef; - - if (_dif_hat != NULL) - delete [] _dif_hat; - - if (_dif_tilde != NULL) - delete [] _dif_tilde; - - if (_buckling != NULL) - delete [] _buckling; + if (_fiss_matrix != NULL) + delete [] _fiss_matrix; } } @@ -161,6 +151,28 @@ char* Material::getName() const { } +/** + * @brief Return the aggregate volume/area of all instances of this Material. + * @details The volume/area of the Material is computed from track segments + * which overlap this Material during track generation. + * @return the volume/area of the Material + */ +double Material::getVolume() { + return _volume; +} + + +/** + * @brief Return the number of instances of this Material in the Geometry. + * @details The number of instances of this Material in the Geometry is + * determined during track generation. + * @return the number of material instances + */ +int Material::getNumInstances() { + return _num_instances; +} + + /** * @brief Returns the number of energy groups for this Material's nuclear data. * @return the number of energy groups @@ -183,20 +195,6 @@ FP_PRECISION* Material::getSigmaT() { } - -/** - * @brief Return the array of the Material's absorption cross-sections. - * @return the pointer to the Material's array of absorption cross-sections - */ -FP_PRECISION* Material::getSigmaA() { - if (_sigma_a == NULL) - log_printf(ERROR, "Unable to return Material %d's absorption " - "cross-section since it has not yet been set", _id); - - return _sigma_a; -} - - /** * @brief Return the array of the Material's scattering cross-section matrix. * @return the pointer to the Material's array of scattering cross-sections @@ -252,115 +250,33 @@ FP_PRECISION* Material::getChi() { /** - * @brief Return the array of the Material's diffusion coefficients. - * @return the pointer to the Material's array of diffusion coefficients + * @brief Return the array of the Material's fission matrix. + * @return the pointer to the Material's fission matrix array */ -FP_PRECISION* Material::getDifCoef() { - - if (_dif_coef == NULL){ - - _dif_coef = new FP_PRECISION[_num_groups]; +FP_PRECISION* Material::getFissionMatrix() { + if (_fiss_matrix == NULL) + log_printf(ERROR, "Unable to return Material %d's fission matrix " + "since it has not yet been built", _id); - for (int e = 0; e < _num_groups; e++) - _dif_coef[e] = 0.0; - } - - return _dif_coef; + return _fiss_matrix; } -/** - * @brief Return the array of the Material's surface diffusion coefficients. - * @details Returns the diffusion coefficients \f$ \hat{D} \f$ for this Material - * on each of the four surfaces of a CMFD mesh cell. - * @return the pointer to the Material's array of surface diffusion coefficients - */ -FP_PRECISION* Material::getDifHat() { - - if (_dif_hat == NULL){ - - _dif_hat = new FP_PRECISION[4*_num_groups]; - - for (int e = 0; e < 4*_num_groups; e++) - _dif_hat[e] = 0.0; - } - - return _dif_hat; -} - - -/** - * @brief Return the array of the Material's CMFD correction to the surface - * diffusion coefficients. - * @return the pointer to the Material's array of CMFD correction to the - * surface diffusion coefficients - */ -FP_PRECISION* Material::getDifTilde() { - - if (_dif_tilde == NULL){ - - _dif_tilde = new FP_PRECISION[4*_num_groups]; - - for (int e = 0; e < 4*_num_groups; e++) - _dif_tilde[e] = 0.0; - } - - return _dif_tilde; -} - - -/** - * @brief Return the array of the Material's CMFD correction to the surface - * diffusion coefficients. - * @return the pointer to the Material's array of CMFD correction to - * the surface diffusion coefficients - */ -FP_PRECISION* Material::getBuckling() { - - if (_buckling == NULL){ - - _buckling = new FP_PRECISION[_num_groups]; - - for (int e = 0; e < _num_groups; e++) - _buckling[e] = 0.0; - } - - return _buckling; -} - /** * @brief Get the Material's total cross section for some energy group. * @param group the energy group * @return the total cross section */ -FP_PRECISION Material::getSigmaTByGroup(int group) { +FP_PRECISION Material::getSigmaTByGroup(int group) { if (_sigma_t == NULL) log_printf(ERROR, "Unable to return Material %d's total " "cross section since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) + + else if (group <= 0 || group > _num_groups) log_printf(ERROR, "Unable to get sigma_t for group %d for Material " "%d which contains %d energy groups", group, _id, _num_groups); - - return _sigma_t[group-1]; -} - -/** - * @brief Get the Material's absorption cross section for some energy group. - * @param group the energy group - * @return the absorption cross section - */ -FP_PRECISION Material::getSigmaAByGroup(int group) { - if (_sigma_a == NULL) - log_printf(ERROR, "Unable to return Material %d's absorption " - "cross section since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get sigma_a for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - - return _sigma_a[group-1]; + return _sigma_t[group-1]; } @@ -370,18 +286,18 @@ FP_PRECISION Material::getSigmaAByGroup(int group) { * @param destination the outgoing energy group * @return the scattering cross section */ -FP_PRECISION Material::getSigmaSByGroup(int origin, int destination) { +FP_PRECISION Material::getSigmaSByGroup(int origin, int destination) { if (_sigma_s == NULL) log_printf(ERROR, "Unable to return Material %d's scattering " "cross section since it has not yet been set", _id); - - if (origin <= 0 || destination <= 0 || origin > _num_groups || destination > _num_groups) + + else if (origin <= 0 || destination <= 0 || + origin > _num_groups || destination > _num_groups) log_printf(ERROR, "Unable to get sigma_s for group %d,%d for Material %d " "which contains %d energy groups", origin, destination, _id, _num_groups); - - return getSigmaSByGroupInline(origin-1,destination-1); - + + return _sigma_s[(destination-1)*_num_groups + (origin-1)]; } @@ -390,17 +306,17 @@ FP_PRECISION Material::getSigmaSByGroup(int origin, int destination) { * @param group the energy group * @return the fission cross section */ -FP_PRECISION Material::getSigmaFByGroup(int group) { +FP_PRECISION Material::getSigmaFByGroup(int group) { if (_sigma_f == NULL) log_printf(ERROR, "Unable to return material %d's fission " "cross section since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) + + else if (group <= 0 || group > _num_groups) log_printf(ERROR, "Unable to get sigma_f for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - + "%d which contains %d energy groups", group, _id, _num_groups); + return _sigma_f[group-1]; -} +} /** @@ -408,17 +324,17 @@ FP_PRECISION Material::getSigmaFByGroup(int group) { * @param group the energy group * @return the nu-fission cross section */ -FP_PRECISION Material::getNuSigmaFByGroup(int group) { +FP_PRECISION Material::getNuSigmaFByGroup(int group) { if (_nu_sigma_f == NULL) log_printf(ERROR, "Unable to return Material %d's nu-fission " "cross section since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) + + else if (group <= 0 || group > _num_groups) log_printf(ERROR, "Unable to get nu_sigma_f for group %d for Material " "%d which contains %d energy groups", group, _id, _num_groups); - + return _nu_sigma_f[group-1]; -} +} /** @@ -426,93 +342,40 @@ FP_PRECISION Material::getNuSigmaFByGroup(int group) { * @param group the energy group * @return the fission spectrum */ -FP_PRECISION Material::getChiByGroup(int group) { +FP_PRECISION Material::getChiByGroup(int group) { if (_chi == NULL) log_printf(ERROR, "Unable to return Material %d's chi spectrum " "since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get chi for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - - return _chi[group-1]; -} - -/** - * @brief Get the Material's diffustion coefficient for some energy group. - * @param group the energy group - * @return the diffusion coefficient - */ -FP_PRECISION Material::getDifCoefByGroup(int group) { - if (_dif_coef == NULL) - log_printf(ERROR, "Unable to return Material %d's diffusion coefficient " - "since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get dif_coef for group %d for Material " + else if (group <= 0 || group > _num_groups) + log_printf(ERROR, "Unable to get chi for group %d for Material " "%d which contains %d energy groups", group, _id, _num_groups); - - return _dif_coef[group-1]; -} - -/** - * @brief Get the Material's dif_hat for some energy group. - * @param group the energy group - * @param surface the index of the surface - * @return the dif_hat value - */ -FP_PRECISION Material::getDifHatByGroup(int group, int surface) { - if (_dif_hat == NULL) - log_printf(ERROR, "Unable to return Material %d's dif_hat " - "since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get dif_hat for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - - return _dif_hat[surface*_num_groups + (group-1)]; + return _chi[group-1]; } /** - * @brief Get the Material's dif_tilde for some energy group. - * @param group the energy group - * @return the dif_tilde value + * @brief Get the Material's fission matrix for some energy group. + * @param origin the incoming energy group \f$ E_{0} \f$ + * @param destination the outgoing energy group \f$ E_{1} \f$ + * @return the fission matrix entry \f$ \nu\Sigma_{f}(E_{0}) * \chi(E_{1})\f$ */ -FP_PRECISION Material::getDifTildeByGroup(int group) { - if (_dif_tilde == NULL) - log_printf(ERROR, "Unable to return Material %d's dif_tilde " - "since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get dif_tilde for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - - return _dif_tilde[group-1]; -} - +FP_PRECISION Material::getFissionMatrixByGroup(int origin, int destination) { + if (_fiss_matrix == NULL) + log_printf(ERROR, "Unable to return Material %d's fission matrix " + "cross section since it has not yet been built", _id); + + else if (origin <= 0 || destination <= 0 || + origin > _num_groups || destination > _num_groups) + log_printf(ERROR, "Unable to get fission matrix for group %d,%d for " + "Material %d which contains %d energy groups", + origin, destination, _id, _num_groups); -/** - * @brief Get the Material's buckling for some energy group. - * @param group the energy group - * @return the buckling value - */ -FP_PRECISION Material::getBucklingByGroup(int group) { - if (_buckling == NULL) - log_printf(ERROR, "Unable to return Material %d's buckling " - "since it has not yet been set", _id); - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to get buckling for group %d for Material " - "%d which contains %d energy groups", group, _id, _num_groups); - - return _buckling[group-1]; + return _fiss_matrix[(destination-1)*_num_groups + (origin-1)]; } - /** * @brief Returns whether or not the Material contains a fissionable (non-zero) * fission cross-section. @@ -561,6 +424,45 @@ void Material::setName(const char* name) { } +/** + * @brief Set the volume/area of the Material. + * @param volume the volume/area of the Material + */ +void Material::setVolume(double volume) { + _volume = volume; +} + + +/** + * @brief Increment the volume/area of the Material by some amount. + * @details This routine is called by the TrackGenerator during track + * generation and segmentation. + * @param volume the amount to increment the current volume by + */ +void Material::incrementVolume(double volume) { + _volume += volume; +} + + +/** + * @brief Set the number of instances of this Material. + * @param num_instances the number of instances of this Material in the Geometry + */ +void Material::setNumInstances(int num_instances) { + _num_instances = num_instances; +} + + +/** + * @brief Increment the number of instances of this Material. + * @details This routine is called by the TrackGenerator during track + * generation and segmentation. + */ +void Material::incrementNumInstances() { + _num_instances++; +} + + /** * @brief Set the number of energy groups for this Material. * @param num_groups the number of energy groups. @@ -580,9 +482,6 @@ void Material::setNumEnergyGroups(const int num_groups) { if (_sigma_t != NULL) MM_FREE(_sigma_t); - if (_sigma_a != NULL) - MM_FREE(_sigma_a); - if (_sigma_s != NULL) MM_FREE(_sigma_s); @@ -601,9 +500,6 @@ void Material::setNumEnergyGroups(const int num_groups) { if (_sigma_t != NULL) delete [] _sigma_t; - if (_sigma_a != NULL) - delete [] _sigma_a; - if (_sigma_s != NULL) delete [] _sigma_s; @@ -615,32 +511,17 @@ void Material::setNumEnergyGroups(const int num_groups) { if (_chi != NULL) delete [] _chi; - - if (_dif_coef != NULL) - delete [] _dif_coef; - - if (_dif_hat != NULL) - delete [] _dif_hat; - - if (_dif_tilde != NULL) - delete [] _dif_tilde; - - if (_buckling != NULL) - delete [] _buckling; } /* Allocate memory for data arrays */ _sigma_t = new FP_PRECISION[_num_groups]; - _sigma_a = new FP_PRECISION[_num_groups]; _sigma_f = new FP_PRECISION[_num_groups]; _nu_sigma_f = new FP_PRECISION[_num_groups]; _chi = new FP_PRECISION[_num_groups]; _sigma_s = new FP_PRECISION[_num_groups*_num_groups]; - /* Assign the null vector to each data array */ memset(_sigma_t, 0.0, sizeof(FP_PRECISION) * _num_groups); - memset(_sigma_a, 0.0, sizeof(FP_PRECISION) * _num_groups); memset(_sigma_f, 0.0, sizeof(FP_PRECISION) * _num_groups); memset(_nu_sigma_f, 0.0, sizeof(FP_PRECISION) * _num_groups); memset(_chi, 0.0, sizeof(FP_PRECISION) * _num_groups); @@ -652,7 +533,7 @@ void Material::setNumEnergyGroups(const int num_groups) { * @brief Set the Material's array of total cross-sections. * @details This method is a helper function to allow OpenMOC users to assign * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length + * NumPy array of the correct size (e.g., a float64 array the length * of the number of energy groups) as input to this function. This * function then fills the NumPy array with the data values for the * Material's total cross-sections. An example of how this function @@ -664,6 +545,10 @@ void Material::setNumEnergyGroups(const int num_groups) { * material.setSigmaT(sigma_t) * @endcode * + * NOTE: This routine will override an zero-valued cross-sections + * (e.g., in void or gap regions) with a minimum value of 1E-10 to + * void numerical issues in the MOC solver. + * * @param xs the array of total cross-sections * @param num_groups the number of energy groups */ @@ -671,10 +556,20 @@ void Material::setSigmaT(double* xs, int num_groups) { if (_num_groups != num_groups) log_printf(ERROR, "Unable to set sigma_t with %d groups for Material " - "%d which contains %d energy groups", num_groups, _id, _num_groups); + "%d which contains %d energy groups", num_groups, + _id, _num_groups); - for (int i=0; i < _num_groups; i++) - _sigma_t[i] = FP_PRECISION(xs[i]); + for (int i=0; i < _num_groups; i++) { + + /* If the cross-section is near zero (e.g., within (-1E-10, 1E-10)) */ + if (fabs(xs[i]) < ZERO_SIGMA_T) { + log_printf(INFO, "Overriding zero cross-section in " + "group %d for Material %d with 1E-10", i, _id); + _sigma_t[i] = FP_PRECISION(ZERO_SIGMA_T); + } + else + _sigma_t[i] = FP_PRECISION(xs[i]); + } } @@ -689,65 +584,21 @@ void Material::setSigmaTByGroup(double xs, int group) { log_printf(ERROR, "Unable to set sigma_t for group %d for Material " "%d which contains %d energy groups", group, _id, _num_groups); - _sigma_t[group-1] = xs; -} - - -/** - * @brief Set the Material's array of absorption scattering cross-sections. - * @details This method is a helper function to allow OpenMOC users to assign - * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the number of energy groups) as input to this function. This - * function then fills the NumPy array with the data values for the - * Material's absorption cross-sections. An example of how this - * function might be called in Python is as follows: - * - * @code - * sigma_a = numpy.array([0.05, 0.1, 0.15, ... ]) - * material = openmoc.Material(openmoc.material_id()) - * material.setSigmaA(sigma_a) - * @endcode - * - * @param xs the array of absorption scattering cross-sections - * @param num_groups the number of energy groups - */ -void Material::setSigmaA(double* xs, int num_groups) { - - if (_num_groups != num_groups) - log_printf(ERROR, "Unable to set sigma_a with %d groups for Material " - "%d which contains %d energy groups", num_groups, _id, _num_groups); - - for (int i=0; i < _num_groups; i++){ - _sigma_a[i] = FP_PRECISION(xs[i]); - - if (_buckling != NULL & _dif_coef != NULL) - _sigma_a[i] += FP_PRECISION(_buckling[i] * _dif_coef[i]); - } -} - - -/** - * @brief Set the Material's absorption cross-section for some energy group. - * @param xs the absorption cross-section - * @param group the energy group - */ -void Material::setSigmaAByGroup(double xs, int group) { - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to set sigma_a for group %d for material " - "%d which contains %d energy groups", group, _id, _num_groups); - - _sigma_a[group-1] = xs; + /* If the cross-section is near zero (e.g., within (-1E-10, 1E-10)) */ + if (fabs(xs) < ZERO_SIGMA_T) { + log_printf(INFO, "Overriding zero cross-section in " + "group %d for Material %d with 1E-10", group, _id); + _sigma_t[group-1] = FP_PRECISION(ZERO_SIGMA_T); + } + else + _sigma_t[group-1] = FP_PRECISION(xs); } - - /** * @brief Set the Material's 2D array of scattering cross-sections. - * @details The array should be passed to OpenMOC as a 1D array in - * column-major order. This assumes the standard convention, + * @details The array should be passed to OpenMOC as a 1D array in + * column-major order. This assumes the standard convention, * where column index is the origin group and the row index is * the destination group. That is, the array should be ordered * as follows: @@ -757,22 +608,22 @@ void Material::setSigmaAByGroup(double xs, int group) { * ... * 2 -> 1 * 2 -> 2 - * ... + * ... * * Note that if the scattering matrix is defined in NumPy by * the standard convention, "flat" will put the matrix into row * major order. Thus, one should transpose the matrix before - * flattening. - * + * flattening. + * * For cache efficiency, the transpose of the input is actually * stored in OpenMOC. - * + * * This method is a helper function to allow OpenMOC users to assign * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the square of the number of energy groups) as input to this - * function. This function then fills the NumPy array with the data - * values for the Material's scattering cross-sections. An example + * NumPy array of the correct size (e.g., a float64 array the length + * of the square of the number of energy groups) as input to this + * function. This function then fills the NumPy array with the data + * values for the Material's scattering cross-sections. An example * of how this function might be called in Python is as follows: * * @code @@ -823,7 +674,7 @@ void Material::setSigmaSByGroup(double xs, int origin, int destination) { * @brief Set the Material's array of fission cross-sections. * @details This method is a helper function to allow OpenMOC users to assign * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length + * NumPy array of the correct size (e.g., a float64 array the length * of the number of energy groups) as input to this function. This * function then fills the NumPy array with the data values for the * Material's fission cross-sections. An example of how this @@ -899,7 +750,7 @@ void Material::setNuSigmaF(double* xs, int num_groups) { for (int i=0; i < _num_groups; i++) _nu_sigma_f[i] = xs[i]; - + /* Determine whether or not this Material is fissionable */ _fissionable = false; @@ -917,7 +768,7 @@ void Material::setNuSigmaF(double* xs, int num_groups) { * for some energy group. * @details This method is a helper function to allow OpenMOC users to assign * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length + * NumPy array of the correct size (e.g., a float64 array the length * of the number of energy groups) as input to this function. This * function then fills the NumPy array with the data values for the * Material's nu*fission cross-sections. An example of how this @@ -952,12 +803,11 @@ void Material::setNuSigmaFByGroup(double xs, int group) { } - /** * @brief Set the Material's array of chi \f$ \chi \f$ values. * @details This method is a helper function to allow OpenMOC users to assign * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length + * NumPy array of the correct size (e.g., a float64 array the length * of the number of energy groups) as input to this function. This * function then fills the NumPy array with the data values for the * Material's chi distribution. An example of how this function might @@ -982,7 +832,7 @@ void Material::setChi(double* xs, int num_groups) { for (int i=0; i < _num_groups; i++) chi_sum += xs[i]; - for (int i=0; i < _num_groups; i++){ + for (int i=0; i < _num_groups; i++) { if (chi_sum == 0) _chi[i] = xs[i]; else @@ -1007,360 +857,34 @@ void Material::setChiByGroup(double xs, int group) { /** - * @brief Set the Material's array of diffusion coefficients. - * @details This method is a helper function to allow OpenMOC users to assign - * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the number of energy groups) as input to this function. This - * function then fills the NumPy array with the data values for the - * Material's diffusion coefficients. An example of how this - * function might be called in Python is as follows: - * - * @code - * dif_coef = numpy.array([0.05, 0.1, 0.15, ... ]) - * material = openmoc.Material(openmoc.material_id()) - * material.setDifCoef(dif_coef) - * @endcode - * - * @param xs the array of diffusion coefficents - * @param num_groups the number of energy groups - */ -void Material::setDifCoef(double* xs, int num_groups) { - - if (_num_groups != num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient with %d groups for " - "Material %d which contains %d energy groups", num_groups, - _id, _num_groups); - - if (_dif_coef == NULL) - _dif_coef = new FP_PRECISION[_num_groups]; - - for (int i=0; i < _num_groups; i++) - _dif_coef[i] = xs[i]; -} - - -/** - * @brief Set the Material's diffusion coefficient for some energy group. - * @param xs the diffusion coefficient - * @param group the energy group - */ -void Material::setDifCoefByGroup(double xs, int group) { - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient for group %d for " - "Material %d which contains %d energy groups", - group, _id, _num_groups); - - if (_dif_coef == NULL){ - _dif_coef = new FP_PRECISION[_num_groups]; - - for (int i=0; i < _num_groups; i++) - _dif_coef[i] = 0.0; - } - - _dif_coef[group-1] = xs; -} - - -/** - * @brief Set the Material's array of diffusion coefficients. - * @details This method is a helper function to allow OpenMOC users to assign - * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the number of energy groups) as input to this function. This - * function then fills the NumPy array with the data values for the - * Material's buckling coefficients. An example of how this function - * might be called in Python is as follows: - * - * @code - * buckling = numpy.array([0.05, 0.1, 0.15, ... ]) - * material = openmoc.Material(openmoc.material_id()) - * material.setBuckling(buckling) - * @endcode - * - * @param xs the array of diffusion coefficents - * @param num_groups the number of energy groups - */ -void Material::setBuckling(double* xs, int num_groups) { - - if (_num_groups != num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient with %d groups for " - "Material %d which contains %d energy groups", num_groups, - _id, _num_groups); - - if (_buckling == NULL) - _buckling = new FP_PRECISION[_num_groups]; - - for (int i=0; i < _num_groups; i++) - _buckling[i] = xs[i]; -} - - -/** - * @brief Set the Material's diffusion coefficient for some energy group. - * @param xs the diffusion coefficient - * @param group the energy group - */ -void Material::setBucklingByGroup(double xs, int group) { - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient for group %d for " - "Material %d which contains %d energy groups", - group, _id, _num_groups); - - if (_buckling == NULL){ - _buckling = new FP_PRECISION[_num_groups]; - for (int i=0; i < _num_groups; i++) - _buckling[i] = 0.0; - } - - _buckling[group-1] = xs; -} - - -/** - * @brief Set the Material's array of diffusion coefficients. - * @details This method is a helper function to allow OpenMOC users to assign - * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the number of energy groups) as input to this function. This - * function then fills the NumPy array with the data values for the - * Material's surface diffusion coefficients. An example of how this - * function might be called in Python is as follows: - * - * @code - * dif_hat = numpy.array([0.05, 0.1, 0.15, ... ]) - * material = openmoc.Material(openmoc.material_id()) - * material.setDifHat(dif_hat) - * @endcode - * - * @param xs the array of surface diffusion coefficents - * @param num_groups the number of energy groups - */ -void Material::setDifHat(double* xs, int num_groups) { - - if (_num_groups != num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient with %d groups " - "for Material %d which contains %d energy groups", num_groups, - _id, _num_groups); - - if (_dif_hat == NULL) - _dif_hat = new FP_PRECISION[4*_num_groups]; - - for (int i=0; i < _num_groups*4; i++) - _dif_hat[i] = xs[i]; -} - - -/** - * @brief Set the Material's diffusion coefficient for some energy group along - * some CMFD mesh cell. - * @param xs the diffusion coefficient along some mesh cell surface - * @param group the energy group - * @param surface the Surface corresponding to this coefficient + * @brief Builds the fission matrix from chi and the fission cross-section. + * @details The fission matrix is constructed as the outer product of the + * chi and fission cross-section vectors. This routine is intended + * for internal use and is called by the Solver at runtime. */ -void Material::setDifHatByGroup(double xs, int group, int surface) { - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient for group %d for " - "Material %d which contains %d energy groups", - group, _id, _num_groups); - - if (_dif_hat == NULL){ - - _dif_hat = new FP_PRECISION[4*_num_groups]; - - for (int i=0; i < _num_groups*4; i++) - _dif_hat[i] = 0.0; - } - - _dif_hat[surface*_num_groups + (group-1)] = xs; -} - - -/** - * @brief Set the Material's array of diffusion coefficients. - * @details This method is a helper function to allow OpenMOC users to assign - * the Material's nuclear data in Python. A user must initialize a - * NumPy array of the correct size (i.e., a float64 array the length - * of the number of energy groups) as input to this function. This - * function then fills the NumPy array with the data values for the - * Material's CMFD corrected diffusion coefficients. An example of how - * this function might be called in Python is as follows: - * - * @code - * dif_tilde = numpy.array([0.05, 0.1, 0.15, ... ]) - * material = openmoc.Material(openmoc.material_id()) - * material.setDifTilde(dif_tilde) - * @endcode - * - * @param xs the array of CMFD corrected diffusion coefficents - * @param num_groups the number of energy groups - */ -void Material::setDifTilde(double* xs, int num_groups) { - - if (_num_groups != num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient with %d groups " - "for Material %d which contains %d energy groups", num_groups, - _id, _num_groups); - - if (_dif_tilde == NULL){ - _dif_tilde = new FP_PRECISION[4*_num_groups]; - } - - for (int i=0; i < _num_groups*4; i++) - _dif_tilde[i] = xs[i]; -} - - -/** - * @brief Set the Material's CMFD corrected diffusion coefficient for some - * energy group. - * @param xs the CMFD corrected diffusion coefficient - * @param group the energy group - * @param surface the Surface corresponding to this coefficient - */ -void Material::setDifTildeByGroup(double xs, int group, int surface) { - - if (group <= 0 || group > _num_groups) - log_printf(ERROR, "Unable to set diffusion coefficient correction for " - "group %d for Material %d which contains %d energy groups", - group, _id, _num_groups); - - if (_dif_tilde == NULL){ - _dif_tilde = new FP_PRECISION[4*_num_groups]; - - for (int i=0; i < _num_groups*4; i++) - _dif_tilde[i] = 0.0; - } - - _dif_tilde[surface*_num_groups + (group-1)] = xs; -} - - -/** - * @brief Checks if the total cross-section for this Material is equal to the - * absorption plus scattering cross-sections for all energy groups. - * @details If the total cross-section does not equal the absorption plus - * scattering cross-section within SIGMA_T_THRESH then this method - * exits OpenMOC. - */ -void Material::checkSigmaT() { +void Material::buildFissionMatrix() { if (_num_groups == 0) - log_printf(ERROR, "Unable to verify Material %d's total cross-section " - "since the number of energy groups has not been set", _id); - if (_sigma_t == NULL) - log_printf(ERROR, "Unable to verify Material %d's total cross-section " - "since its total cross-section has not been set", _id); - if (_sigma_a == NULL) - log_printf(ERROR, "Unable to verify Material %d's total cross-section " - "since its absorption cross-section has not been set", _id); - if (_sigma_s == NULL) - log_printf(ERROR, "Unable to verify Material %d's total cross-section " - "since its scattering cross-section has not been set", _id); - - FP_PRECISION calc_sigma_t; - - /* Loop over all energy groups */ - for (int i=0; i < _num_groups; i++) { - - /* Initialize the calculated total xs to the absorption xs */ - calc_sigma_t = _sigma_a[i]; - - /* Increment calculated total xs by scatter xs for each energy group */ - for (int j=0; j < _num_groups; j++) - calc_sigma_t += _sigma_s[i+j*_num_groups]; - - /* Check if the calculated and total match up to certain threshold */ - if (fabs(calc_sigma_t - _sigma_t[i]) > SIGMA_T_THRESH) { - log_printf(ERROR, "Material id = %d has a different total cross-section " - "than the sum of its scattering and absorption cross-sections " - "for group %d: sigma_t = %f, calc_sigma_t = %f", - _id, i+1, _sigma_t[i], calc_sigma_t); - } - } - - return; -} - - -/** - * @brief Converts this Material's attributes to a character array - * representation. - * @details The character array returned includes the user-defined ID, and each - * of the absorption, total, fission, nu multiplied by fission and - * scattering cross-sections and chi for all energy groups. - * @return character array of this Material's attributes - */ -std::string Material::toString() { - - std::stringstream string; - - string << "Material id = " << _id; - - if (_sigma_a != NULL) { - string << "\n\t\tSigma_a = "; - for (int e = 0; e < _num_groups; e++) - string << _sigma_a[e] << ", "; - } - - if (_sigma_t != NULL) { - string << "\n\t\tSigma_t = "; - for (int e = 0; e < _num_groups; e++) - string << _sigma_t[e] << ", "; - } - - if (_sigma_f != NULL) { - string << "\n\t\tSigma_f = "; - for (int e = 0; e < _num_groups; e++) - string << _sigma_f[e] << ", "; - } - - if (_nu_sigma_f != NULL) { - string << "\n\t\tnu_sigma_f = "; - for (int e = 0; e < _num_groups; e++) - string << _nu_sigma_f[e] << ", "; - } - - if (_sigma_s != NULL) { - string << "\n\t\tSigma_s = \n\t\t"; - for (int G = 0; G < _num_groups; G++) { - for (int g = 0; g < _num_groups; g++) - string << _sigma_s[G+g*_num_groups] << "\t\t "; - string << "\n\t\t"; - } - } - - if (_chi != NULL) { - string << "Chi = "; - for (int e = 0; e < _num_groups; e++) - string << _chi[e] << ", "; - } - - if (_dif_coef != NULL) { - string << "Diffusion Coefficient = "; - for (int e = 0; e < _num_groups; e++) - string << _dif_coef[e] << ", "; - } - - if (_buckling != NULL) { - string << "Buckling = "; - for (int e = 0; e < _num_groups; e++) - string << _buckling[e] << ", "; + log_printf(ERROR, "Unable to build Material %d's fission matrix " + "since the number of energy groups has not been set", _id); + else if (_nu_sigma_f == NULL) + log_printf(ERROR, "Unable to build Material %d's fission matrix " + "since its nu-fission cross-section has not been set", _id); + else if (_chi == NULL) + log_printf(ERROR, "Unable to build Material %d's fission matrix " + "since its chi spectrum has not been set", _id); + + /* Deallocate memory for old fission matrix if needed */ + if (_fiss_matrix != NULL) + delete [] _fiss_matrix; + + _fiss_matrix = new FP_PRECISION[_num_groups*_num_groups]; + + /* Compute vector outer product of chi and the fission cross-section */ + for (int G=0; G < _num_groups; G++) { + for (int g=0; g < _num_groups; g++) + _fiss_matrix[G*_num_groups+g] = _chi[G] * _nu_sigma_f[g]; } - - return string.str(); -} - - -/** - * @brief Prints a string representation of all of the Material's attributes to - * the console. - */ -void Material::printString() { - log_printf(NORMAL, toString().c_str()); } @@ -1392,17 +916,17 @@ void Material::alignData() { /* Allocate word-aligned memory for cross-section data arrays */ FP_PRECISION* new_sigma_t = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - FP_PRECISION* new_sigma_a = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); FP_PRECISION* new_sigma_f = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); FP_PRECISION* new_nu_sigma_f=(FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); FP_PRECISION* new_chi = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - /* The scattering matrix will be the number of vector groups - * wide (SIMD) and the actual number of groups long since + /* The fission and scattering matrices will be the number of vector + * groups wide (SIMD) and the actual number of groups long since * instructions are not SIMD in this dimension */ size = _num_vector_groups * VEC_LENGTH * _num_vector_groups; size *= VEC_LENGTH * sizeof(FP_PRECISION); + FP_PRECISION* new_fiss_matrix = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); FP_PRECISION* new_sigma_s = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); /* Initialize data structures to ones for sigma_t since it is used to @@ -1410,48 +934,52 @@ void Material::alignData() { size = _num_vector_groups * VEC_LENGTH * sizeof(FP_PRECISION); for (int i=0; i < _num_vector_groups * VEC_LENGTH; i++) { new_sigma_t[i] = 1.0; - new_sigma_a[i] = 0.0; new_sigma_f[i] = 0.0; new_nu_sigma_f[i] = 0.0; new_chi[i] = 0.0; } size *= _num_vector_groups * VEC_LENGTH; + memset(new_fiss_matrix, 0.0, size); memset(new_sigma_s, 0.0, size); /* Copy materials data from unaligned arrays into new aligned arrays */ size = _num_groups * sizeof(FP_PRECISION); memcpy(new_sigma_t, _sigma_t, size); - memcpy(new_sigma_a, _sigma_a, size); memcpy(new_sigma_f, _sigma_f, size); memcpy(new_nu_sigma_f, _nu_sigma_f, size); memcpy(new_chi, _chi, size); for (int e=0; e < _num_groups; e++) { + memcpy(new_fiss_matrix, _fiss_matrix, size); memcpy(new_sigma_s, _sigma_s, size); + new_fiss_matrix += _num_vector_groups * VEC_LENGTH; new_sigma_s += _num_vector_groups * VEC_LENGTH; + _fiss_matrix += _num_groups; _sigma_s += _num_groups; } + _fiss_matrix -= _num_groups * _num_groups; _sigma_s -= _num_groups * _num_groups; - /* Reset the new scattering cross section array pointer */ + /* Reset the new fission / scattering matrix array pointers */ + new_fiss_matrix -= _num_vector_groups * VEC_LENGTH * _num_groups; new_sigma_s -= _num_vector_groups * VEC_LENGTH * _num_groups; /* Delete the old unaligned arrays */ delete [] _sigma_t; - delete [] _sigma_a; delete [] _sigma_f; delete [] _nu_sigma_f; delete [] _chi; + delete [] _fiss_matrix; delete [] _sigma_s; /* Set the material's array pointers to the new aligned arrays */ _sigma_t = new_sigma_t; - _sigma_a = new_sigma_a; _sigma_f = new_sigma_f; _nu_sigma_f = new_nu_sigma_f; _chi = new_chi; + _fiss_matrix = new_fiss_matrix; _sigma_s = new_sigma_s; _data_aligned = true; @@ -1460,42 +988,120 @@ void Material::alignData() { } +/** + * @brief Transposes the scattering and fission matrices. + * @details This routine is used by the Solver when performing + * adjoint flux caclulations. + */ +void Material::transposeProductionMatrices() { + + int num_groups; + if (_data_aligned) + num_groups = _num_vector_groups * VEC_LENGTH; + else + num_groups = _num_groups; + + /* Perform matrix transpose on each matrix that has been allocated */ + if (_fiss_matrix != NULL) + matrix_transpose(_fiss_matrix, num_groups, num_groups); + if (_sigma_s != NULL) + matrix_transpose(_sigma_s, num_groups, num_groups); +} + + /** * @brief Create a duplicate of the Material. * @return a pointer to the clone */ -Material* Material::clone(){ +Material* Material::clone() { - Material* clone = new Material(getId()); + Material* clone = new Material(material_id(), _name); - clone->setNumEnergyGroups(_num_groups); + /* Set the number of groups if this Material's groups have been set */ + if (_num_groups > 0) + clone->setNumEnergyGroups(_num_groups); for (int i=0; i < _num_groups; i++) { clone->setSigmaTByGroup((double)_sigma_t[i], i+1); - clone->setSigmaAByGroup((double)_sigma_a[i], i+1); clone->setSigmaFByGroup((double)_sigma_f[i], i+1); clone->setNuSigmaFByGroup((double)_nu_sigma_f[i], i+1); clone->setChiByGroup((double)_chi[i], i+1); for (int j=0; j < _num_groups; j++) - clone->setSigmaSByGroup( - (double)getSigmaSByGroupInline(i,j), i+1, j+1); + clone->setSigmaSByGroup((double)getSigmaSByGroup(i+1,j+1), i+1, j+1); + } - if (_dif_coef != NULL) - clone->setDifCoefByGroup((double)_dif_coef[i], i+1); + if (_fiss_matrix != NULL) + clone->buildFissionMatrix(); - if (_buckling != NULL) - clone->setBucklingByGroup((double)_buckling[i], i+1); + return clone; +} + + +/** + * @brief Converts this Material's attributes to a character array + * representation. + * @details The character array returned includes the user-defined ID, and each + * of the absorption, total, fission, nu multiplied by fission and + * scattering cross-sections and chi for all energy groups. + * @return character array of this Material's attributes + */ +std::string Material::toString() { - for (int j=0; j < 4; j++) { + std::stringstream string; - if (_dif_hat != NULL) - clone->setDifHatByGroup((double)_dif_hat[i*4+j], i+1, j); + string << "Material id = " << _id; - if (_dif_tilde != NULL) - clone->setDifTildeByGroup((double)_dif_tilde[i*4+j], i+1, j); + if (_sigma_t != NULL) { + string << "\n\t\tSigma_t = "; + for (int e = 0; e < _num_groups; e++) + string << _sigma_t[e] << ", "; + } + + if (_sigma_f != NULL) { + string << "\n\t\tSigma_f = "; + for (int e = 0; e < _num_groups; e++) + string << _sigma_f[e] << ", "; + } + + if (_nu_sigma_f != NULL) { + string << "\n\t\tnu_sigma_f = "; + for (int e = 0; e < _num_groups; e++) + string << _nu_sigma_f[e] << ", "; + } + + if (_sigma_s != NULL) { + string << "\n\t\tSigma_s = \n\t\t"; + for (int G = 0; G < _num_groups; G++) { + for (int g = 0; g < _num_groups; g++) + string << _sigma_s[G+g*_num_groups] << "\t\t "; + string << "\n\t\t"; } } - return clone; + if (_chi != NULL) { + string << "Chi = "; + for (int e = 0; e < _num_groups; e++) + string << _chi[e] << ", "; + } + + if (_fiss_matrix != NULL) { + string << "\n\t\tFiss. Matrix = \n\t\t"; + for (int G = 0; G < _num_groups; G++) { + for (int g = 0; g < _num_groups; g++) + string << _fiss_matrix[G+g*_num_groups] << "\t\t "; + string << "\n\t\t"; + } + } + + return string.str(); +} + + +/** + * @brief Prints a string representation of all of the Material's attributes to + * the console. + */ +void Material::printString() { + log_printf(NORMAL, toString().c_str()); } diff --git a/src/Material.h b/src/Material.h index 458bb200b..b84f1b851 100644 --- a/src/Material.h +++ b/src/Material.h @@ -9,19 +9,24 @@ #define MATERIAL_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "constants.h" +#include "log.h" +#include "linalg.h" #include #include #include #include -#include "log.h" #endif #ifdef ICPC -/** Word-aligned memory deallocationallocation for Intel's compiler */ +/** Word-aligned memory allocation for Intel's compiler */ #define MM_FREE(array) _mm_free(array) /** Word-aligned memory allocation for Intel's compiler */ -#define MM_MALLOC(size,alignment) _mm_alloc(size, alignment) +#define MM_MALLOC(size,alignment) _mm_malloc(size, alignment) #else @@ -33,15 +38,10 @@ #endif -/** Error threshold for determining how close the sum of \f$ \Sigma_a \f$ - * and \f$ \Sigma_s \f$ must match that of \f$ \Sigma_t \f$ for each energy - * group - */ -#define SIGMA_T_THRESH 1E-3 - int material_id(); void reset_material_id(); +void maximize_material_id(int material_id); /** @@ -59,17 +59,19 @@ class Material { /** A user-defined name for the Material */ char* _name; + /** The volume / area of the Material computed from overlapping segments */ + double _volume; + + /** The total number of instances of this Material in the Geometry */ + int _num_instances; + /** The number of energy groups */ int _num_groups; /** An array of the total cross-sections for each energy group */ FP_PRECISION* _sigma_t; - /** An array of the absorption cross-sections for each energy group */ - FP_PRECISION* _sigma_a; - - /** A 2D array of the scattering cross-section matrix. The first index is - * row number and second index is column number */ + /** A 2D array of the scattering cross-section matrix from/into each group */ FP_PRECISION* _sigma_s; /** An array of the fission cross-sections for each energy group */ @@ -82,19 +84,8 @@ class Material { /** An array of the chi \f$ \chi \f$ values for each energy group */ FP_PRECISION* _chi; - /** An array of the diffusion coefficients for each energy group */ - FP_PRECISION* _dif_coef; - - /** An array of the diffusion coefficients for each energy group */ - FP_PRECISION* _buckling; - - /** An array of the diffusion coefficient for each energy group - * for each surface */ - FP_PRECISION* _dif_hat; - - /** An array of the CMFD correction to the diffusion coefficient values - * for each energy group for each surface */ - FP_PRECISION* _dif_tilde; + /** A 2D array of the fission matrix from/into each group */ + FP_PRECISION* _fiss_matrix; /** A boolean representing whether or not this Material contains a non-zero * fission cross-section and is fissionable */ @@ -113,81 +104,52 @@ class Material { int getId() const; char* getName() const; + double getVolume(); + int getNumInstances(); int getNumEnergyGroups() const; FP_PRECISION* getSigmaT(); - FP_PRECISION* getSigmaA(); FP_PRECISION* getSigmaS(); FP_PRECISION* getSigmaF(); FP_PRECISION* getNuSigmaF(); FP_PRECISION* getChi(); - FP_PRECISION* getDifCoef(); - FP_PRECISION* getBuckling(); - FP_PRECISION* getDifHat(); - FP_PRECISION* getDifTilde(); + FP_PRECISION* getFissionMatrix(); FP_PRECISION getSigmaTByGroup(int group); - FP_PRECISION getSigmaAByGroup(int group); FP_PRECISION getSigmaSByGroup(int origin, int destination); - FP_PRECISION getSigmaSByGroupInline(int origin, int destination); FP_PRECISION getSigmaFByGroup(int group); FP_PRECISION getNuSigmaFByGroup(int group); FP_PRECISION getChiByGroup(int group); - FP_PRECISION getDifCoefByGroup(int group); - FP_PRECISION getBucklingByGroup(int group); - FP_PRECISION getDifHatByGroup(int group, int surface); - FP_PRECISION getDifTildeByGroup(int group); + FP_PRECISION getFissionMatrixByGroup(int origin, int destination); bool isFissionable(); bool isDataAligned(); int getNumVectorGroups(); void setName(const char* name); + void setVolume(double volume); + void incrementVolume(double volume); + void setNumInstances(int num_instances); + void incrementNumInstances(); void setNumEnergyGroups(const int num_groups); void setSigmaT(double* xs, int num_groups); - void setSigmaA(double* xs, int num_groups); void setSigmaS(double* xs, int num_groups); void setSigmaF(double* xs, int num_groups); void setNuSigmaF(double* xs, int num_groups); void setChi(double* xs, int num_groups); - void setBuckling(double* xs, int num_groups); - void setDifCoef(double* xs, int num_groups); - void setDifHat(double* xs, int num_groups); - void setDifTilde(double* xs, int num_groups); void setSigmaTByGroup(double xs, int group); - void setSigmaAByGroup(double xs, int group); void setSigmaFByGroup(double xs, int group); void setNuSigmaFByGroup(double xs, int group); void setSigmaSByGroup(double xs, int origin, int destination); void setChiByGroup(double xs, int group); - void setBucklingByGroup(double xs, int group); - void setDifCoefByGroup(double xs, int group); - void setDifHatByGroup(double xs, int group, int surface); - void setDifTildeByGroup(double xs, int group, int surface); - - void checkSigmaT(); - std::string toString(); - void printString(); + void buildFissionMatrix(); + void transposeProductionMatrices(); void alignData(); - Material* clone(); -}; + std::string toString(); + void printString(); +}; -/** - * @brief inline function for efficient mapping for scattering, from - * 1D as stored in memory to 2D matrix - * @details Encapsulates the logic for indexing into the scattering - * matrix so it does not need to be repeated in other parts of - * the code. Note that this routine is 0-based, rather than - * 1-based indexing, as it is intended for use inside the code, - * not by users from Python. - * @param origin the column index of the matrix element - * @param destination the row index of the matrix element - */ -inline FP_PRECISION Material::getSigmaSByGroupInline( - int origin, int destination) { - return _sigma_s[destination*_num_groups + origin]; -} #endif /* MATERIAL_H_ */ diff --git a/src/Matrix.cpp b/src/Matrix.cpp new file mode 100644 index 000000000..cf619f108 --- /dev/null +++ b/src/Matrix.cpp @@ -0,0 +1,592 @@ +#include "Matrix.h" + +/** + * @brief Constructor initializes Matrix as a list of lists + * and sets the matrix dimensions. + * @detail The matrix object uses a "lists of lists" structure (implemented as + * a map of lists) to allow for easy setting and incrementing of the + * values in the object. When the matrix is needed to perform linear + * algebra operations, it is converted to compressed row storage (CSR) + * form [1]. The matrix is ordered by cell (as opposed to by group) on + * the outside. Locks are used to make the matrix thread-safe against + * concurrent writes the same value. One lock locks out multiple rows of + * the matrix at a time reprsenting multiple groups in the same cell. + * + * [1] "Sparse matrix", Wikipedia, + * https://en.wikipedia.org/wiki/Sparse_matrix. + * + * @param cell_locks Omp locks for atomic cell operations + * @param num_x The number of cells in the x direction. + * @param num_y The number of cells in the y direction. + * @param num_groups The number of energy groups in each cell. + */ +Matrix::Matrix(omp_lock_t* cell_locks, int num_x, int num_y, int num_groups) { + + setNumX(num_x); + setNumY(num_y); + setNumGroups(num_groups); + _num_rows = _num_x*_num_y*_num_groups; + + /* Initialize variables */ + for (int i=0; i < _num_rows; i++) + _LIL.push_back(std::map()); + + _A = NULL; + _LU = NULL; + _IA = NULL; + _ILU = NULL; + _JA = NULL; + _JLU = NULL; + _DIAG = NULL; + _modified = true; + _NNZ = 0; + _NNZLU = 0; + + /* Set OpenMP locks for each Matrix cell */ + if (cell_locks == NULL) + log_printf(ERROR, "Unable to create a Matrix without an array of cell " + "locks"); + + _cell_locks = cell_locks; +} + + +/** + * @brief Destructor clears list of lists and deletes the arrays + * used to represent the matrix in CSR form. + */ +Matrix::~Matrix() { + + if (_A != NULL) + delete [] _A; + + if (_LU != NULL) + delete [] _LU; + + if (_IA != NULL) + delete [] _IA; + + if (_ILU != NULL) + delete [] _ILU; + + if (_JA != NULL) + delete [] _JA; + + if (_JLU != NULL) + delete [] _JLU; + + if (_DIAG != NULL) + delete [] _DIAG; + + for (int i=0; i < _num_rows; i++) + _LIL[i].clear(); + _LIL.clear(); +} + + +/** + * @brief Increment a value in the matrix. + * @detail This method takes a cell and group of origin (cell/group from) + * and cell and group of destination (cell/group to) and floating + * point value. The origin and destination are used to compute the + * row and column in the matrix. If a value exists for the row/column, + * the value is incremented by val; otherwise, it is set to val. + * @param cell_from The origin cell. + * @param group_from The origin group. + * @param cell_to The destination cell. + * @param group_from The destination group. + * @param val The value used to increment the row/column location. + */ +void Matrix::incrementValue(int cell_from, int group_from, + int cell_to, int group_to, FP_PRECISION val) { + + if (cell_from >= _num_x*_num_y || cell_from < 0) + log_printf(ERROR, "Unable to increment Matrix value for cell_from %d" + " which is not between 0 and %d", cell_from, _num_x*_num_y-1); + else if (cell_to >= _num_x*_num_y || cell_to < 0) + log_printf(ERROR, "Unable to increment Matrix value for cell_to %d" + " which is not between 0 and %d", cell_from, _num_x*_num_y-1); + else if (group_from >= _num_groups || group_from < 0) + log_printf(ERROR, "Unable to increment Matrix value for group_from %d" + " which is not between 0 and %d", group_from, _num_groups-1); + else if (group_to >= _num_groups || group_to < 0) + log_printf(ERROR, "Unable to increment Matrix value for group_to %d" + " which is not between 0 and %d", group_to, _num_groups-1); + + /* Atomically increment the Matrix value from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell_to]); + + int row = cell_to*_num_groups + group_to; + int col = cell_from*_num_groups + group_from; + _LIL[row][col] += val; + + /* Release Matrix cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell_to]); + + /* Set global modified flag to true */ + _modified = true; +} + + +/** + * @brief Set a value in the matrix. + * @detail This method takes a cell and group of origin (cell/group from) + * and cell and group of destination (cell/group to) and floating + * point value. The origin and destination are used to compute the + * row and column in the matrix. The location specified by the + * row/column is set to val. + * @param cell_from The origin cell. + * @param group_from The origin group. + * @param cell_to The destination cell. + * @param group_from The destination group. + * @param val The value used to set the row/column location. + */ +void Matrix::setValue(int cell_from, int group_from, + int cell_to, int group_to, FP_PRECISION val) { + + if (cell_from >= _num_x*_num_y || cell_from < 0) + log_printf(ERROR, "Unable to set Matrix value for cell_from %d" + " which is not between 0 and %d", cell_from, _num_x*_num_y-1); + else if (cell_to >= _num_x*_num_y || cell_to < 0) + log_printf(ERROR, "Unable to set Matrix value for cell_to %d" + " which is not between 0 and %d", cell_from, _num_x*_num_y-1); + else if (group_from >= _num_groups || group_from < 0) + log_printf(ERROR, "Unable to set Matrix value for group_from %d" + " which is not between 0 and %d", group_from, _num_groups-1); + else if (group_to >= _num_groups || group_to < 0) + log_printf(ERROR, "Unable to set Matrix value for group_to %d" + " which is not between 0 and %d", group_to, _num_groups-1); + + /* Atomically set the Matrix value from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell_to]); + + int row = cell_to*_num_groups + group_to; + int col = cell_from*_num_groups + group_from; + _LIL[row][col] = val; + + /* Release Matrix cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell_to]); + + /* Set global modified flag to true */ + _modified = true; +} + + +/** + * @brief Clear all values in the matrix list of lists. + */ +void Matrix::clear() { + for (int i=0; i < _num_rows; i++) + _LIL[i].clear(); + + _modified = true; +} + + +/** + * @brief Convert the matrix lists of lists to compressed row (CSR) storage + * form. + */ +void Matrix::convertToCSR() { + + /* Get number of nonzero values */ + int NNZ = getNNZ(); + int NNZLU = getNNZLU(); + + if (NNZ != _NNZ || NNZLU != _NNZLU) { + + /* Deallocate memory for arrays if previously allocated */ + if (_A != NULL) + delete [] _A; + + if (_LU != NULL) + delete [] _LU; + + if (_IA != NULL) + delete [] _IA; + + if (_ILU != NULL) + delete [] _ILU; + + if (_JA != NULL) + delete [] _JA; + + if (_JLU != NULL) + delete [] _JLU; + + if (_DIAG != NULL) + delete [] _DIAG; + + /* Allocate memory for arrays */ + _A = new FP_PRECISION[NNZ]; + _LU = new FP_PRECISION[NNZLU]; + _IA = new int[_num_rows+1]; + _ILU = new int[_num_rows+1]; + _JA = new int[NNZ]; + _JLU = new int[NNZLU]; + _DIAG = new FP_PRECISION[_num_rows]; + + _NNZ = NNZ; + _NNZLU = NNZLU; + } + + std::fill_n(_DIAG, _num_rows, 0.0); + + /* Form arrays */ + int j = 0; + int jlu = 0; + std::map::iterator iter; + for (int row=0; row < _num_rows; row++) { + _IA[row] = j; + _ILU[row] = jlu; + for (iter = _LIL[row].begin(); iter != _LIL[row].end(); ++iter) { + if (iter->second != 0.0) { + _JA[j] = iter->first; + _A[j] = iter->second; + + if (row == iter->first) + _DIAG[row] = iter->second; + else { + _JLU[jlu] = iter->first; + _LU[jlu] = iter->second; + jlu++; + } + + j++; + } + } + } + + _IA[_num_rows] = NNZ; + _ILU[_num_rows] = NNZLU; + + /* Reset flat indicating the CSR objects have the same values as the + * LIL object */ + _modified = false; +} + + + +/** + * @brief Print the matrix object to the log file. + */ +void Matrix::printString() { + + /* Convert to CSR form */ + convertToCSR(); + + std::stringstream string; + string << std::setprecision(6) << std::endl; + string << " Matrix Object " << std::endl; + string << " Num rows: " << _num_rows << std::endl; + string << " NNZ : " << getNNZ() << std::endl; + + for (int row=0; row < _num_rows; row++) { + for (int i = _IA[row]; i < _IA[row+1]; i++) + string << " ( " << row << ", " << _JA[i] << "): " << _A[i] << std::endl; + } + + string << "End Matrix " << std::endl; + + log_printf(NORMAL, string.str().c_str()); +} + + +/** + * @brief Get a value in the matrix. + * @detail This method takes a cell and group of origin (cell/group from) + * and cell and group of destination (cell/group to). + * The origin and destination are used to compute the + * row and column in the matrix. The value at the location specified + * by the row/column is returned. + * @param cell_from The origin cell. + * @param group_from The origin group. + * @param cell_to The destination cell. + * @param group_from The destination group. + * @return The value at the corresponding row/column location. + */ +FP_PRECISION Matrix::getValue(int cell_from, int group_from, + int cell_to, int group_to) { + int row = cell_to*_num_groups + group_to; + int col = cell_from*_num_groups + group_from; + return _LIL[row][col]; +} + + +/** + * @brief Get the full matrix (A) component of the CSR form of the matrix + * object. + * @return A pointer to the A component of the CSR form matrix object. + */ +FP_PRECISION* Matrix::getA() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _A; +} + + +/** + * @brief Get the lower + upper (LU) component of the CSR form of the matrix + * object. + * @return A pointer to the lower + upper (LU) component of the CSR form matrix + * object. + */ +FP_PRECISION* Matrix::getLU() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _LU; +} + + +/** + * @brief Get an array of the row indices (I) component of the CSR form of the + * full matrix (A). + * @return A pointer to the I component of the CSR form of the full matrix (A). + */ +int* Matrix::getIA() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _IA; +} + + +/** + * @brief Get an array of the row indices (I) component of the CSR form of the + * lower + upper (LU) components of the matrix. + * @return A pointer to the I component of the CSR form of the LU components + * of the matrix. + */ +int* Matrix::getILU() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _ILU; +} + + +/** + * @brief Get an array of the column indices (J) component of the CSR form of + * the full matrix (A). + * @return A pointer to the J component of the CSR form of the full matrix (A). + */ +int* Matrix::getJA() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _JA; +} + + +/** + * @brief Get an array of the column indices (J) component of the CSR form of + * the lower + upper (LU) components of the matrix. + * @return A pointer to the J component of the CSR form of the LU components + * of the matrix. + */ +int* Matrix::getJLU() { + + /* If the matrix has been modified, regenerate its' CSR attributes */ + if (_modified) + convertToCSR(); + + return _JLU; +} + + +/** + * @brief Get the diagonal component of the matrix object. + * @return A pointer to the diagonal component of the matrix object. + */ +FP_PRECISION* Matrix::getDiag() { + + if (_modified) + convertToCSR(); + + return _DIAG; +} + + +/** + * @brief Get the number of cells in the x dimension. + * @return The number of cells in the x dimension. + */ +int Matrix::getNumX() { + return _num_x; +} + + +/** + * @brief Get the number of cells in the y dimension. + * @return The number of cells in the y dimension. + */ +int Matrix::getNumY() { + return _num_y; +} + + +/** + * @brief Get the number of groups in each cell. + * @return The number of groups in each cell. + */ +int Matrix::getNumGroups() { + return _num_groups; +} + + +/** + * @brief Get the number of rows in the matrix. + * @return The number of rows in the matrix. + */ +int Matrix::getNumRows() { + return _num_rows; +} + + +/** + * @brief Get the number of non-zero values in the full matrix. + * @return The number of non-zero values in the full matrix. + */ +int Matrix::getNNZ() { + + int NNZ = 0; + std::map::iterator iter; + for (int row=0; row < _num_rows; row++) { + for (iter = _LIL[row].begin(); iter != _LIL[row].end(); ++iter) { + if (iter->second != 0.0) + NNZ++; + } + } + + return NNZ; +} + + +/** + * @brief Get the number of non-zero values in the lower + upper components of + * the matrix. + * @return The number of non-zero values in the lower + upper components of the + * matrix. + */ +int Matrix::getNNZLU() { + + int NNZLU = 0; + std::map::iterator iter; + for (int row=0; row < _num_rows; row++) { + for (iter = _LIL[row].begin(); iter != _LIL[row].end(); ++iter) { + if (iter->second != 0.0 && iter->first != row) + NNZLU++; + } + } + + return NNZLU; +} + + +/** + * @brief Set the number of cells in the x dimension. + * @param num_x The number of cells in the x dimension. + */ +void Matrix::setNumX(int num_x) { + + if (num_x < 1) + log_printf(ERROR, "Unable to set Matrix num x to non-positive value %d", + num_x); + + _num_x = num_x; +} + + +/** + * @brief Set the number of cells in the y dimension. + * @param num_y The number of cells in the y dimension. + */ +void Matrix::setNumY(int num_y) { + + if (num_y < 1) + log_printf(ERROR, "Unable to set Matrix num y to non-positive value %d", + num_y); + + _num_y = num_y; +} + + +/** + * @brief Set the number of groups in each cell. + * @param num_groups The number of groups in each cell. + */ +void Matrix::setNumGroups(int num_groups) { + + if (num_groups < 1) + log_printf(ERROR, "Unable to set Matrix num groups to non-positive value" + " %d", num_groups); + + _num_groups = num_groups; +} + + +/** + * @brief Transpose the matrix in place. + */ +void Matrix::transpose() { + + Matrix temp(_cell_locks, _num_x, _num_y, _num_groups); + convertToCSR(); + int col, cell_to, cell_from, group_to, group_from; + FP_PRECISION val; + + /* Transpose matrix to temp */ + for (int row=0; row < _num_rows; row++) { + for (int i = _IA[row]; i < _IA[row+1]; i++) { + col = _JA[row]; + cell_to = row / _num_groups; + group_to = row % _num_groups; + cell_from = col / _num_groups; + group_from = col % _num_groups; + val = _A[i]; + temp.setValue(cell_to, group_to, cell_from, group_from, val); + } + } + + /* Copy temp to current matrix */ + clear(); + temp.convertToCSR(); + int* IA = temp.getIA(); + int* JA = temp.getJA(); + FP_PRECISION* A = temp.getA(); + + for (int row=0; row < _num_rows; row++) { + for (int i = IA[row]; i < IA[row+1]; i++) { + col = JA[row]; + cell_to = row / _num_groups; + group_to = row % _num_groups; + cell_from = col / _num_groups; + group_from = col % _num_groups; + val = A[i]; + setValue(cell_from, group_from, cell_to, group_to, val); + } + } +} + + +/** + * @brief Return the array of cell locks for atomic cell operations. + * @return an array of cell locks + */ +omp_lock_t* Matrix::getCellLocks() { + return _cell_locks; +} diff --git a/src/Matrix.h b/src/Matrix.h new file mode 100644 index 000000000..fbb46aa7c --- /dev/null +++ b/src/Matrix.h @@ -0,0 +1,94 @@ +/** + * @file Matrix.h + * @brief A matrix object + * @date May 5, 2015 + * @author Samuel Shaner, MIT, Course 22 (shaner@mit.edu) + */ + +#ifndef MATRIX_H_ +#define MATRIX_H_ + + +#ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#endif + + +class Matrix { + +private: + + /** A list of lists representing the matrix */ + std::vector< std::map > _LIL; + + /** The CSR matrix variables */ + FP_PRECISION* _A; + FP_PRECISION* _LU; + int* _IA; + int* _JA; + int* _ILU; + int* _JLU; + FP_PRECISION* _DIAG; + + bool _modified; + int _num_x; + int _num_y; + int _num_groups; + int _num_rows; + int _NNZ; + int _NNZLU; + + /** OpenMP mutual exclusion locks for atomic cell updates */ + omp_lock_t* _cell_locks; + + void convertToCSR(); + void setNumX(int num_x); + void setNumY(int num_y); + void setNumGroups(int num_groups); + +public: + Matrix(omp_lock_t* cell_locks, int num_x=1, int num_y=1, int num_groups=1); + virtual ~Matrix(); + + /* Worker functions */ + void incrementValue(int cell_from, int group_from, int cell_to, int group_to, + FP_PRECISION val); + void clear(); + void printString(); + void transpose(); + + /* Getter functions */ + FP_PRECISION getValue(int cell_from, int group_from, int cell_to, + int group_to); + FP_PRECISION* getA(); + FP_PRECISION* getLU(); + int* getIA(); + int* getILU(); + int* getJA(); + int* getJLU(); + FP_PRECISION* getDiag(); + int getNumX(); + int getNumY(); + int getNumGroups(); + int getNumRows(); + int getNNZ(); + int getNNZLU(); + omp_lock_t* getCellLocks(); + + /* Setter functions */ + void setValue(int cell_from, int group_from, int cell_to, int group_to, + FP_PRECISION val); +}; + +#endif /* MATRIX_H_ */ diff --git a/src/ParallelHashMap.h b/src/ParallelHashMap.h new file mode 100644 index 000000000..71094d445 --- /dev/null +++ b/src/ParallelHashMap.h @@ -0,0 +1,852 @@ +/** + * @file ParallelHashMap.h + * @brief A thread-safe hash map supporting insertion and lookup operations + * @details The parallel hash map is built on top of a fixed-sized hash map + * object and features OpenMP concurrency structures. The underlying + * fixed-sized hash map handles collisions with chaining. + * @date June 6, 2015 + * @author Geoffrey Gunow, MIT, Course 22 (geogunow@mit.edu) + */ + +#ifndef __PARALLEL_HASH_MAP__ +#define __PARALLEL_HASH_MAP__ +#include +#include +#include +#include + +#include "log.h" + + +/** + * @class FixedHashMap ParallelHashMap.h "src/ParallelHashMap.h" + * @brief A fixed-size hash map supporting insertion and lookup operations + * @details The FixedHashMap class supports insertion and lookup operations + * but not deletion as deletion is not needed in the OpenMOC application. + * This hash table uses chaining for collisions and does not incorporate + * concurrency objects except for tracking the number of entries in the + * table for which an atomic increment is used. This hash table is not + * thread safe but is used as a building block for the ParallelHashMap + * class. This table guarantees O(1) insertions and lookups on average. + */ +template +class FixedHashMap { + struct node { + node(K k_in, V v_in) : next(NULL), key(k_in), value(v_in) {} + K key; + V value; + node *next; + }; + + private: + size_t _M; /* table size */ + size_t _N; /* number of elements present in table */ + node ** _buckets; /* buckets of values stored in nodes */ + + public: + + FixedHashMap(size_t M = 64); + virtual ~FixedHashMap(); + bool contains(K key); + V& at(K key); + void insert(K key, V value); + int insert_and_get_count(K key, V value); + size_t size(); + size_t bucket_count(); + K* keys(); + V* values(); + void clear(); + void print_buckets(); +}; + + +/** + * @class ParallelHashMap ParallelHashMap.h "src/ParallelHashMap.h" + * @brief A thread-safe hash map supporting insertion and lookup operations + * @details The ParallelHashMap class is built on top of the FixedHashMap + * class, supporting insertion and lookup operations but not deletion as + * deletion is not needed in the OpenMOC application. This hash table uses + * chaining for collisions, as defined in FixedHashMap. It offers lock + * free lookups in O(1) time on average and fine-grained locking for + * insertions in O(1) time on average as well. Resizing is conducted + * periodically during inserts, although the starting table size can be + * chosen to limit the number of resizing operations. + */ +template +class ParallelHashMap { + + /* padded pointer to hash table to avoid false sharing */ + struct paddedPointer { + volatile long pad_L1; + volatile long pad_L2; + volatile long pad_L3; + volatile long pad_L4; + volatile long pad_L5; + volatile long pad_L7; + volatile long pad_L8; + FixedHashMap volatile* value; + volatile long pad_R1; + volatile long pad_R2; + volatile long pad_R3; + volatile long pad_R4; + volatile long pad_R5; + volatile long pad_R6; + volatile long pad_R7; + volatile long pad_R8; + }; + + private: + FixedHashMap *_table; + paddedPointer *_announce; + size_t _num_threads; + size_t _N; + omp_lock_t * _locks; + size_t _num_locks; + void resize(); + + public: + ParallelHashMap(size_t M = 64, size_t L = 64); + virtual ~ParallelHashMap(); + bool contains(K key); + V at(K key); + void update(K key, V value); + void insert(K key, V value); + int insert_and_get_count(K key, V value); + size_t size(); + size_t bucket_count(); + size_t num_locks(); + K* keys(); + V* values(); + void clear(); + void print_buckets(); +}; + + +/** + * @brief Constructor initializes fixed-size table of buckets filled with empty + * linked lists. + * @details The constructor initializes a fixed-size hash map with the size + * as an input parameter. If no size is given the default size (64) + * is used. Buckets are filled with empty linked lists presented as + * NULL pointers. + * @param M size of fixed hash map + */ +template +FixedHashMap::FixedHashMap(size_t M) { + + /* ensure M is a power of 2 */ + if ((M & (M-1)) != 0) { + /* if not, round up to nearest power of 2 */ + M--; + for (size_t i = 1; i < 8 * sizeof(size_t); i*=2) + M |= M >> i; + M++; + } + + /* allocate table */ + _M = M; + _N = 0; + _buckets = new node*[_M](); +} + + +/** + * @brief Destructor deletes all nodes in the linked lists associated with each + * bucket in the fixed-size table and their pointers. + */ +template +FixedHashMap::~FixedHashMap() { + /* for each bucket, scan through linked list and delete all nodes */ + for (size_t i=0; i<_M; i++) { + node *iter_node = _buckets[i]; + while (iter_node != NULL) { + node *next_node = iter_node->next; + delete iter_node; + iter_node = next_node; + } + } + + /* delete all buckets (now pointers to empty linked lists) */ + delete [] _buckets; +} + + +/** + * @brief Determine whether the fixed-size table contains a given key + * @details The linked list in the bucket associated with the key is searched + * to determine whether the key is present. + * @param key key to be searched + * @return boolean value referring to whether the key is contained in the map + */ +template +bool FixedHashMap::contains(K key) { + + /* get hash into table assuming M is a power of 2, using fast modulus */ + size_t key_hash = std::hash()(key) & (_M-1); + + /* search corresponding bucket for key */ + node *iter_node = _buckets[key_hash]; + while (iter_node != NULL) { + if (iter_node->key == key) + return true; + else + iter_node = iter_node->next; + } + return false; +} + + +/** + * @brief Determine the value associated with a given key in the fixed-size + * table. + * @details The linked list in the bucket associated with the key is searched + * and once the key is found, the corresponding value is returned. + * An exception is thrown if the key is not present in the map. + * @param key key whose corresponding value is desired + * @return value associated with the given key + */ +template +V& FixedHashMap::at(K key) { + + /* get hash into table assuming M is a power of 2, using fast modulus */ + size_t key_hash = std::hash()(key) & (_M-1); + + /* search bucket for key and return the corresponding value if found */ + node *iter_node = _buckets[key_hash]; + while (iter_node != NULL) { + if (iter_node->key == key) + return iter_node->value; + else + iter_node = iter_node->next; + } + + /* after the bucket has been completely searched without finding the key, + throw an exception */ + throw std::out_of_range("Key not present in map"); +} + + +/** + * @brief Inserts a key/value pair into the fixed-size table. + * @details The specified key value pair is inserted into the fixed-size table. + * If the key already exists in the table, the pair is not inserted + * and the function returns. + * @param key key of the key/value pair to be inserted + * @param value value of the key/value pair to be inserted + */ +template +void FixedHashMap::insert(K key, V value) { + + /* get hash into table using fast modulus */ + size_t key_hash = std::hash()(key) & (_M-1); + + /* check to see if key already exists in map */ + if (contains(key)) + return; + + /* create new node */ + node *new_node = new node(key, value); + + /* find where to place element in linked list */ + node **iter_node = &_buckets[key_hash]; + while (*iter_node != NULL) + iter_node = &(*iter_node)->next; + + /* place element in linked list */ + *iter_node = new_node; + + /* increment counter */ +#pragma omp atomic + _N++; +} + + +/** + * @brief Inserts a key/value pair into the fixed-size table and returns the + * order number with which it was inserted. + * @details The specified key value pair is inserted into the fixed-size table. + * If the key already exists in the table, the pair is not inserted + * and the function returns -1. + * @param key key of the key/value pair to be inserted + * @param value value of the key/value pair to be inserted + * @return order number in which key/value pair was inserted, -1 is returned if + * key was already present in map. + */ +template +int FixedHashMap::insert_and_get_count(K key, V value) { + + /* get hash into table using fast modulus */ + size_t key_hash = std::hash()(key) & (_M-1); + + /* check to see if key already exists in map */ + if (contains(key)) + return -1; + + /* create new node */ + node *new_node = new node(key, value); + + /* find where to place element in linked list */ + node **iter_node = &_buckets[key_hash]; + while (*iter_node != NULL) + iter_node = &(*iter_node)->next; + + /* place element in linked list */ + *iter_node = new_node; + + /* increment counter and return number */ + size_t N; +#pragma omp critical (node_incr) + N = _N++; + + return (int) N; +} + + +/** + * @brief Returns the number of key/value pairs in the fixed-size table + * @return number of key/value pairs in the map + */ +template +size_t FixedHashMap::size() { + return _N; +} + + +/** + * @brief Returns the number of buckets in the fixed-size table + * @return number of buckets in the map + */ +template +size_t FixedHashMap::bucket_count() { + return _M; +} + + +/** + * @brief Returns an array of the keys in the fixed-size table + * @details All buckets are scanned in order to form a list of all keys + * present in the table and then the list is returned. WARNING: The user + * is responsible for freeing the allocated memory once the array is no + * longer needed. + * @return an array of keys in the map whose length is the number of key/value + * pairs in the table. +*/ +template +K* FixedHashMap::keys() { + + /* allocate array of keys */ + K *key_list = new K[_N]; + + /* fill array with keys */ + size_t ind = 0; + for (size_t i=0; i<_M; i++) { + node *iter_node = _buckets[i]; + while (iter_node != NULL) { + key_list[ind] = iter_node->key; + iter_node = iter_node->next; + ind++; + } + } + return key_list; +} + + +/** + * @brief Returns an array of the values in the fixed-size table + * @details All buckets are scanned in order to form a list of all values + * present in the table and then the list is returned. WARNING: The user + * is responsible for freeing the allocated memory once the array is no + * longer needed. + * @return an array of values in the map whose length is the number of + * key/value pairs in the table. +*/ +template +V* FixedHashMap::values() { + + /* allocate array of values */ + V *values = new V[_N]; + + /* fill array with values */ + size_t ind = 0; + for (size_t i=0; i<_M; i++) { + node *iter_node = _buckets[i]; + while (iter_node != NULL) { + values[ind] = iter_node->value; + iter_node = iter_node->next; + ind++; + } + } + return values; +} + + +/** + * @brief Clears all key/value pairs form the hash table. + */ +template +void FixedHashMap::clear() { + + /* for each bucket, scan through linked list and delete all nodes */ + for (size_t i=0; i<_M; i++) { + node *iter_node = _buckets[i]; + while (iter_node != NULL) { + node *next_node = iter_node->next; + delete iter_node; + iter_node = next_node; + } + } + + /* reset each bucket to null */ + for (size_t i=0; i<_M; i++) + _buckets[i] = NULL; + + /* reset the number of entries to zero */ + _N = 0; +} + + +/** + * @brief Prints the contents of each bucket to the screen + * @details All buckets are scanned and the contents of the buckets are + * printed, which are pointers to linked lists. If the pointer is NULL + * suggesting that the linked list is empty, NULL is printed to the + * screen. + */ +template +void FixedHashMap::print_buckets() { + log_printf(NORMAL, "Printing all buckets in the hash map..."); + for (size_t i=0; i<_M; i++) { + if (_buckets[i] == NULL) + log_printf(NORMAL, "Bucket %d -> NULL", i); + else + log_printf(NORMAL, "Bucket %d -> %p", i, _buckets[i]); + } +} + + +/** + * @brief Constructor generates initial underlying table as a fixed-sized + * hash map and intializes concurrency structures. + */ +template +ParallelHashMap::ParallelHashMap(size_t M, size_t L) { + + /* allocate table */ + _table = new FixedHashMap(M); + + /* get number of threads and create concurrency structures */ + _num_threads = 1; + _num_threads = omp_get_max_threads(); + _num_locks = L; + _locks = new omp_lock_t[_num_locks]; + for (size_t i=0; i<_num_locks; i++) + omp_init_lock(&_locks[i]); + + _announce = new paddedPointer[_num_threads]; +} + + +/** + * @brief Destructor frees memory associated with fixed-sized hash map and + * concurrency structures. + */ +template +ParallelHashMap::~ParallelHashMap() { + delete _table; + delete [] _locks; + delete [] _announce; +} + + +/** + * @brief Determine whether the parallel hash map contains a given key + * @details First the thread accessing the table announces its presence and + * which table it is reading. Then the linked list in the bucket + * associated with the key is searched without setting any locks + * to determine whether the key is present. When the thread has + * finished accessing the table, the announcement is reset to NULL. + * The announcement ensures that the data in the map is not freed + * during a resize until all threads have finished accessing the map. + * @param key key to be searched + * @return boolean value referring to whether the key is contained in the map + */ +template +bool ParallelHashMap::contains(K key) { + + /* get thread ID */ + size_t tid = 0; + tid = omp_get_thread_num(); + + /* get pointer to table, announce it will be searched, + and ensure consistency */ + FixedHashMap *table_ptr; + do { + table_ptr = _table; + _announce[tid].value = table_ptr; +#pragma omp flush(_announce) + } while (table_ptr != _table); + + /* see if current table contains the thread */ + bool present = table_ptr->contains(key); + + /* reset table announcement to not searching */ + _announce[tid].value = NULL; + + return present; +} + + +/** + * @brief Determine the value associated with a given key. + * @details This function follows the same algorithm as except that + * the value associated with the searched key is returned. + * First the thread accessing the table acquires the lock corresponding + * with the associated bucket based on the key. Then the linked list + * in the bucket is searched for the key. An exception is thrown if the + * key is not found. When the thread has finished accessing the table, + * it releases the lock. + * @param key key to be searched + * @return value associated with the key + */ +template +V ParallelHashMap::at(K key) { + /* get thread ID */ + size_t tid = 0; + tid = omp_get_thread_num(); + + /* get pointer to table, announce it will be searched */ + FixedHashMap *table_ptr; + do { + table_ptr = _table; + _announce[tid].value = table_ptr; +#pragma omp flush(_announce) + } while (table_ptr != _table); + + /* get value associated with the key in the underlying table */ + V value = table_ptr->at(key); + + /* reset table announcement to not searching */ + _announce[tid].value = NULL; + + return value; +} + + +/** + * @brief Insert a given key/value pair into the parallel hash map. + * @details First the underlying table is checked to determine if a resize + * should be conducted. Then, the table is checked to see if it + * already contains the key. If so, the key/value pair is not inserted + * and the function returns. Otherwise, the lock of the associated + * bucket is acquired and the key/value pair is added to the bucket. + * @param key key of the key/value pair to be inserted + * @param value value of the key/value pair to be inserted + */ +template +void ParallelHashMap::insert(K key, V value) { + /* check if resize needed */ + if (2*_table->size() > _table->bucket_count()) + resize(); + + /* check to see if key is already contained in the table */ + if (contains(key)) + return; + + /* get lock hash */ + size_t lock_hash = (std::hash()(key) & (_table->bucket_count() - 1)) + % _num_locks; + + /* acquire lock */ + omp_set_lock(&_locks[lock_hash]); + + /* insert value */ + _table->insert(key, value); + + /* release lock */ + omp_unset_lock(&_locks[lock_hash]); +} + + +/** + * @brief Updates the value associated with a key in the parallel hash map. + * @details The thread first acquires the lock for the bucket associated with + * the key is acquired, then the linked list in the bucket is searched + * for the key. If the key is not found, an exception is returned. When + * the key is found, the value is updated and the lock is released. + * @param key the key of the key/value pair to be updated + * @param value the new value for the key/value pair + */ +template +void ParallelHashMap::update(K key, V value) { + + /* get lock hash */ + size_t lock_hash = (std::hash()(key) & (_table->bucket_count() - 1)) + % _num_locks; + + /* acquire lock */ + omp_set_lock(&_locks[lock_hash]); + + /* insert value */ + _table->at(key) = value; + + /* release lock */ + omp_unset_lock(&_locks[lock_hash]); +} + + +/** + * @brief Insert a given key/value pair into the parallel hash map and return + the order number. + * @details First the underlying table is checked to determine if a resize + * should be conducted. Then, the table is checked to see if it + * already contains the key. If so, the key/value pair is not inserted + * and the function returns. Otherwise, the lock of the associated + * bucket is acquired and the key/value pair is added to the bucket. + * @param key key of the key/value pair to be inserted + * @param value value of the key/value pair to be inserted + * @return order number in which the key/value pair was inserted, -1 if it + * already exists + */ +template +int ParallelHashMap::insert_and_get_count(K key, V value) { + + /* check if resize needed */ + if (2*_table->size() > _table->bucket_count()) + resize(); + + /* check to see if key is already contained in the table */ + if (contains(key)) + return -1; + + /* get lock hash */ + size_t lock_hash = (std::hash()(key) & (_table->bucket_count() - 1)) + % _num_locks; + + /* acquire lock */ + omp_set_lock(&_locks[lock_hash]); + + /* insert value */ + int N =_table->insert_and_get_count(key, value); + + /* release lock */ + omp_unset_lock(&_locks[lock_hash]); + + return N; +} + + +/** + * @brief Resizes the underlying table to twice its current capacity. + * @details In a thread-safe manner, this procedure resizes the underlying + * FixedHashMap table to twice its current capacity using locks and the + * announce array. First, all locks are set in order to block inserts and + * prevent deadlock. A new table is allocated of twice the size and all + * key/value pairs from the old table, then the pointer is switched to the + * new table and locks are released. Finally the memory needs to be freed. + * To prevent threads currently reading the table from encountering + * segmentation faults, the resizing threads waits for the announce array + * to be free of references to the old table before freeing the memory. + */ +template +void ParallelHashMap::resize() { + + /* acquire all locks in order */ + for (size_t i=0; i<_num_locks; i++) + omp_set_lock(&_locks[i]); + + /* recheck if resize needed */ + if (2*_table->size() < _table->bucket_count()) { + /* release locks */ + for (size_t i=0; i<_num_locks; i++) + omp_unset_lock(&_locks[i]); + + return; + } + + /* allocate new hash map of double the size */ + FixedHashMap *new_map = + new FixedHashMap(2*_table->bucket_count()); + + /* get keys, values, and number of elements */ + K *key_list = _table->keys(); + V *value_list = _table->values(); + + /* insert key/value pairs into new hash map */ + for (size_t i=0; i<_table->size(); i++) + new_map->insert(key_list[i], value_list[i]); + + /* save pointer of old table */ + FixedHashMap *old_table = _table; + + /* reassign pointer */ + _table = new_map; +#pragma omp flush(_table) + + /* release all locks */ + for (size_t i=0; i<_num_locks; i++) + omp_unset_lock(&_locks[i]); + + /* delete key and value list */ + delete [] key_list; + delete [] value_list; + + /* wait for all threads to stop reading from the old table */ + for (size_t i=0; i<_num_threads; i++) + while (_announce[i].value == old_table) + continue; + + /* free memory associated with old table */ + delete old_table; +} + + +/** + * @brief Returns the number of key/value pairs in the underlying table + * @return number of key/value pairs in the map + */ +template +size_t ParallelHashMap::size() { + return _table->size(); +} + + +/** + * @brief Returns the number of buckets in the underlying table + * @return number of buckets in the map + */ +template +size_t ParallelHashMap::bucket_count() { + return _table->bucket_count(); +} + + +/** + * @brief Returns the number of locks in the parallel hash map + * @return number of locks in the map + */ +template +size_t ParallelHashMap::num_locks() { + return _num_locks; +} + + +/** + * @brief Returns an array of the keys in the underlying table + * @details All buckets are scanned in order to form a list of all keys + * present in the table and then the list is returned. Threads + * announce their presence to ensure table memory is not freed + * during access. WARNING: The user is responsible for freeing the + * allocated memory once the array is no longer needed. + * @return an array of keys in the map whose length is the number of key/value + * pairs in the table. + */ +template +K* ParallelHashMap::keys() { + + /* get thread ID */ + size_t tid = 0; + tid = omp_get_thread_num(); + + /* get pointer to table, announce it will be searched */ + FixedHashMap *table_ptr; + do { + table_ptr = _table; + _announce[tid].value = table_ptr; +#pragma omp flush(_announce) + } while (table_ptr != _table); + + /* get key list */ + K* key_list = table_ptr->keys(); + + /* reset table announcement to not searching */ + _announce[tid].value = NULL; + + return key_list; +} + + +/** + * @brief Returns an array of the values in the underlying table + * @details All buckets are scanned in order to form a list of all values + * present in the table and then the list is returned. Threads + * announce their presence to ensure table memory is not freed + * during access. WARNING: The user is responsible for freeing the + * allocated memory once the array is no longer needed. + * @return an array of values in the map whose length is the number of key/value + * pairs in the table. + */ +template +V* ParallelHashMap::values() { + + /* get thread ID */ + size_t tid = 0; + tid = omp_get_thread_num(); + + /* get pointer to table, announce it will be searched */ + FixedHashMap *table_ptr; + do { + table_ptr = _table; + _announce[tid].value = table_ptr; +#pragma omp flush(_announce) + } while (table_ptr != _table); + + /* get value list */ + V* value_list = table_ptr->values(); + + /* reset table announcement to not searching */ + _announce[tid].value = NULL; + + return value_list; +} + + +/** + * @brief Clears all key/value pairs form the hash table. + */ +template +void ParallelHashMap::clear() { + + /* acquire all locks in order */ + for (size_t i=0; i<_num_locks; i++) + omp_set_lock(&_locks[i]); + + /* clear underlying fixed table */ + _table->clear(); + + /* release all locks in order */ + for (size_t i=0; i<_num_locks; i++) + omp_unset_lock(&_locks[i]); +} + + +/** + * @brief Prints the contents of each bucket to the screen + * @details All buckets are scanned and the contents of the buckets are + * printed, which are pointers to linked lists. If the pointer is NULL + * suggesting that the linked list is empty, NULL is printed to the + * screen. Threads announce their presence to ensure table memory is + * not freed during access. + */ +template +void ParallelHashMap::print_buckets() { + + /* get thread ID */ + size_t tid = 0; + tid = omp_get_thread_num(); + + /* get pointer to table, announce it will be searched */ + FixedHashMap *table_ptr; + do { + table_ptr = _table; + _announce[tid].value = table_ptr; +#pragma omp flush(_announce) + } while (table_ptr != _table); + + /* print buckets */ + table_ptr->print_buckets(); + + /* reset table announcement to not searching */ + _announce[tid].value = NULL; +} + +#endif diff --git a/src/Point.cpp b/src/Point.cpp index 29e2c87cc..20795d264 100644 --- a/src/Point.cpp +++ b/src/Point.cpp @@ -4,22 +4,31 @@ /** * @brief Constructor initializes an empty Point. */ -Point::Point() { } +Point::Point() { + _xyz = new double[3]; + _xyz[0] = 0.0; + _xyz[1] = 0.0; + _xyz[2] = 0.0; +} /** * @brief Destructor */ -Point::~Point() { } +Point::~Point() { + delete [] _xyz; +} /** * @brief Converts this Point to a character representation of its attributes. - * @details The character array includes the x-coordinate and y-coordinates. + * @details The character array includes the x-coordinate, y-coordinate, and + * z-coordinate * @return a character array of this Point's attributes */ std::string Point::toString() { std::stringstream string; - string << "Point: x = " << _x << ", y = " << _y; + string << "Point: x = " << _xyz[0] << ", y = " << _xyz[1] << ", z = " + << _xyz[2]; return string.str(); } diff --git a/src/Point.h b/src/Point.h index 1e6701a33..9249e6dcd 100644 --- a/src/Point.h +++ b/src/Point.h @@ -9,34 +9,35 @@ #define POINT_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "log.h" #include #include -#include "log.h" #endif /** * @class Point Point.h "src/Point.h" - * @brief Class to represent a 2D point in space. + * @brief Class to represent a 3D point in space. */ class Point { private: - /** The Point's x-coordinate */ - double _x; - - /** The Point's y-coordinate */ - double _y; + /** The Point's coordinates */ + double* _xyz; public: Point(); virtual ~Point(); - void setCoords(const double x, const double y); + void setCoords(const double x, const double y, const double z); double getX() const; double getY() const; + double getZ() const; void setX(const double x); void setY(const double y); - double distance(const double x, const double y) const; + void setZ(const double z); double distanceToPoint(const Point* point); std::string toString(); }; @@ -47,9 +48,10 @@ class Point { * @param x x-coordinate * @param y y-coordinate */ -inline void Point::setCoords(const double x, const double y) { - _x = x; - _y = y; +inline void Point::setCoords(const double x, const double y, const double z) { + _xyz[0] = x; + _xyz[1] = y; + _xyz[2] = z; } @@ -58,7 +60,7 @@ inline void Point::setCoords(const double x, const double y) { * @return the x-coordinate */ inline double Point::getX() const { - return _x; + return _xyz[0]; } @@ -67,7 +69,16 @@ inline double Point::getX() const { * @return the y-coordinate */ inline double Point::getY() const { - return _y; + return _xyz[1]; +} + + +/** + * @brief Returns this Point's z-coordinate. + * @return the z-coordinate + */ +inline double Point::getZ() const { + return _xyz[2]; } @@ -76,7 +87,7 @@ inline double Point::getY() const { * @param x the new x-coordinate */ inline void Point::setX(const double x) { - _x = x; + _xyz[0] = x; } @@ -85,20 +96,16 @@ inline void Point::setX(const double x) { * @param y the new y-coordinate */ inline void Point::setY(const double y) { - _y = y; + _xyz[1] = y; } /** - * @brief Compute the distance from this Point to another Point of interest. - * @param x the x-coordinate of the Point of interest - * @param y the y-coordinate of the Point of interest - * @return distance to the Point of interest + * @brief Set the Point's z-coordinate + * @param z the new z-coordinate */ -inline double Point::distance(const double x, const double y) const { - double deltax = _x - x; - double deltay = _y - y; - return sqrt(deltax*deltax + deltay*deltay); +inline void Point::setZ(const double z) { + _xyz[2] = z; } @@ -108,9 +115,10 @@ inline double Point::distance(const double x, const double y) const { * @return distance to the Point of interest */ inline double Point::distanceToPoint(const Point* point) { - double deltax = _x - point->_x; - double deltay = _y - point->_y; - return sqrt(deltax*deltax + deltay*deltay); + double deltax = _xyz[0] - point->getX(); + double deltay = _xyz[1] - point->getY(); + double deltaz = _xyz[2] - point->getZ(); + return sqrt(deltax*deltax + deltay*deltay + deltaz*deltaz); } diff --git a/src/PolarQuad.cpp b/src/PolarQuad.cpp new file mode 100644 index 000000000..e430d6820 --- /dev/null +++ b/src/PolarQuad.cpp @@ -0,0 +1,688 @@ +#include "PolarQuad.h" + + +/** + * @brief Dummy constructor sets the default number of angles to zero. + */ +PolarQuad::PolarQuad() { + _num_polar = 0; + _sin_thetas = NULL; + _weights = NULL; + _multiples = NULL; + _quad_type = CUSTOM; +} + + +/** + * @brief Destructor deletes arrray of sines of the polar angles, the weights + * of the polar angles and the products of the sines and weights. + */ +PolarQuad::~PolarQuad() { + + if (_sin_thetas != NULL) + delete [] _sin_thetas; + + if (_weights != NULL) + delete [] _weights; + + if (_multiples != NULL) + delete [] _multiples; +} + + + +/** + * @brief Returns the number of polar angles. + * @return the number of polar angles + */ +int PolarQuad::getNumPolarAngles() const { + return _num_polar; +} + + +/** + * @brief Returns the \f$ sin(\theta)\f$ value for a particular polar angle. + * @param n index of the polar angle of interest + * @return the value of \f$ \sin(\theta) \f$ for this polar angle + */ +FP_PRECISION PolarQuad::getSinTheta(const int n) const { + + if (n < 0 || n >= _num_polar) + log_printf(ERROR, "Attempted to retrieve sin theta for polar angle = " + "%d but only %d polar angles are defined", n, _num_polar); + + else if (_sin_thetas == NULL) + log_printf(ERROR, "Attempted to retrieve sin theta for polar angle = %d " + "but the sin thetas have not been initialized", n); + + return _sin_thetas[n]; +} + + +/** + * @brief Returns the weight value for a particular polar angle. + * @param n index of the polar angle of interest + * @return the weight for a polar angle + */ +FP_PRECISION PolarQuad::getWeight(const int n) const { + + if (n < 0 || n >= _num_polar) + log_printf(ERROR, "Attempted to retrieve the weight for polar angle = " + "%d but only %d polar angles are defined", n, _num_polar); + + else if (_weights == NULL) + log_printf(ERROR, "Attempted to retrieve weight for polar angle = %d " + "but the weights have not been initialized", n); + + return _weights[n]; +} + + +/** + * @brief Returns the multiple value for a particular polar angle. + * @details A multiple is the sine of a polar angle multiplied by its weight. + * @param n index of the polar angle of interest + * @return the value of the sine of the polar angle multiplied with its weight + */ +FP_PRECISION PolarQuad::getMultiple(const int n) const { + + if (n < 0 || n >= _num_polar) + log_printf(ERROR, "Attempted to retrieve the multiple for polar angle = " + "%d but only %d polar angles are defined", n, _num_polar); + + else if (_multiples == NULL) + log_printf(ERROR, "Attempted to retrieve multiple for polar angle = %d " + "but the multiples have not been initialized", n); + + return _multiples[n]; +} + + +/** + * @brief Returns a pointer to the PolarQuad's array of \f$ sin\theta_{p} \f$. + * @return a pointer to the array of \f$ sin\theta_{p} \f$ + */ +FP_PRECISION* PolarQuad::getSinThetas() { + + if (_sin_thetas == NULL) + log_printf(ERROR, "Attempted to retrieve the sin thetas array " + "but it has not been initialized"); + + return _sin_thetas; +} + + +/** + * @brief Returns a pointer to the PolarQuad's array of polar weights. + * @return a pointer to the polar weights array + */ +FP_PRECISION* PolarQuad::getWeights() { + + if (_weights == NULL) + log_printf(ERROR, "Attempted to retrieve the weights array " + "but it has not been initialized"); + + return _weights; +} + + +/** + * @brief Returns a pointer to the PolarQuad's array of multiples. + * @details A multiple is the sine of a polar angle multiplied by its weight. + * @return a pointer to the multiples array + */ +FP_PRECISION* PolarQuad::getMultiples() { + + if (_multiples == NULL) + log_printf(ERROR, "Attempted to retrieve the multiples array " + "but it has not been initialized"); + + return _multiples; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles + */ +void PolarQuad::setNumPolarAngles(const int num_polar) { + + if (num_polar <= 0) + log_printf(ERROR, "Unable to set the number of polar angles to %d " + "which is less than or equal to zero", num_polar); + + _num_polar = num_polar; +} + + +/** + * @brief Set the PolarQuad's array of sines of each polar angle. + * @details This method is a helper function to allow OpenMOC users to assign + * the PolarQuad's sin thetas in Python. A user must initialize a + * NumPy array of the correct size (e.g., a float64 array the length + * of the number of polar angles) as input to this function. This + * function then fills the NumPy array with the data values for the + * PolarQuad's sin thetas. An example of how this function might be + * called in Python is as follows: + * + * @code + * sin_thetas= numpy.array([0.05, 0.1, 0.15, ... ]) + * polar_quad = openmoc.PolarQuad() + * polar_quad.setNumPolarAngles(len(sin_thetas)) + * polar_quad.setSinThetas(sin_thetas) + * @endcode + * + * @param sin_thetas the array of sines of each polar angle + * @param num_polar the number of polar angles + */ +void PolarQuad::setSinThetas(double* sin_thetas, int num_polar) { + + if (_num_polar != num_polar) + log_printf(ERROR, "Unable to set %d sin thetas for PolarQuad " + "with %d polar angles", num_polar, _num_polar); + + /* Deallocate memory if it was allocated previously */ + if (_sin_thetas != NULL) + delete [] _sin_thetas; + + /* Initialize memory for arrays */ + _sin_thetas = new FP_PRECISION[_num_polar]; + + /* Extract sin thetas from user input */ + for (int p=0; p < _num_polar; p++) { + if (sin_thetas[p] < 0. || sin_thetas[p] > 1.) + log_printf(ERROR, "Unable to set sin theta to %f which is " + "not in the range [0,1]", sin_thetas[p]); + _sin_thetas[p] = FP_PRECISION(sin_thetas[p]); + } +} + + +/** + * @brief Set the PolarQuad's array of weights for each angle. + * @details This method is a helper function to allow OpenMOC users to assign + * the PolarQuad's angular weights in Python. A user must initialize a + * NumPy array of the correct size (e.g., a float64 array the length + * of the number of polar angles) as input to this function. This + * function then fills the NumPy array with the data values for the + * PolarQuad's weights. An example of how this function might be + * called in Python is as follows: + * + * @code + * weights = numpy.array([0.05, 0.1, 0.15, ... ]) + * polar_quad = openmoc.PolarQuad() + * polar_quad.setNumPolarAngles(len(weights)) + * polar_quad.setWeights(weights) + * @endcode + * + * @param weights the array of weights for each polar angle + * @param num_polar the number of polar angles + */ +void PolarQuad::setWeights(double* weights, int num_polar) { + + if (_num_polar != num_polar) + log_printf(ERROR, "Unable to set %d weights for PolarQuad " + "with %d polar angles", num_polar, _num_polar); + + /* Deallocate memory if it was allocated previously */ + if (_weights != NULL) + delete [] _weights; + + /* Initialize memory for arrays */ + _weights = new FP_PRECISION[_num_polar]; + double tot_weight = 0.; + + /* Extract weights from user input */ + for (int p=0; p < _num_polar; p++) { + _weights[p] = FP_PRECISION(weights[p]); + tot_weight += _weights[p]; + } + + /* Check that weights sum to 1 (half of the symmetric polar domain) */ + if (fabs(tot_weight - 1.0) > POLAR_WEIGHT_SUM_TOL) + log_printf(ERROR, "The polar weights sum to %f instead of 1.0", tot_weight); +} + + +/** + * @brief Dummy routine to initialize the polar quadrature. + * @details The parent class routine simply checks that the number of polar + * angles has been set by the user and returns; + */ +void PolarQuad::initialize() { + if (_num_polar == 0) + log_printf(ERROR, "Unable to initialize PolarQuad with zero polar angles. " + "Set the number of polar angles before initialization."); + + if (_sin_thetas != NULL && _weights != NULL) + precomputeMultiples(); +} + + +/** + * @brief This private routine computes the produce of the sine thetas and + * weights for each angle in the polar quadrature. + * @details Note that this routine must be called after populating the + * sine thetas and weights arrays. + */ +void PolarQuad::precomputeMultiples() { + + /* Deallocate memory if it was allocated previously */ + if (_multiples != NULL) + delete [] _multiples; + + /* Initialize memory for arrays */ + _multiples = new FP_PRECISION[_num_polar]; + + /* Compute multiples of sine thetas and weights */ + for (int p=0; p < _num_polar; p++) + _multiples[p] = _sin_thetas[p] * _weights[p]; +} + + +/** + * @brief Converts this Quadrature to a character array of its attributes. + * @details The character array includes the number of polar angles, the + * the values of the sine and weight of each polar angle, and the + * product of the sine and weight of each polar angle. + * @return a character array of the PolarQuad's attributes + */ +std::string PolarQuad::toString() { + + std::stringstream string; + + string << "PolarQuad"; + string << "\n\t# angles = " << _num_polar; + + string << "\n\tsin thetas = "; + if (_sin_thetas != NULL) { + for (int p = 0; p < _num_polar; p++) + string << _sin_thetas[p] << ", "; + } + + string << "\n\tweights = "; + if (_weights != NULL) { + for (int p = 0; p < _num_polar; p++) + string << _weights[p] << ", "; + } + + string << "\n\tmultiples = "; + if (_multiples != NULL) { + for (int p = 0; p < _num_polar; p++) + string << _multiples[p] << ", "; + } + + return string.str(); +} + + +/** + * @brief Returns the quadrature type. + * @return an enum corresponding to the quadrature type + */ +quadratureType PolarQuad::getQuadratureType() { + return _quad_type; +} + + + +/** + * @brief Dummy constructor calls the parent constructor. + */ +TYPolarQuad::TYPolarQuad(): PolarQuad() { + _quad_type = TABUCHI_YAMAMOTO; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles (maximum 3) + */ +void TYPolarQuad::setNumPolarAngles(const int num_polar) { + + if (num_polar > 3) + log_printf(ERROR, "Unable to set the number of polar angles to %d " + "for TYPolarQuad (max 3 angles)", num_polar); + + PolarQuad::setNumPolarAngles(num_polar); +} + + +/** + * @brief Routine to initialize the polar quadrature. + * @details This routine uses the tabulated values for the Tabuchi-Yamamoto + * polar angle quadrature, including the sine thetas and weights. + */ +void TYPolarQuad::initialize() { + + /* Call parent class initialize routine */ + PolarQuad::initialize(); + + /* Allocate temporary arrays for tabulated quadrature values */ + double* sin_thetas = new double[_num_polar]; + double* weights = new double[_num_polar]; + + /* Tabulated values for the sine thetas and weights for the + * Tabuchi-Yamamoto polar angle quadrature */ + if (_num_polar == 1) { + sin_thetas[0] = 0.798184; + weights[0] = 1.0; + } + + else if (_num_polar == 2) { + sin_thetas[0] = 0.363900; + sin_thetas[1] = 0.899900; + weights[0] = 0.212854; + weights[1] = 0.787146; + } + + else if (_num_polar == 3) { + sin_thetas[0] = 0.166648; + sin_thetas[1] = 0.537707; + sin_thetas[2] = 0.932954; + weights[0] = 0.046233; + weights[1] = 0.283619; + weights[2] = 0.670148; + } + + /* Set the arrays of sin thetas and weights */ + PolarQuad::setSinThetas(sin_thetas, _num_polar); + PolarQuad::setWeights(weights, _num_polar); + + /* Deallocate temporary arrays */ + delete [] sin_thetas; + delete [] weights; + + /* Compute the product of the sine thetas and weights */ + PolarQuad::precomputeMultiples(); +} + + +/** + * @brief Dummy constructor calls the parent constructor. + */ +LeonardPolarQuad::LeonardPolarQuad(): PolarQuad() { + _quad_type = LEONARD; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles (2 or 3) + */ +void LeonardPolarQuad::setNumPolarAngles(const int num_polar) { + + if (num_polar < 2 || num_polar > 3) + log_printf(ERROR, "Unable to set the number of polar angles to %d " + "for LeonardPolarQuad (2 or 3 angles)", num_polar); + + PolarQuad::setNumPolarAngles(num_polar); +} + + +/** + * @brief Routine to initialize the polar quadrature. + * @details This routine uses the tabulated values for the Leonard + * polar angle quadrature, including the sine thetas and weights. + */ +void LeonardPolarQuad::initialize() { + + /* Call parent class initialize routine */ + PolarQuad::initialize(); + + /* Allocate temporary arrays for tabulated quadrature values */ + double* sin_thetas = new double[_num_polar]; + double* weights = new double[_num_polar]; + + /* Tabulated values for the sine thetas and weights for the + * Leonard polar angle quadrature */ + if (_num_polar == 2) { + sin_thetas[0] = 0.273658; + sin_thetas[1] = 0.865714; + weights[0] = 0.139473; + weights[1] = 0.860527; + } + + else if (_num_polar == 3) { + sin_thetas[0] = 0.099812; + sin_thetas[1] = 0.395534; + sin_thetas[2] = 0.891439; + weights[0] = 0.017620; + weights[1] = 0.188561; + weights[2] = 0.793819; + } + + /* Set the arrays of sin thetas and weights */ + PolarQuad::setSinThetas(sin_thetas, _num_polar); + PolarQuad::setWeights(weights, _num_polar); + + /* Deallocate temporary arrays */ + delete [] sin_thetas; + delete [] weights; + + /* Compute the product of the sine thetas and weights */ + PolarQuad::precomputeMultiples(); +} + + + +/** + * @brief Dummy constructor calls the parent constructor. + */ +GLPolarQuad::GLPolarQuad(): PolarQuad() { + _quad_type = GAUSS_LEGENDRE; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles (maximum 6) + */ +void GLPolarQuad::setNumPolarAngles(const int num_polar) { + + if (num_polar > 6) + log_printf(ERROR, "Unable to set the number of polar angles to %d " + "for GLPolarQuad (max 6 angles)", num_polar); + + PolarQuad::setNumPolarAngles(num_polar); +} + + +/** + * @brief Routine to initialize the polar quadrature. + * @details This routine uses the tabulated values for the Gauss-Legendre + * polar angle quadrature, including the sine thetas and weights. + */ +void GLPolarQuad::initialize() { + + /* Call parent class initialize routine */ + PolarQuad::initialize(); + + /* Allocate temporary arrays for tabulated quadrature values */ + double* sin_thetas = new double[_num_polar]; + double* weights = new double[_num_polar]; + + /* Tabulated values for the sine thetas and weights for the + * Leonard polar angle quadrature */ + if (_num_polar == 1) { + sin_thetas[0] = sin(acos(0.5773502691)); + weights[0] = 1.0; + } + else if (_num_polar == 2) { + sin_thetas[0] = sin(acos(0.3399810435)); + sin_thetas[1] = sin(acos(0.8611363115)); + weights[0] = 0.6521451549; + weights[1] = 0.3478548451; + } + else if (_num_polar == 3) { + sin_thetas[0] = sin(acos(0.2386191860)); + sin_thetas[1] = sin(acos(0.6612093864)); + sin_thetas[2] = sin(acos(0.9324695142)); + weights[0] = 0.4679139346; + weights[1] = 0.3607615730; + weights[2] = 0.1713244924; + } + else if (_num_polar == 4) { + sin_thetas[0] = sin(acos(0.1834346424)); + sin_thetas[1] = sin(acos(0.5255324099)); + sin_thetas[2] = sin(acos(0.7966664774)); + sin_thetas[3] = sin(acos(0.9602898564)); + weights[0] = 0.3626837834; + weights[1] = 0.3137066459; + weights[2] = 0.2223810344; + weights[3] = 0.1012285363; + } + else if (_num_polar == 5) { + sin_thetas[0] = sin(acos(0.1488743387)); + sin_thetas[1] = sin(acos(0.4333953941)); + sin_thetas[2] = sin(acos(0.6794095682)); + sin_thetas[3] = sin(acos(0.8650633666)); + sin_thetas[4] = sin(acos(0.9739065285)); + weights[0] = 0.2955242247; + weights[1] = 0.2692667193; + weights[2] = 0.2190863625; + weights[3] = 0.1494513492; + weights[4] = 0.0666713443; + } + else if (_num_polar == 6) { + sin_thetas[0] = sin(acos(0.1252334085)); + sin_thetas[1] = sin(acos(0.3678314989)); + sin_thetas[2] = sin(acos(0.5873179542)); + sin_thetas[3] = sin(acos(0.7699026741)); + sin_thetas[4] = sin(acos(0.9041172563)); + sin_thetas[5] = sin(acos(0.9815606342)); + weights[0] = 0.2491470458; + weights[1] = 0.2334925365; + weights[2] = 0.2031674267; + weights[3] = 0.1600783286; + weights[4] = 0.1069393260; + weights[5] = 0.0471753364; + } + + /* Set the arrays of sin thetas and weights */ + PolarQuad::setSinThetas(sin_thetas, _num_polar); + PolarQuad::setWeights(weights, _num_polar); + + /* Deallocate temporary arrays */ + delete [] sin_thetas; + delete [] weights; + + /* Compute the product of the sine thetas and weights */ + PolarQuad::precomputeMultiples(); +} + + + +/** + * @brief Dummy constructor calls the parent constructor. + */ +EqualWeightsPolarQuad::EqualWeightsPolarQuad(): PolarQuad() { + _quad_type = EQUAL_WEIGHTS; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles + */ +void EqualWeightsPolarQuad::setNumPolarAngles(const int num_polar) { + PolarQuad::setNumPolarAngles(num_polar); +} + + +/** + * @brief Routine to initialize the polar quadrature. + * @details This routine generates the sine thetas and weights. + */ +void EqualWeightsPolarQuad::initialize() { + + /* Call parent class initialize routine */ + PolarQuad::initialize(); + + /* Allocate temporary arrays for tabulated quadrature values */ + double* sin_thetas = new double[_num_polar]; + double* weights = new double[_num_polar]; + + double cos_theta_a, cos_theta_b; + cos_theta_a = 1.; + + /* Generate the sin thetas and weights using equations 420-422 of the + * DOE Nucl. Eng. Handbook "Lattice Physics Computations" */ + for (int p=0; p < _num_polar; p++) { + cos_theta_b = cos_theta_a - (1. / _num_polar); + sin_thetas[p] = sin(acos(0.5 * (cos_theta_a + cos_theta_b))); + weights[p] = cos_theta_a - cos_theta_b; + cos_theta_a = cos_theta_b; + } + + /* Set the arrays of sin thetas and weights */ + PolarQuad::setSinThetas(sin_thetas, _num_polar); + PolarQuad::setWeights(weights, _num_polar); + + /* Deallocate temporary arrays */ + delete [] sin_thetas; + delete [] weights; + + /* Compute the product of the sine thetas and weights */ + PolarQuad::precomputeMultiples(); +} + + + +/** + * @brief Dummy constructor calls the parent constructor. + */ +EqualAnglesPolarQuad::EqualAnglesPolarQuad(): PolarQuad() { + _quad_type = EQUAL_ANGLES; +} + + +/** + * @brief Set the number of polar angles to initialize. + * @param num_polar the number of polar angles + */ +void EqualAnglesPolarQuad::setNumPolarAngles(const int num_polar) { + PolarQuad::setNumPolarAngles(num_polar); +} + + +/** + * @brief Routine to initialize the polar quadrature. + * @details This routine generates the sine thetas and weights. + */ +void EqualAnglesPolarQuad::initialize() { + + /* Call parent class initialize routine */ + PolarQuad::initialize(); + + /* Allocate temporary arrays for tabulated quadrature values */ + double* sin_thetas = new double[_num_polar]; + double* weights = new double[_num_polar]; + + double cos_theta_a, cos_theta_b; + double theta_a, theta_b; + double delta_theta = M_PI / (2. * _num_polar); + theta_a = 0.; + + /* Generate the sin thetas and weights using equations 420-422 of the + * DOE Nucl. Eng. Handbook "Lattice Physics Computations" */ + for (int p=0; p < _num_polar; p++) { + theta_b = theta_a + delta_theta; + cos_theta_a = cos(theta_a); + cos_theta_b = cos(theta_b); + sin_thetas[p] = sin(acos((0.5 * (cos_theta_a + cos_theta_b)))); + weights[p] = cos_theta_a - cos_theta_b; + theta_a = theta_b; + } + + /* Set the arrays of sin thetas and weights */ + PolarQuad::setSinThetas(sin_thetas, _num_polar); + PolarQuad::setWeights(weights, _num_polar); + + /* Deallocate temporary arrays */ + delete [] sin_thetas; + delete [] weights; + + /* Compute the product of the sine thetas and weights */ + PolarQuad::precomputeMultiples(); +} diff --git a/src/PolarQuad.h b/src/PolarQuad.h new file mode 100644 index 000000000..232ebc8c9 --- /dev/null +++ b/src/PolarQuad.h @@ -0,0 +1,167 @@ +/** + * @file PolarQuad.h + * @brief The PolarQuad abstract class and subclasses. + * @details The PolarQuad subclasses are defined with tabulated or functional + * quadrature sets given in the "Lattice Physics Computations", + * Handbook of Nuclear Engineering, Dave Knott, Akio Yamamoto, 2010. + * @date April 6, 2015 + * @author William Boyd, MIT, Course 22 (wboyd@mit.edu) +*/ + + +#ifndef POLARQUAD_H_ +#define POLARQUAD_H_ + +#ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "constants.h" +#include "log.h" +#include +#endif + + +/** + * @enum quadratureType + * @brief The types of quadrature sets supported by OpenMOC. + */ +enum quadratureType { + TABUCHI_YAMAMOTO, + LEONARD, + GAUSS_LEGENDRE, + EQUAL_WEIGHTS, + EQUAL_ANGLES, + CUSTOM +}; + + +/** + * @class PolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief The arbitrary polar quadrature parent class. + */ +class PolarQuad { + +protected: + + /** The quadrature type being used */ + quadratureType _quad_type; + + /** The number of polar angles */ + int _num_polar; + + /** An array of the sines of quadrature angles */ + FP_PRECISION* _sin_thetas; + + /** An array of the quadrature weights */ + FP_PRECISION* _weights; + + /** An array of the sines multipled by the weights */ + FP_PRECISION* _multiples; + + void precomputeMultiples(); + +public: + + PolarQuad(); + virtual ~PolarQuad(); + + int getNumPolarAngles() const; + FP_PRECISION getSinTheta(const int n) const; + FP_PRECISION getWeight(const int n) const; + FP_PRECISION getMultiple(const int n) const; + FP_PRECISION* getSinThetas(); + FP_PRECISION* getWeights(); + FP_PRECISION* getMultiples(); + quadratureType getQuadratureType(); + + virtual void setNumPolarAngles(const int num_polar); + void setSinThetas(double* sin_thetas, int num_polar); + void setWeights(double* weights, int num_polar); + + virtual void initialize(); + + std::string toString(); +}; + + + +/** + * @class TYPolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief Tabuchi-Yamamoto's polar quadrature. + */ +class TYPolarQuad: public PolarQuad { + +private: + +public: + TYPolarQuad(); + void setNumPolarAngles(const int num_polar); + void initialize(); +}; + + +/** + * @class LeonardPolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief Leonard's polar quadrature. + */ +class LeonardPolarQuad: public PolarQuad { + +private: + +public: + LeonardPolarQuad(); + void setNumPolarAngles(const int num_polar); + void initialize(); +}; + + + +/** + * @class GLPolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief Gauss-Legendre's polar quadrature. + */ +class GLPolarQuad: public PolarQuad { + +private: + +public: + GLPolarQuad(); + void setNumPolarAngles(const int num_polar); + void initialize(); +}; + + + +/** + * @class EqualWeightsPolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief Equal weights polar quadrature. + */ +class EqualWeightsPolarQuad: public PolarQuad { + +private: + +public: + EqualWeightsPolarQuad(); + void setNumPolarAngles(const int num_polar); + void initialize(); +}; + + + +/** + * @class EqualAnglesPolarQuad PolarQuad.h "src/PolarQuad.h" + * @brief Equal angles polar quadrature. + */ +class EqualAnglesPolarQuad: public PolarQuad { + +private: + +public: + EqualAnglesPolarQuad(); + void setNumPolarAngles(const int num_polar); + void initialize(); +}; + + +#endif /* POLARQUAD_H_ */ diff --git a/src/Quadrature.cpp b/src/Quadrature.cpp deleted file mode 100644 index 6ea561353..000000000 --- a/src/Quadrature.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "Quadrature.h" - - -/** - * @brief Constructor initializes arrays with polar angles and weights. - * @param type the Quadrature type (LEONARD or TABUCHI) - * @param num_polar_angles the number of polar angles (1, 2, or 3) - */ -Quadrature::Quadrature(quadratureType type, int num_polar_angles) { - - if (num_polar_angles != 1 && num_polar_angles != 2 && num_polar_angles != 3) - log_printf(ERROR, "Unable to set the number of polar angles to %d. Only" - "1, 2 and 3 polar angles are supported by OpenMOC."); - - _num_polar_angles = num_polar_angles; - - /** Initialize memory for arrays */ - _sinthetas = new FP_PRECISION[_num_polar_angles]; - _weights = new FP_PRECISION[_num_polar_angles]; - _multiples = new FP_PRECISION[_num_polar_angles]; - - /* If Quadrature type is TABUCHI */ - if (type == TABUCHI) { - - _type = TABUCHI; - - if (_num_polar_angles == 1) { - _sinthetas[0] = 0.798184; - _weights[0] = 1.0; - _multiples[0] = _sinthetas[0] * _weights[0]; - } - - else if (_num_polar_angles == 2) { - _sinthetas[0] = 0.363900; - _sinthetas[1] = 0.899900; - _weights[0] = 0.212854; - _weights[1] = 0.787146; - _multiples[0] = _sinthetas[0] * _weights[0]; - _multiples[1] = _sinthetas[1] * _weights[1]; - } - - else if (_num_polar_angles == 3) { - _sinthetas[0] = 0.166648; - _sinthetas[1] = 0.537707; - _sinthetas[2] = 0.932954; - _weights[0] = 0.046233; - _weights[1] = 0.283619; - _weights[2] = 0.670148; - _multiples[0] = _sinthetas[0] * _weights[0]; - _multiples[1] = _sinthetas[1] * _weights[1]; - _multiples[2] = _sinthetas[2] * _weights[2]; - } - - else - log_printf(ERROR, "TABUCHI type polar Quadrature supports 1, 2, or " - "3 polar angles but %d are defined", _num_polar_angles); - } - - /* If quadrature type is LEONARD */ - else if (type == LEONARD) { - - _type = LEONARD; - - if (_num_polar_angles == 2) { - _sinthetas[0] = 0.273658; - _sinthetas[1] = 0.865714; - _weights[0] = 0.139473; - _weights[1] = 0.860527; - _multiples[0] = _sinthetas[0] * _weights[0]; - _multiples[1] = _sinthetas[1] * _weights[1]; - } - - else if (_num_polar_angles == 3) { - _sinthetas[0] = 0.099812; - _sinthetas[1] = 0.395534; - _sinthetas[2] = 0.891439; - _weights[0] = 0.017620; - _weights[1] = 0.188561; - _weights[2] = 0.793819; - _multiples[0] = _sinthetas[0] * _weights[0]; - _multiples[1] = _sinthetas[1] * _weights[1]; - _multiples[2] = _sinthetas[2] * _weights[2]; - } - - else { - log_printf(ERROR, "LEONARD type polar Quadrature supports 2, or 3" - "polar angles but %d are defined", _num_polar_angles); - } - - } - - else - log_printf(ERROR, "LEONARD and TABUCHI polar Quadrature types " - "supported, but unknown type given"); -} - - -/** - * @brief Destructor deletes arrray of sines of the polar angles, the weights - * of the polar angles and the products of the sines and weights. - */ -Quadrature::~Quadrature() { - delete [] _sinthetas; - delete [] _weights; - delete [] _multiples; -} - - -/** - * @brief Returns the polar Quadrature type (LEONARD or TABUCHI) - * @return the polar Quadrature type - */ -quadratureType Quadrature::getType() const { - return _type; -} - - -/** - * @brief Returns the number of polar angles (1, 2 or 3). - * @return the number of polar angles - */ -int Quadrature::getNumPolarAngles() const { - return _num_polar_angles; -} - - -/** - * @brief Returns the \f$ sin(\theta)\f$ value for a particular polar angle. - * @param n index of the polar angle of interest - * @return the value of \f$ \sin(\theta) \f$ for this polar angle - */ -FP_PRECISION Quadrature::getSinTheta(const int n) const { - - if (n < 0 || n >= _num_polar_angles) - log_printf(ERROR, "Attempted to retrieve sintheta for polar angle = %d" - " but only %d polar angles are defined", _num_polar_angles); - - return _sinthetas[n]; -} - - -/** - * @brief Returns the weight value for a particular polar angle. - * @param n index of the polar angle of interest - * @return the weight for a polar angle - */ -FP_PRECISION Quadrature::getWeight(const int n) const { - - if (n < 0 || n >= _num_polar_angles) - log_printf(ERROR, "Attempted to retrieve the weight for polar angle = %d " - "but only %d polar angles are defined", _num_polar_angles); - - return _weights[n]; -} - - -/** - * @brief Returns the multiple value for a particular polar angle. - * @details A multiple is the sine of a polar angle multiplied by its weight. - * @param n index of the polar angle of interest - * @return the value of the sine of the polar angle multiplied with its weight - */ -FP_PRECISION Quadrature::getMultiple(const int n) const { - - if (n < 0 || n >= _num_polar_angles) - log_printf(ERROR, "Attempted to retrieve the multiple for polar angle = %d" - "but only %d polar angles are defined", _num_polar_angles); - - return _multiples[n]; -} - - -/** - * @brief Returns a pointer to the Quadrature's array of \f$ sin\theta_{p} \f$. - * @return a pointer to the array of \f$ sin\theta_{p} \f$ - */ -FP_PRECISION* Quadrature::getSinThetas() { - return _sinthetas; -} - - -/** - * @brief Returns a pointer to the Quadrature's array of polar weights. - * @return a pointer to the polar weights array - */ -FP_PRECISION* Quadrature::getWeights() { - return _weights; -} - - - -/** - * @brief Returns a pointer to the Quadrature's array of multiples. - * @details A multiple is the sine of a polar angle multiplied by its weight. - * @return a pointer to the multiples array - */ -FP_PRECISION* Quadrature::getMultiples() { - return _multiples; -} - - -/** - * @brief Converts this Quadrature to a character array of its attributes. - * @details The character array includes the polar Quadrature type, the number - * of polar angles, and the values of the sine of each polar angle, - * the weight of each polar angle, and the product of the sine - * and weight of each polar angle. - * @return a character array of this Quadrature's attributes - */ -std::string Quadrature::toString() { - - std::stringstream string; - - string << "Quadrature type = "; - - if (_type == LEONARD) - string << "LEONARD"; - else if (_type == TABUCHI) - string << "TABUCHI"; - - string << "\nsinthetas = "; - for (int p = 0; p < _num_polar_angles; p++) - string << _sinthetas[p] << ", "; - - string << "\nweights = "; - for (int p = 0; p < _num_polar_angles; p++) - string << _weights[p] << ", "; - - string << "\nmultiples= "; - for (int p = 0; p < _num_polar_angles; p++) - string << _multiples[p] << ", "; - - return string.str(); -} diff --git a/src/Quadrature.h b/src/Quadrature.h deleted file mode 100644 index 88eae4ec5..000000000 --- a/src/Quadrature.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file Quadrature.h - * @brief The Quadrature class. - * @date January 20, 2012 - * @author William Boyd, MIT, Course 22 (wboyd@mit.edu) -*/ - - -#ifndef QUADRATURE_H_ -#define QUADRATURE_H_ - -#ifdef __cplusplus -#include -#include "log.h" -#endif - -/** - * @enum quadratureType - * @brief The type of polar quadrature. - */ -enum quadratureType { - /** The Leonard type polar quadrature */ - LEONARD, - - /** The Tabuchi-Yamamoto polar quadrature */ - TABUCHI -}; - - -/** - * @class Quadrature Quadrature.h "src/Quadrature.h" - * @brief Stores values for a variety of polar quadratures which may be used. - */ -class Quadrature { - -private: - /** The type of polar quadrature (LEONARD or TABUCHI) */ - quadratureType _type; - - /** The number of polar angles */ - int _num_polar_angles; - - /** An array of the sine of the polar angles from the quadrature set */ - FP_PRECISION* _sinthetas; - - /** An array of the weights for the polar angles from the quadrature set */ - FP_PRECISION* _weights; - - /** An array of the sine multipled by the weight for the polar angles from - * the quadrature set */ - FP_PRECISION* _multiples; - -public: - - Quadrature(quadratureType type=TABUCHI, int num_polar_angles=3); - virtual ~Quadrature(); - - int getNumPolarAngles() const; - quadratureType getType() const; - FP_PRECISION getSinTheta(const int n) const; - FP_PRECISION getWeight(const int n) const; - FP_PRECISION getMultiple(const int n) const; - FP_PRECISION* getSinThetas(); - FP_PRECISION* getWeights(); - FP_PRECISION* getMultiples(); - std::string toString(); -}; - - -#endif /* QUADRATURE_H_ */ diff --git a/src/Solver.cpp b/src/Solver.cpp index 682757531..b285cf66e 100644 --- a/src/Solver.cpp +++ b/src/Solver.cpp @@ -2,68 +2,49 @@ /** * @brief Constructor initializes an empty Solver class with array pointers * set to NULL. - * @details If the constructor receives Geometry and TrackGenerator - * objects it will retrieve the number of energy groups - * and FSRs from the Geometry and azimuthal angles from the - * TrackGenerator. - * @param geometry an optional pointer to a Geometry object * @param track_generator an optional pointer to a TrackGenerator object */ -Solver::Solver(Geometry* geometry, TrackGenerator* track_generator) { +Solver::Solver(TrackGenerator* track_generator) { /* Default values */ _num_materials = 0; _num_groups = 0; _num_azim = 0; - _polar_times_groups = 0; + _num_parallel_track_groups = 0; _num_FSRs = 0; _num_fissionable_FSRs = 0; - _num_mesh_cells = 0; _FSR_volumes = NULL; _FSR_materials = NULL; - _surface_currents = NULL; - _quad = NULL; _track_generator = NULL; _geometry = NULL; _cmfd = NULL; + _exp_evaluator = new ExpEvaluator(); _tracks = NULL; - _azim_weights = NULL; _polar_weights = NULL; _boundary_flux = NULL; - _boundary_leakage = NULL; _scalar_flux = NULL; - _fission_sources = NULL; - _scatter_sources = NULL; - _old_fission_sources = NULL; + _old_scalar_flux = NULL; + _fixed_sources = NULL; _reduced_sources = NULL; - _source_residuals = NULL; - - _interpolate_exponential = true; - _exp_table = NULL; - - if (geometry != NULL){ - _cmfd = geometry->getCmfd(); - setGeometry(geometry); - } if (track_generator != NULL) setTrackGenerator(track_generator); /* Default polar quadrature */ - _quadrature_type = TABUCHI; + _user_polar_quad = false; + _polar_quad = new TYPolarQuad(); _num_polar = 3; - _two_times_num_polar = 2 * _num_polar; + _polar_times_groups = 0; _num_iterations = 0; - _source_convergence_thresh = 1E-3; - _converged_source = false; + setConvergenceThreshold(1E-5); + _user_fluxes = false; _timer = new Timer(); - } @@ -88,29 +69,26 @@ Solver::~Solver() { if (_boundary_flux != NULL) delete [] _boundary_flux; - if (_scalar_flux != NULL) + if (_scalar_flux != NULL && !_user_fluxes) delete [] _scalar_flux; - if (_fission_sources != NULL) - delete [] _fission_sources; - - if (_scatter_sources != NULL) - delete [] _scatter_sources; + if (_old_scalar_flux != NULL) + delete [] _old_scalar_flux; - if (_old_fission_sources != NULL) - delete [] _old_fission_sources; + if (_fixed_sources != NULL) + delete [] _fixed_sources; if (_reduced_sources != NULL) delete [] _reduced_sources; - if (_source_residuals != NULL) - delete [] _source_residuals; + if (_exp_evaluator != NULL) + delete _exp_evaluator; - if (_exp_table != NULL) - delete [] _exp_table; + if (_timer != NULL) + delete _timer; - if (_quad != NULL) - delete _quad; + if (_polar_quad != NULL && !_user_polar_quad) + delete _polar_quad; } @@ -128,6 +106,7 @@ Geometry* Solver::getGeometry() { } + /** * @brief Returns a pointer to the TrackGenerator. * @return a pointer to the TrackGenerator @@ -143,20 +122,44 @@ TrackGenerator* Solver::getTrackGenerator() { /** - * @brief Returns the number of angles used for the polar quadrature (1,2,3). - * @return the number of polar angles + * @brief Returns a pointer to the PolarQuad. + * @return a pointer to the PolarQuad */ -int Solver::getNumPolarAngles() { - return _num_polar; +PolarQuad* Solver::getPolarQuad() { + + if (_polar_quad == NULL) + log_printf(ERROR, "Unable to return the Solver's PolarQuad " + "since it has not yet been set"); + + return _polar_quad; +} + + +/** + * @brief Returns the calculated volume for a flat source region. + * @param fsr_id the flat source region ID of interest + * @return the flat source region volume + */ +FP_PRECISION Solver::getFSRVolume(int fsr_id) { + + if (fsr_id < 0 || fsr_id > _num_FSRs) + log_printf(ERROR, "Unable to get the volume for FSR %d since the FSR " + "IDs lie in the range (0, %d)", fsr_id, _num_FSRs); + + else if (_FSR_volumes == NULL) + log_printf(ERROR, "Unable to get the volume for FSR %d since the FSR " + "volumes have not yet been computed", fsr_id); + + return _FSR_volumes[fsr_id]; } /** - * @brief Returns the type of polar quadrature in use (TABUCHI or LEONARD). - * @return the type of polar quadrature + * @brief Returns the number of angles used for the polar quadrature. + * @return the number of polar angles */ -quadratureType Solver::getPolarQuadratureType() { - return _quadrature_type; +int Solver::getNumPolarAngles() { + return _num_polar; } @@ -174,7 +177,7 @@ int Solver::getNumIterations() { * @return the time to converge the source (seconds) */ double Solver::getTotalTime() { - return _timer->getSplit("Total time to converge the source"); + return _timer->getSplit("Total time"); } @@ -188,30 +191,26 @@ FP_PRECISION Solver::getKeff() { /** - * @brief Returns the threshold for source convergence. - * @return the threshold for source convergence + * @brief Returns the threshold for source/flux convergence. + * @return the threshold for source/flux convergence */ -FP_PRECISION Solver::getSourceConvergenceThreshold() { - return _source_convergence_thresh; +FP_PRECISION Solver::getConvergenceThreshold() { + return _converge_thresh; } /** - * @brief Returns whether the Solver is using single floating point precision. - * @return true if so, false otherwise + * @brief Get the maximum allowable optical length for a track segment + * @return The max optical length */ -bool Solver::isUsingSinglePrecision() { -#ifdef SINGLE - return true; -#else - return false; -#endif +FP_PRECISION Solver::getMaxOpticalLength() { + return _exp_evaluator->getMaxOpticalLength(); } /** * @brief Returns whether the solver is using double floating point precision. - * @return true if so, false otherwise + * @return true if using double precision float point arithmetic */ bool Solver::isUsingDoublePrecision() { #ifdef DOUBLE @@ -225,43 +224,110 @@ bool Solver::isUsingDoublePrecision() { /** * @brief Returns whether the Solver uses linear interpolation to * compute exponentials. - * @details The Solver uses linear interpolation to compute exponentials by - * default. The Solver::useExponentialIntrinsic() routine can be - * called to use the C++ exponential intrinsic routine instead. The - * Solver::useExponentialInterpolation() routine may be called to - * return to using linear interpolation. - * @return true if so, false otherwise + * @return true if using linear interpolation to compute exponentials */ bool Solver::isUsingExponentialInterpolation() { - return _interpolate_exponential; + return _exp_evaluator->isUsingInterpolation(); +} + + +/** + * @brief Returns the source for some energy group for a flat source region + * @details This is a helper routine used by the openmoc.process module. + * @param fsr_id the ID for the FSR of interest + * @param group the energy group of interest + * @return the flat source region source + */ +FP_PRECISION Solver::getFSRSource(int fsr_id, int group) { + + if (fsr_id >= _num_FSRs) + log_printf(ERROR, "Unable to return a source for FSR ID = %d " + "since the max FSR ID = %d", fsr_id, _num_FSRs-1); + + else if (fsr_id < 0) + log_printf(ERROR, "Unable to return a source for FSR ID = %d " + "since FSRs do not have negative IDs", fsr_id); + + else if (group-1 >= _num_groups) + log_printf(ERROR, "Unable to return a source in group %d " + "since there are only %d groups", group, _num_groups); + + else if (group <= 0) + log_printf(ERROR, "Unable to return a source in group %d " + "since groups must be greater or equal to 1", group); + + else if (_scalar_flux == NULL) + log_printf(ERROR, "Unable to return a source " + "since it has not yet been computed"); + + /* Get Material and cross-sections */ + Material* material = _FSR_materials[fsr_id]; + FP_PRECISION* sigma_s = material->getSigmaS(); + FP_PRECISION* fiss_mat = material->getFissionMatrix(); + + FP_PRECISION fission_source = 0.0; + FP_PRECISION scatter_source = 0.0; + FP_PRECISION total_source; + + /* Compute total scattering and fission sources for this FSR */ + for (int g=0; g < _num_groups; g++) { + scatter_source += sigma_s[(group-1)*(_num_groups)+g] + * _scalar_flux(fsr_id,g); + fission_source += fiss_mat[(group-1)*(_num_groups)+g] + * _scalar_flux(fsr_id,g); + } + + fission_source /= _k_eff; + + /* Compute the total source */ + total_source = fission_source + scatter_source; + + /* Add in fixed source (if specified by user) */ + total_source += _fixed_sources(fsr_id,group-1); + + /* Normalize to solid angle for isotropic approximation */ + total_source *= ONE_OVER_FOUR_PI; + + return total_source; } /** - * @brief Returns whether the Solver uses the exponential intrinsic exp(...) - * routine to compute exponentials. - * @details The Solver uses linear interpolation to compute exponentials by - * default. The Solver::useExponentialIntrinsic() routine can be - * called to use the C++ exponential intrinsic routine instead. - * @return true if so, false otherwise + * @brief Returns the scalar flux for some FSR and energy group. + * @param fsr_id the ID for the FSR of interest + * @param group the energy group of interest + * @return the FSR scalar flux */ -bool Solver::isUsingExponentialIntrinsic() { - return !_interpolate_exponential; +FP_PRECISION Solver::getFlux(int fsr_id, int group) { + + if (fsr_id >= _num_FSRs) + log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " + "since the max FSR ID = %d", fsr_id, _num_FSRs-1); + + else if (fsr_id < 0) + log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " + "since FSRs do not have negative IDs", fsr_id); + + else if (group-1 >= _num_groups) + log_printf(ERROR, "Unable to return a scalar flux in group %d " + "since there are only %d groups", group, _num_groups); + + else if (group <= 0) + log_printf(ERROR, "Unable to return a scalar flux in group %d " + "since groups must be greater or equal to 1", group); + + else if (_scalar_flux == NULL) + log_printf(ERROR, "Unable to return a scalar flux " + "since it has not yet been computed"); + + return _scalar_flux(fsr_id,group-1); } /** * @brief Sets the Geometry for the Solver. - * @details The Geometry must already have initialized FSR offset maps - * and segmentized the TrackGenerator's tracks. Each of these - * should be initiated in Python prior to assigning a Geometry - * to the Solver: - * - * @code - * geometry.initializeFlatSourceRegions() - * track_generator.generateTracks() - * @endcode - * + * @details This is a private setter method for the Solver and is not + * intended to be called by the user. * @param geometry a pointer to a Geometry object */ void Solver::setGeometry(Geometry* geometry) { @@ -271,13 +337,6 @@ void Solver::setGeometry(Geometry* geometry) { "Geometry has not yet initialized FSRs"); _geometry = geometry; - _num_FSRs = _geometry->getNumFSRs(); - _num_groups = _geometry->getNumEnergyGroups(); - _polar_times_groups = _num_groups * _num_polar; - _num_materials = _geometry->getNumMaterials(); - - if (_cmfd != NULL) - _num_mesh_cells = _cmfd->getNumCells(); } @@ -290,6 +349,7 @@ void Solver::setGeometry(Geometry* geometry) { * * @code * track_generator.generateTracks() + * solver.setTrackGenerator(track_generator) * @endcode * * @param track_generator a pointer to a TrackGenerator object @@ -302,65 +362,117 @@ void Solver::setTrackGenerator(TrackGenerator* track_generator) { _track_generator = track_generator; _num_azim = _track_generator->getNumAzim() / 2; - _num_tracks = _track_generator->getNumTracksArray(); + _num_parallel_track_groups = _track_generator->getNumParallelTrackGroups(); _tot_num_tracks = _track_generator->getNumTracks(); - _azim_weights = _track_generator->getAzimWeights(); - _tracks = new Track*[_tot_num_tracks]; + _tracks = _track_generator->getTracksByParallelGroup(); - /* Initialize the tracks array */ - int counter = 0; + /* Retrieve and store the Geometry from the TrackGenerator */ + setGeometry(_track_generator->getGeometry()); +} - for (int i=0; i < _num_azim; i++) { - for (int j=0; j < _num_tracks[i]; j++) { - _tracks[counter] = &_track_generator->getTracks()[i][j]; - counter++; - } - } + +/** + * @brief Assign a PolarQuad object to the Solver. + * @details This routine allows use of a PolarQuad with any polar angle + * quadrature. Alternatively, this routine may take in any subclass + * of the PolarQuad parent class, including TYPolarQuad (default), + * LeonardPolarQuad, GLPolarQuad, etc. + * + * Users may assign a PolarQuad object to the Solver from + * Python script as follows: + * + * @code + * polar_quad = openmoc.LeonardPolarQuad() + * polar_quad.setNumPolarAngles(2) + * solver.setPolarQuadrature(polar_quad) + * @endcode + * + * @param polar_quad a pointer to a PolarQuad object + */ +void Solver::setPolarQuadrature(PolarQuad* polar_quad) { + _user_polar_quad = true; + _polar_quad = polar_quad; + _num_polar = _polar_quad->getNumPolarAngles(); + _polar_times_groups = _num_groups * _num_polar; } /** - * @brief Sets the type of polar angle quadrature set to use (ie, TABUCHI - * or LEONARD). - * @param quadrature_type the polar angle quadrature type + * @brief Sets the threshold for source/flux convergence. + * @brief The default threshold for convergence is 1E-5. + * @param source_thresh the threshold for source/flux convergence */ -void Solver::setPolarQuadratureType(quadratureType quadrature_type) { - _quadrature_type = quadrature_type; +void Solver::setConvergenceThreshold(FP_PRECISION threshold) { + + if (threshold <= 0.0) + log_printf(ERROR, "Unable to set the convergence threshold to %f " + "since it is not a positive number", threshold); + + _converge_thresh = threshold; } /** - * @brief Sets the number of polar angles to use (only 1, 2, or 3 currently - * supported). The default of 3 angles is recommended. - * @param num_polar the number of polar angles + * @brief Assign a fixed source for a flat source region and energy group. + * @param fsr_id the flat source region ID + * @param group the energy group + * @param source the volume-averaged source in this group */ -void Solver::setNumPolarAngles(int num_polar) { +void Solver::setFixedSourceByFSR(int fsr_id, int group, FP_PRECISION source) { + _fix_src_FSR_map[std::pair(fsr_id, group)] = source; +} - if (num_polar <= 0) - log_printf(ERROR, "Unable to set the Solver's number of polar angles " - "to %d since this is a negative number", num_polar); - if (num_polar > 3) - log_printf(ERROR, "Unable to set the Solver's number of polar angles to %d" - "since only 1, 2 or 3 are currently supported", num_polar); +/** + * @brief Assign a fixed source for a Cell and energy group. + * @param cell the Cell of interest + * @param group the energy group + * @param source the volume-averaged source in this group + */ +void Solver::setFixedSourceByCell(Cell* cell, int group, FP_PRECISION source) { + + /* Recursively add the source to all Cells within a FILL type Cell */ + if (cell->getType() == FILL) { + std::map cells = cell->getAllCells(); + std::map::iterator iter; + for (iter = cells.begin(); iter != cells.end(); ++iter) + setFixedSourceByCell(iter->second, group, source); + } + else + _fix_src_cell_map[std::pair(cell, group)] = source; +} - _num_polar = num_polar; - _two_times_num_polar = 2 * _num_polar; - _polar_times_groups = _num_groups * _num_polar; + +/** + * @brief Assign a fixed source for a Material and energy group. + * @param material the Material of interest + * @param group the energy group + * @param source the volume-averaged source in this group + */ +void Solver::setFixedSourceByMaterial(Material* material, int group, + FP_PRECISION source) { + _fix_src_material_map[std::pair(material, group)] = source; } /** - * @brief Sets the threshold for source convergence (>0) - * @param source_thresh the threshold for source convergence + * @brief Set the maximum allowable optical length for a track segment + * @param max_optical_length The max optical length */ -void Solver::setSourceConvergenceThreshold(FP_PRECISION source_thresh) { +void Solver::setMaxOpticalLength(FP_PRECISION max_optical_length) { + _exp_evaluator->setMaxOpticalLength(max_optical_length); +} - if (source_thresh <= 0.0) - log_printf(ERROR, "Unable to set the source convergence threshold to %f" - "since the threshold must be a positive number", source_thresh); - _source_convergence_thresh = source_thresh; +/** + * @brief Set the precision, or maximum allowable approximation error, of the + * the exponential interpolation table. + * @details By default, the precision is 1E-5 based on the analysis in + * Yamamoto's 2003 paper. + * @param precision the precision of the exponential interpolation table, + */ +void Solver::setExpPrecision(FP_PRECISION precision) { + _exp_evaluator->setExpPrecision(precision); } @@ -369,16 +481,203 @@ void Solver::setSourceConvergenceThreshold(FP_PRECISION source_thresh) { * exponential in the transport equation. */ void Solver::useExponentialInterpolation() { - _interpolate_exponential = true; + _exp_evaluator->useInterpolation(); } /** - * @brief Informs the Solver to use the exponential intrinsic exp(...) function - * to compute the exponential in the transport equation + * @brief Informs the Solver to use the exponential intrinsic exp(...) + * function to compute the exponential in the transport equation. */ void Solver::useExponentialIntrinsic() { - _interpolate_exponential = false; + _exp_evaluator->useIntrinsic(); +} + + +/** + * @brief Initializes a new PolarQuad object. + * @details Deletes memory old PolarQuad if one was previously allocated. + */ +void Solver::initializePolarQuadrature() { + + FP_PRECISION* azim_weights = _track_generator->getAzimWeights(); + + /* Initialize the PolarQuad object */ + _polar_quad->setNumPolarAngles(_num_polar); + _polar_quad->initialize(); + _polar_times_groups = _num_groups * _num_polar; + + /* Deallocate polar weights if previously assigned */ + if (_polar_weights != NULL) + delete [] _polar_weights; + + _polar_weights = new FP_PRECISION[_num_azim*_num_polar]; + + /* Compute the total azimuthal weight for tracks at each polar angle */ +#pragma omp parallel for schedule(guided) + for (int i=0; i < _num_azim; i++) { + for (int p=0; p < _num_polar; p++) + _polar_weights(i,p) = + azim_weights[i] * _polar_quad->getMultiple(p) * FOUR_PI; + } +} + + +/** + * @brief Initializes new ExpEvaluator object to compute exponentials. + */ +void Solver::initializeExpEvaluator() { + + _exp_evaluator->setPolarQuadrature(_polar_quad); + + if (_exp_evaluator->isUsingInterpolation()) { + + /* Find minimum of optional user-specified and actual max taus */ + FP_PRECISION max_tau_a = _track_generator->getMaxOpticalLength(); + FP_PRECISION max_tau_b = _exp_evaluator->getMaxOpticalLength(); + FP_PRECISION max_tau = std::min(max_tau_a, max_tau_b) + TAU_NUDGE; + + /* Split Track segments so that none has a greater optical length */ + _track_generator->splitSegments(max_tau); + + /* Initialize exponential interpolation table */ + _exp_evaluator->setMaxOpticalLength(max_tau); + _exp_evaluator->initialize(); + } +} + + +/** + * @brief Initializes the Material fission matrices. + * @details In an adjoint calculation, this routine will transpose the + * scattering and fission matrices in each material. + * @param mode the solution type (FORWARD or ADJOINT) + */ +void Solver::initializeMaterials(solverMode mode) { + + log_printf(INFO, "Initializing materials..."); + + std::map materials = _geometry->getAllMaterials(); + std::map::iterator m_iter; + + for (m_iter = materials.begin(); m_iter != materials.end(); ++m_iter) { + m_iter->second->buildFissionMatrix(); + + if (mode == ADJOINT) + m_iter->second->transposeProductionMatrices(); + } +} + + +/** + * @brief Initializes the FSR volumes and Materials array. + * @details This method assigns each FSR a unique, monotonically increasing + * ID, sets the Material for each FSR, and assigns a volume based on + * the cumulative length of all of the segments inside the FSR. + */ +void Solver::initializeFSRs() { + + log_printf(INFO, "Initializing flat source regions..."); + + /* Delete old FSR arrays if they exist */ + if (_FSR_volumes != NULL) + delete [] _FSR_volumes; + + if (_FSR_materials != NULL) + delete [] _FSR_materials; + + /* Retrieve simulation parameters from the Geometry */ + _num_FSRs = _geometry->getNumFSRs(); + _num_groups = _geometry->getNumEnergyGroups(); + _polar_times_groups = _num_groups * _num_polar; + _num_materials = _geometry->getNumMaterials(); + + /* Get an array of volumes indexed by FSR */ + _FSR_volumes = _track_generator->getFSRVolumes(); + + /* Generate the FSR centroids */ + _track_generator->generateFSRCentroids(); + + /* Attach the correct materials to each track segment */ + _track_generator->initializeSegments(); + + /* Allocate an array of Material pointers indexed by FSR */ + _FSR_materials = new Material*[_num_FSRs]; + + /* Loop over all FSRs to extract FSR material pointers */ + for (int r=0; r < _num_FSRs; r++) { + _FSR_materials[r] = _geometry->findFSRMaterial(r); + log_printf(INFO, "FSR ID = %d has Material ID = %d and volume = %f ", + r, _FSR_materials[r]->getId(), _FSR_volumes[r]); + } +} + + +/** + * @brief Counts the number of fissionable flat source regions. + * @details This routine is used by the Solver::computeEigenvalue(...) + * routine which uses the number of fissionable FSRs to normalize + * the residual on the fission source distribution. + */ +void Solver::countFissionableFSRs() { + + log_printf(INFO, "Counting fissionable FSRs..."); + + /* Count the number of fissionable FSRs */ + _num_fissionable_FSRs = 0; + for (int r=0; r < _num_FSRs; r++) { + if (_FSR_materials[r]->isFissionable()) + _num_fissionable_FSRs++; + } +} + + +/** + * @brief Assigns fixed sources assigned by Cell, Material to FSRs. + */ +void Solver::initializeFixedSources() { + + Cell* fsr_cell; + Material* fsr_material; + int group; + FP_PRECISION source; + std::pair cell_group_key; + std::pair mat_group_key; + std::map< std::pair, FP_PRECISION >::iterator cell_iter; + std::map< std::pair, FP_PRECISION >::iterator mat_iter; + + /* Fixed sources assigned by Cell */ + for (cell_iter = _fix_src_cell_map.begin(); + cell_iter != _fix_src_cell_map.end(); ++cell_iter) { + + /* Get the Cell with an assigned fixed source */ + cell_group_key = cell_iter->first; + group = cell_group_key.second; + source = _fix_src_cell_map[cell_group_key]; + + /* Search for this Cell in all FSRs */ + for (int r=0; r < _num_FSRs; r++) { + fsr_cell = _geometry->findCellContainingFSR(r); + if (cell_group_key.first->getId() == fsr_cell->getId()) + setFixedSourceByFSR(r, group, source); + } + } + + /** Fixed sources assigned by Material */ + for (mat_iter = _fix_src_material_map.begin(); + mat_iter != _fix_src_material_map.end(); ++mat_iter) { + + /* Get the Material with an assigned fixed source */ + mat_group_key = mat_iter->first; + group = mat_group_key.second; + source = _fix_src_material_map[mat_group_key]; + + for (int r=0; r < _num_FSRs; r++) { + fsr_material = _geometry->findFSRMaterial(r); + if (mat_group_key.first->getId() == fsr_material->getId()) + setFixedSourceByFSR(r, group, source); + } + } } @@ -386,71 +685,304 @@ void Solver::useExponentialIntrinsic() { * @brief Initializes a Cmfd object for acceleratiion prior to source iteration. * @details Instantiates a dummy Cmfd object if one was not assigned to * the Solver by the user and initializes FSRs, materials, fluxes - * and the Mesh object. This method is for internal use only and is - * called by the Solver::convergeSource() method and should not be - * called directly by the user. + * and the Mesh object. This method is for internal use only + * and should not be called directly by the user. */ -void Solver::initializeCmfd(){ +void Solver::initializeCmfd() { log_printf(INFO, "Initializing CMFD..."); + /* Retrieve CMFD from the Geometry */ + _cmfd = _geometry->getCmfd(); + + /* If the user did not initialize Cmfd, simply return */ + if (_cmfd == NULL) + return; + else if (!_cmfd->isFluxUpdateOn()) + return; + + /* Intialize the CMFD energy group structure */ + _cmfd->setSourceConvergenceThreshold(_converge_thresh*1.e-1); + _cmfd->setNumMOCGroups(_num_groups); + _cmfd->initializeGroupMap(); + /* Give CMFD number of FSRs and FSR property arrays */ _cmfd->setNumFSRs(_num_FSRs); _cmfd->setFSRVolumes(_FSR_volumes); _cmfd->setFSRMaterials(_FSR_materials); _cmfd->setFSRFluxes(_scalar_flux); - _cmfd->setPolarQuadrature(_quadrature_type, _num_polar); + _cmfd->setPolarQuadrature(_polar_quad); + _cmfd->setGeometry(_geometry); + _cmfd->initialize(); } +/** + * @brief Returns the Material data to its original state. + * @details In an adjoint calculation, the scattering and fission matrices + * in each material are transposed during initialization. This + * routine returns both matrices to their original (FORWARD) + * state at the end of a calculation. + * @param mode the solution type (FORWARD or ADJOINT) + */ +void Solver::resetMaterials(solverMode mode) { + + if (mode == FORWARD) + return; + + log_printf(INFO, "Resetting materials..."); + + std::map materials = _geometry->getAllMaterials(); + std::map::iterator m_iter; + + for (m_iter = materials.begin(); m_iter != materials.end(); ++m_iter) + m_iter->second->transposeProductionMatrices(); +} + /** - * @brief Checks that each FSR has at least one Track segment crossing it - * and if not, throws an exception and prints an error message. - * @details This method is for internal use only and is called by the - * Solver::convergeSource() method and should not be called - * directly by the user. + * @brief This method performs one transport sweep using the fission source. + * @details This is a helper routine used for Krylov subspace methods. */ -void Solver::checkTrackSpacing() { +void Solver::fissionTransportSweep() { + computeFSRFissionSources(); + transportSweep(); + addSourceToScalarFlux(); +} - int* FSR_segment_tallies = new int[_num_FSRs]; - int num_segments; - segment* curr_segment; - segment* segments; - Cell* cell; - /* Set each tally to zero to begin with */ - #pragma omp parallel for - for (int r=0; r < _num_FSRs; r++) - FSR_segment_tallies[r] = 0; +/** + * @brief This method performs one transport sweep using the scatter source. + * @details This is a helper routine used for Krylov subspace methods. + */ +void Solver::scatterTransportSweep() { + computeFSRScatterSources(); + transportSweep(); + addSourceToScalarFlux(); +} - /* Iterate over all azimuthal angles, all tracks, and all Track segments - * and tally each segment in the corresponding FSR */ - #pragma omp parallel for private (num_segments, curr_segment) - for (int i=0; i < _tot_num_tracks; i++) { - num_segments = _tracks[i]->getNumSegments(); - segments = _tracks[i]->getSegments(); +/** + * @brief Computes the scalar flux distribution by performing a series of + * transport sweeps. + * @details This is the main method exposed to the user through the Python + * interface to compute the scalar flux distribution, e.g., for a + * fixed source calculation. This routine makes an initial guess for + * scalar and boundary fluxes and performs transport sweep until + * convergence. + * + * By default, this method will perform a maximum of 1000 transport + * sweeps with a 1E-5 threshold on the average FSR scalar flux. These + * values may be freely modified by the user at runtime. + * + * The only_fixed_source runtime parameter may be used to control + * the type of source distribution used in the calculation. By + * default, this paramter is true and only the fixed sources specified + * by the user will be considered. Alternatively, when the parameter + * is false, the source will be computed as the scattering and fission + * sources resulting from a previously computed flux distribution + * (e.g., an eigenvalue calculation) in addition to any user-defined + * fixed sources. + * + * This method may be called by the user to compute the scalar flux + * for a fixed source distribution from Python as follows: + * + * @code + * // Assign fixed sources + * // ... + * + * // Find the flux distribution resulting from the fixed sources + * solver.computeFlux(max_iters=100) + * @endcode + * + * Alternatively, as described above, this method may be called by + * the user in Python to compute the flux from a superposition of + * fixed and / or eigenvalue sources as follows: + * + * @code + * // Solve for sources and scalar flux distribution + * solver.computeEigenvalue(max_iters=1000) + * + * // Add fixed source(s) + * // ... + * + * // Find fluxes from superposition of eigenvalue and fixed sources + * solver.computeFlux(max_iters=100, only_fixed_source=False) + * @endcode + * + * + * @param max_iters the maximum number of source iterations to allow + * @param mode the solution type (FORWARD or ADJOINT) + * @param only_fixed_source use only fixed sources (true by default) + */ +void Solver::computeFlux(int max_iters, solverMode mode, + bool only_fixed_source) { - for (int s=0; s < num_segments; s++) { - curr_segment = &segments[s]; - FSR_segment_tallies[curr_segment->_region_id]++; - } + if (_track_generator == NULL) + log_printf(ERROR, "The Solver is unable to compute the flux " + "since it does not contain a TrackGenerator"); + + log_printf(NORMAL, "Computing the flux..."); + + /* Clear all timing data from a previous simulation run */ + clearTimerSplits(); + + /* Start the timer to record the total time to converge the flux */ + _timer->startTimer(); + + /* Initialize keff to 1 for FSR source calculations */ + _k_eff = 1.; + + _num_iterations = 0; + FP_PRECISION residual = 0.; + + /* Initialize data structures */ + initializeFSRs(); + initializeMaterials(mode); + countFissionableFSRs(); + initializePolarQuadrature(); + initializeExpEvaluator(); + + /* Initialize new flux arrays if a) the user requested the use of + * only fixed sources or b) no previous simulation was performed which + * initialized and computed the flux (e.g., an eigenvalue calculation) */ + if (only_fixed_source || _num_iterations == 0) { + initializeFluxArrays(); + flattenFSRFluxes(0.0); + storeFSRFluxes(); } - /* Loop over all FSRs and if one FSR does not have tracks in it, print - * error message to the screen and exit program */ - #pragma omp parallel for private (cell) - for (int r=0; r < _num_FSRs; r++) { + initializeSourceArrays(); + zeroTrackFluxes(); - if (FSR_segment_tallies[r] == 0) { - log_printf(ERROR, "No tracks were tallied inside FSR id = %d. Please " - "reduce your track spacing, increase the number of azimuthal" - "angles, or increase the size of the FSRs", r); - } + /* Compute the sum of fixed, total and scattering sources */ + computeFSRSources(); + + /* Source iteration loop */ + for (int i=0; i < max_iters; i++) { + + transportSweep(); + addSourceToScalarFlux(); + residual = computeResidual(SCALAR_FLUX); + storeFSRFluxes(); + _num_iterations++; + + log_printf(NORMAL, "Iteration %d:\tres = %1.3E", i, residual); + + /* Check for convergence */ + if (i > 1 && residual < _converge_thresh) + break; } - delete [] FSR_segment_tallies; + if (_num_iterations == max_iters-1) + log_printf(WARNING, "Unable to converge the flux"); + + resetMaterials(mode); + + _timer->stopTimer(); + _timer->recordSplit("Total time"); +} + + +/** + * @brief Computes the total source distribution by performing a series of + * transport sweep and source updates. + * @details This is the main method exposed to the user through the Python + * interface to compute the source distribution, e.g., for a fixed + * and/or external source calculation. This routine makes an initial + * guess for the scalar and boundary fluxes and performs transport + * sweeps and source updates until convergence. + * + * By default, this method will perform a maximum of 1000 transport + * sweeps with a 1E-5 threshold on the integrated FSR total source. + * These values may be freely modified by the user at runtime. + * + * The k_eff parameter may be used for fixed source calculations + * with fissionable material (e.g., start-up in a reactor from + * a fixed external source). In this case, the user must "guess" + * the critical eigenvalue to be be used to scale the fission source. + * + * The res_type parameter may be used to control the convergence + * criterion - SCALAR_FLUX, TOTAL_SOURCE (default) and FISSION_SOURCE + * are all supported options in OpenMOC at this time. + * + * This method may be called by the user from Python as follows: + * + * @code + * // Assign fixed sources + * // ... + * + * // Find the flux distribution resulting from the fixed sources + * solver.computeSource(max_iters=100, k_eff=0.981) + * @endcode + * + * @param max_iters the maximum number of source iterations to allow + * @param mode the solution type (FORWARD or ADJOINT) + * @param k_eff the sub/super-critical eigenvalue (default 1.0) + * @param res_type the type of residual used for the convergence criterion + */ +void Solver::computeSource(int max_iters, solverMode mode, + double k_eff, residualType res_type) { + + if (_track_generator == NULL) + log_printf(ERROR, "The Solver is unable to compute the source " + "since it does not contain a TrackGenerator"); + + else if (k_eff <= 0.) + log_printf(ERROR, "The Solver is unable to compute the source with " + "keff = %f since it is not a positive value", k_eff); + + log_printf(NORMAL, "Computing the source..."); + + /* Clear all timing data from a previous simulation run */ + clearTimerSplits(); + + /* Start the timer to record the total time to converge the flux */ + _timer->startTimer(); + + /* Set the eigenvalue to the user-specified value */ + _k_eff = k_eff; + + _num_iterations = 0; + FP_PRECISION residual = 0.; + + /* Initialize data structures */ + initializeFSRs(); + initializeMaterials(mode); + initializePolarQuadrature(); + initializeExpEvaluator(); + initializeFluxArrays(); + initializeSourceArrays(); + + /* Guess unity scalar flux for each region */ + flattenFSRFluxes(1.0); + storeFSRFluxes(); + zeroTrackFluxes(); + + /* Source iteration loop */ + for (int i=0; i < max_iters; i++) { + + computeFSRSources(); + transportSweep(); + addSourceToScalarFlux(); + residual = computeResidual(res_type); + storeFSRFluxes(); + _num_iterations++; + + log_printf(NORMAL, "Iteration %d:\tres = %1.3E", i, residual); + + /* Check for convergence */ + if (i > 1 && residual < _converge_thresh) + break; + } + + if (_num_iterations == max_iters-1) + log_printf(WARNING, "Unable to converge the source distribution"); + + resetMaterials(mode); + + _timer->stopTimer(); + _timer->recordSplit("Total time"); } @@ -458,31 +990,34 @@ void Solver::checkTrackSpacing() { * @brief Computes keff by performing a series of transport sweep and * source updates. * @details This is the main method exposed to the user through the Python - * interface to run a simulation. The method makes an initial guess - * for the scalar and boundary fluxes and peforms transport sweeps - * and source updates until convergence. The method may be called - * by the user from Python as follows: + * interface to perform an eigenvalue calculation. The method makes + * an initial guess for the scalar and boundary fluxes and performs + * transport sweeps and source updates until convergence. + * + * By default, this method will perform a maximum of 1000 transport + * sweeps with a 1E-5 threshold on the integrated FSR fission source. + * These values may be freely modified by the user at runtime. + * + * The res_type parameter may be used to control the convergence + * criterion - SCALAR_FLUX, TOTAL_SOURCE and FISSION_SOURCE (default) + * are all supported options in OpenMOC at this time. * * @code - * max_iters = 1000 - * solver.convergeSource(max_iters) + * solver.computeEigenvalue(max_iters=100, res_type=FISSION_SOURCE) * @endcode * - * @param max_iterations the maximum number of source iterations to allow - * @return the value of the computed eigenvalue \f$ k_{eff} \f$ + * @param max_iters the maximum number of source iterations to allow + * @param mode the solution type (FORWARD or ADJOINT) + * @param res_type the type of residual used for the convergence criterion */ -FP_PRECISION Solver::convergeSource(int max_iterations) { - - /* Error checking */ - if (_geometry == NULL) - log_printf(ERROR, "The Solver is unable to converge the source " - "since it does not contain a Geometry"); +void Solver::computeEigenvalue(int max_iters, solverMode mode, + residualType res_type) { if (_track_generator == NULL) - log_printf(ERROR, "The Solver is unable to converge the source " + log_printf(ERROR, "The Solver is unable to compute the eigenvalue " "since it does not contain a TrackGenerator"); - log_printf(NORMAL, "Converging the source..."); + log_printf(NORMAL, "Computing the eigenvalue..."); /* Clear all timing data from a previous simulation run */ clearTimerSplits(); @@ -490,73 +1025,61 @@ FP_PRECISION Solver::convergeSource(int max_iterations) { /* Start the timer to record the total time to converge the source */ _timer->startTimer(); - /* Counter for the number of iterations to converge the source */ _num_iterations = 0; + FP_PRECISION residual = 0.; /* An initial guess for the eigenvalue */ _k_eff = 1.0; - /* The residual on the source */ - FP_PRECISION residual = 0.0; - - /* The old residual and k_eff */ - FP_PRECISION residual_old = 1.0; - FP_PRECISION keff_old = 1.0; - /* Initialize data structures */ + initializeFSRs(); + initializeMaterials(mode); + countFissionableFSRs(); initializePolarQuadrature(); + initializeExpEvaluator(); initializeFluxArrays(); initializeSourceArrays(); - buildExpInterpTable(); - initializeFSRs(); - - if (_cmfd != NULL && _cmfd->isFluxUpdateOn()) - initializeCmfd(); - - /* Check that each FSR has at least one segment crossing it */ - checkTrackSpacing(); + initializeCmfd(); /* Set scalar flux to unity for each region */ - flattenFSRSources(1.0); flattenFSRFluxes(1.0); + storeFSRFluxes(); zeroTrackFluxes(); /* Source iteration loop */ - for (int i=0; i < max_iterations; i++) { - - log_printf(NORMAL, "Iteration %d: \tk_eff = %1.6f" - "\tres = %1.3E", i, _k_eff, residual); - + for (int i=0; i < max_iters; i++) { normalizeFluxes(); - residual = computeFSRSources(); + computeFSRSources(); transportSweep(); addSourceToScalarFlux(); /* Solve CMFD diffusion problem and update MOC flux */ - if (_cmfd != NULL && _cmfd->isFluxUpdateOn()){ + if (_cmfd != NULL && _cmfd->isFluxUpdateOn()) { _k_eff = _cmfd->computeKeff(i); _cmfd->updateBoundaryFlux(_tracks, _boundary_flux, _tot_num_tracks); } else computeKeff(); + log_printf(NORMAL, "Iteration %d:\tk_eff = %1.6f" + "\tres = %1.3E", i, _k_eff, residual); + + residual = computeResidual(res_type); + storeFSRFluxes(); _num_iterations++; - /* Check for convergence of the fission source distribution */ - if (i > 1 && residual < _source_convergence_thresh) { - _timer->stopTimer(); - _timer->recordSplit("Total time to converge the source"); - return _k_eff; - } + /* Check for convergence */ + if (i > 1 && residual < _converge_thresh) + break; } - _timer->stopTimer(); - _timer->recordSplit("Total time to converge the source"); + if (_num_iterations == max_iters-1) + log_printf(WARNING, "Unable to converge the source distribution"); - log_printf(WARNING, "Unable to converge the source after %d iterations", - max_iterations); + resetMaterials(mode); - return _k_eff; + _timer->stopTimer(); + _timer->recordSplit("Total time"); } @@ -565,7 +1088,7 @@ FP_PRECISION Solver::convergeSource(int max_iterations) { * code in the source convergence loop. */ void Solver::clearTimerSplits() { - _timer->clearSplit("Total time to converge the source"); + _timer->clearSplit("Total time"); } @@ -579,17 +1102,11 @@ void Solver::printTimerReport() { log_printf(TITLE, "TIMING REPORT"); /* Get the total runtime */ - double tot_time = _timer->getSplit("Total time to converge the source"); + double tot_time = _timer->getSplit("Total time"); msg_string = "Total time to solution"; msg_string.resize(53, '.'); log_printf(RESULT, "%s%1.4E sec", msg_string.c_str(), tot_time); - /* Time per unknown */ - double time_per_unknown = tot_time / (_num_FSRs * _num_groups); - msg_string = "Solution time per unknown"; - msg_string.resize(53, '.'); - log_printf(RESULT, "%s%1.4E sec", msg_string.c_str(), time_per_unknown); - /* Time per iteration */ double time_per_iter = tot_time / _num_iterations; msg_string = "Solution time per iteration"; @@ -600,7 +1117,7 @@ void Solver::printTimerReport() { int num_segments = _track_generator->getNumSegments(); int num_integrations = 2 * _num_polar * _num_groups * num_segments; double time_per_integration = (time_per_iter / num_integrations); - msg_string = "Integration time per segment integration"; + msg_string = "Time per segment integration"; msg_string.resize(53, '.'); log_printf(RESULT, "%s%1.4E sec", msg_string.c_str(), time_per_integration); @@ -615,7 +1132,7 @@ void Solver::printTimerReport() { num_digits += (int) log10((double) num_segments); num_digits += (int) log10((double) _num_FSRs); - num_digits = 67 - num_digits; + num_digits = 66 - num_digits; num_digits /= 4; std::stringstream msg; diff --git a/src/Solver.h b/src/Solver.h index fb8a4f27a..3590b48b1 100644 --- a/src/Solver.h +++ b/src/Solver.h @@ -10,20 +10,23 @@ #ifdef __cplusplus #define _USE_MATH_DEFINES -#include +#ifdef SWIG +#include "Python.h" +#endif +#include "constants.h" #include "Timer.h" -#include "Quadrature.h" +#include "PolarQuad.h" #include "TrackGenerator.h" #include "Cmfd.h" +#include "ExpEvaluator.h" +#include #endif /** Indexing macro for the scalar flux in each FSR and energy group */ #define _scalar_flux(r,e) (_scalar_flux[(r)*_num_groups + (e)]) -/** Indexing macro for the surface currents for each CMFD Mesh surface and - * each energy group */ -#define _surface_currents(r,e) (_surface_currents[(r)*_cmfd->getNumCmfdGroups() \ - + _cmfd->getCmfdGroup((e))]) +/** Indexing macro for the old scalar flux in each FSR and energy group */ +#define _old_scalar_flux(r,e) (_old_scalar_flux[(r)*_num_groups + (e)]) /** Indexing macro for the total source divided by the total cross-section * (\f$ \frac{Q}{\Sigma_t} \f$) in each FSR and energy group */ @@ -40,24 +43,47 @@ + (j)*_polar_times_groups \ + (p)*_num_groups + (e)]) -/** Indexing macro for the leakage for each polar angle and energy group - * for both the forward and reverse direction for each track */ -#define _boundary_leakage(i,pe2) (_boundary_leakage[2*(i)*_polar_times_groups \ - +(pe2)]) +/** Indexing scheme for fixed sources for each FSR and energy group */ +#define _fixed_sources(r,e) (_fixed_sources[(r)*_num_groups + (e)]) /** Indexing scheme for the total fission source (\f$ \nu\Sigma_f\Phi \f$) * for each FSR and energy group */ -#define _fission_sources(r,e) (_fission_sources[(r)*_num_groups + (e)]) +#define fission_sources(r,e) (fission_sources[(r)*_num_groups + (e)]) -/** Indexing scheme for the total in-scatter source (\f$ \Sigma_s\Phi \f$) +/** Indexing scheme for the total scatter source (\f$ Sigma_s\Phi \f$) * for each FSR and energy group */ -#define _scatter_sources(r,e) (_scatter_sources[(r)*_num_groups + (e)]) +#define scatter_sources(r,e) (scatter_sources[(r)*_num_groups + (e)]) + + +/** + * @enum solverMode + * @brief The solution mode used by the MOC solver. +*/ +enum solverMode { + + /** The forward flux distribution */ + FORWARD, + + /** The adjoint flux distribution */ + ADJOINT, +}; + + +/** + * @enum residualType + * @brief The type of residual used for the convergence criterion. +*/ +enum residualType { + + /** A residual on the scalar flux distribution */ + SCALAR_FLUX, -/** The value of 4pi: \f$ 4\pi \f$ */ -#define FOUR_PI 12.5663706143 + /** A residual on the fission source distribution */ + FISSION_SOURCE, -/** The values of 1 divided by 4pi: \f$ \frac{1}{4\pi} \f$ */ -#define ONE_OVER_FOUR_PI 0.0795774715 + /** A residual on the total source distribution */ + TOTAL_SOURCE, +}; /** @@ -81,9 +107,6 @@ class Solver { /** The number of fissionable flat source regions */ int _num_fissionable_FSRs; - /** The number of mesh cells */ - int _num_mesh_cells; - /** The FSR "volumes" (i.e., areas) indexed by FSR UID */ FP_PRECISION* _FSR_volumes; @@ -100,32 +123,23 @@ class Solver { int _num_materials; /** A pointer to a polar quadrature */ - Quadrature* _quad; + PolarQuad* _polar_quad; + + /** A boolean indicating if a user-defined PolarQuad was assigned */ + bool _user_polar_quad; /** The number of polar angles */ int _num_polar; - /** Twice the number of polar angles */ - int _two_times_num_polar; - /** The number of polar angles times energy groups */ int _polar_times_groups; - /** The type of polar quadrature (TABUCHI or LEONARD) */ - quadratureType _quadrature_type; - /** A pointer to the 2D ragged array of Tracks */ Track** _tracks; - /** A pointer to an array with the number of Tracks per azimuthal angle */ - int* _num_tracks; - /** The total number of Tracks */ int _tot_num_tracks; - /** The weights for each azimuthal angle */ - FP_PRECISION* _azim_weights; - /** The weights for each polar angle in the polar angle quadrature */ FP_PRECISION* _polar_weights; @@ -134,252 +148,202 @@ class Solver { * a Track along both "forward" and "reverse" directions. */ FP_PRECISION* _boundary_flux; - /** The angular leakages for each Track for all energy groups, polar angles, - * and azimuthal angles. This array stores the weighted outgoing fluxes - * for a Track along both "forward" and "reverse" directions. */ - FP_PRECISION* _boundary_leakage; - /** The scalar flux for each energy group in each FSR */ FP_PRECISION* _scalar_flux; - /** The CMFD Mesh surface currents in each energy group */ - FP_PRECISION* _surface_currents; + /** The old scalar flux for each energy group in each FSR */ + FP_PRECISION* _old_scalar_flux; + + /** Optional user-specified fixed sources in each FSR and energy group */ + FP_PRECISION* _fixed_sources; - /** The fission source in each FSR and energy group */ - FP_PRECISION* _fission_sources; + /** A mapping of fixed sources keyed by the pair (FSR ID, energy group) */ + std::map< std::pair, FP_PRECISION > _fix_src_FSR_map; - /** The in-scatter source in each FSR and energy group */ - FP_PRECISION* _scatter_sources; + /** A mapping of fixed sources keyed by the pair (Cell*, energy group) */ + std::map< std::pair, FP_PRECISION > _fix_src_cell_map; - /** The old fission source in each FSR from the previous iteration */ - FP_PRECISION* _old_fission_sources; + /** A mapping of fixed sources keyed by the pair (Material*, energy group) */ + std::map< std::pair, FP_PRECISION > _fix_src_material_map; /** Ratios of source to total cross-section for each FSR and energy group */ FP_PRECISION* _reduced_sources; - /** An array of the residuals between the old source and the new source - * on each iteration in each FSR and energy group */ - FP_PRECISION* _source_residuals; - /** The current iteration's approximation to k-effective */ FP_PRECISION _k_eff; - /** An array of k-effective at each iteration */ - std::vector _residual_vector; - - /** The total leakage across vacuum boundaries */ - FP_PRECISION _leakage; - /** The number of source iterations needed to reach convergence */ int _num_iterations; - /** Whether or not the Solver has converged the source */ - bool _converged_source; + /** The tolerance for converging the source/flux */ + FP_PRECISION _converge_thresh; - /** The tolerance for converging the source */ - FP_PRECISION _source_convergence_thresh; + /** An ExpEvaluator to compute exponentials in the transport equation */ + ExpEvaluator* _exp_evaluator; - /** A boolean indicating whether or not to use linear interpolation - * to comptue the exponential in the transport equation */ - bool _interpolate_exponential; + /** Indicator of whether the flux array is defined by the user */ + bool _user_fluxes; - /** The exponential linear interpolation table */ - FP_PRECISION* _exp_table; + /** A timer to record timing data for a simulation */ + Timer* _timer; - /** The size of the exponential linear interpolation table */ - int _exp_table_size; + /** A pointer to a Coarse Mesh Finite Difference (CMFD) acceleration object */ + Cmfd* _cmfd; - /** The maximum index of the exponential linear interpolation table */ - int _exp_table_max_index; + /** The number of groups of tracks that can be looped over in parallel + * without data races between threads */ + int _num_parallel_track_groups; - /** The spacing for the exponential linear interpolation table */ - FP_PRECISION _exp_table_spacing; + void clearTimerSplits(); - /** The inverse spacing for the exponential linear interpolation table */ - FP_PRECISION _inverse_exp_table_spacing; +public: + Solver(TrackGenerator* track_generator=NULL); + virtual ~Solver(); - /** A timer to record timing data for a simulation */ - Timer* _timer; + virtual void setGeometry(Geometry* geometry); - /** A pointer to a Coarse Mesh Finite Difference (CMFD) acceleration object */ - Cmfd* _cmfd; + Geometry* getGeometry(); + TrackGenerator* getTrackGenerator(); + PolarQuad* getPolarQuad(); + FP_PRECISION getFSRVolume(int fsr_id); + int getNumPolarAngles(); + int getNumIterations(); + double getTotalTime(); + FP_PRECISION getKeff(); + FP_PRECISION getConvergenceThreshold(); + FP_PRECISION getMaxOpticalLength(); + bool isUsingDoublePrecision(); + bool isUsingExponentialInterpolation(); - int round_to_int(float x); - int round_to_int(double x); + virtual FP_PRECISION getFSRSource(int fsr_id, int group); + virtual FP_PRECISION getFlux(int fsr_id, int group); + virtual void getFluxes(FP_PRECISION* out_fluxes, int num_fluxes) = 0; - /** - * @brief Creates a polar quadrature object for the Solver. - */ - virtual void initializePolarQuadrature() =0; + virtual void setTrackGenerator(TrackGenerator* track_generator); + virtual void setPolarQuadrature(PolarQuad* polar_quad); + virtual void setConvergenceThreshold(FP_PRECISION threshold); + virtual void setFluxes(FP_PRECISION* in_fluxes, int num_fluxes) = 0; + void setFixedSourceByFSR(int fsr_id, int group, FP_PRECISION source); + void setFixedSourceByCell(Cell* cell, int group, FP_PRECISION source); + void setFixedSourceByMaterial(Material* material, int group, + FP_PRECISION source); + void setMaxOpticalLength(FP_PRECISION max_optical_length); + void setExpPrecision(FP_PRECISION precision); + void useExponentialInterpolation(); + void useExponentialIntrinsic(); - /** - * @brief Initializes Track boundary angular flux and leakage and - * FSR scalar flux arrays. - */ - virtual void initializeFluxArrays() =0; + virtual void initializePolarQuadrature(); + virtual void initializeExpEvaluator(); + virtual void initializeMaterials(solverMode mode=FORWARD); + virtual void initializeFSRs(); + virtual void countFissionableFSRs(); + virtual void initializeFixedSources(); + virtual void initializeCmfd(); - /** - * @brief Allocates memory for FSR source arrays. - */ - virtual void initializeSourceArrays() =0; + virtual void resetMaterials(solverMode mode=FORWARD); + virtual void fissionTransportSweep(); + virtual void scatterTransportSweep(); /** - * @brief Builds the exponential linear interpolation table. + * @brief Initializes Track boundary angular and FSR scalar flux arrays. */ - virtual void buildExpInterpTable() =0; + virtual void initializeFluxArrays() = 0; /** - * @brief Initializes the volumes and Material arrays for each FSR. + * @brief Allocates memory for FSR source arrays. */ - virtual void initializeFSRs() =0; - - virtual void initializeCmfd(); - - virtual void checkTrackSpacing(); + virtual void initializeSourceArrays() = 0; /** * @brief Zero each Track's boundary fluxes for each energy group and polar * angle in the "forward" and "reverse" directions. */ - virtual void zeroTrackFluxes() =0; + virtual void zeroTrackFluxes() = 0; /** * @brief Set the scalar flux for each FSR and energy group to some value. * @param value the value to assign to each FSR scalar flux */ - virtual void flattenFSRFluxes(FP_PRECISION value) =0; + virtual void flattenFSRFluxes(FP_PRECISION value) = 0; /** - * @brief Set the source for each FSR and energy group to some value. - * @param value the value to assign to each FSR source + * @brief Stores the current scalar fluxes in the old scalar flux array. */ - virtual void flattenFSRSources(FP_PRECISION value) =0; + virtual void storeFSRFluxes() = 0; /** * @brief Normalizes all FSR scalar fluxes and Track boundary angular * fluxes to the total fission source (times \f$ \nu \f$). */ - virtual void normalizeFluxes() =0; + virtual void normalizeFluxes() = 0; /** - * @brief Computes the total source (fission and scattering) for each FSR - * and energy group. - * @return the residual between this source and the previous source + * @brief Computes the total source (fission, scattering, fixed) for + * each FSR and energy group. */ - virtual FP_PRECISION computeFSRSources() =0; + virtual void computeFSRSources() = 0; /** - * @brief Compute \f$ k_{eff} \f$ from total fission and absorption rates - * in each FSR and energy group. + * @brief Computes the total fission source for each FSR and energy group. */ - virtual void computeKeff() =0; + virtual void computeFSRFissionSources() = 0; /** - * @brief Add the source term contribution in the transport equation to - * the FSR scalar flux. + * @brief Computes the total scattering source for each FSR and energy group. */ - virtual void addSourceToScalarFlux() =0; + virtual void computeFSRScatterSources() = 0; /** - * @brief This method performs one transport sweep of all azimuthal angles, - * Tracks, segments, polar angles and energy groups. + * @brief Computes the residual between successive flux/source iterations. + * @param res_type the type of residual (FLUX, FISSION_SOURCE, TOTAL_SOURCE) + * @return the total residual summed over FSRs and energy groups */ - virtual void transportSweep() =0; - - void clearTimerSplits(); - - -public: - Solver(Geometry* geom=NULL, TrackGenerator* track_generator=NULL); - virtual ~Solver(); - - Geometry* getGeometry(); - TrackGenerator* getTrackGenerator(); - int getNumPolarAngles(); - quadratureType getPolarQuadratureType(); - int getNumIterations(); - double getTotalTime(); - FP_PRECISION getKeff(); - FP_PRECISION getSourceConvergenceThreshold(); - - bool isUsingSinglePrecision(); - bool isUsingDoublePrecision(); - bool isUsingExponentialInterpolation(); - bool isUsingExponentialIntrinsic(); + virtual double computeResidual(residualType res_type) = 0; /** - * @brief Returns the scalar flux for a FSR and energy group. - * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest - * @return the FSR scalar flux + * @brief Compute \f$ k_{eff} \f$ from total fission and absorption rates + * in each FSR and energy group. */ - virtual FP_PRECISION getFSRScalarFlux(int fsr_id, int energy_group) =0; + virtual void computeKeff() = 0; /** - * @brief Returns an array of the scalar flux in each FSR and energy group. - * @return an array of FSR scalar fluxes + * @brief Add the source term contribution in the transport equation to + * the FSR scalar flux. */ - virtual FP_PRECISION* getFSRScalarFluxes() =0; + virtual void addSourceToScalarFlux() = 0; /** - * @brief Returns the source for a FSR and energy group. - * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest - * @return the FSR source + * @brief This method performs one transport swep. */ - virtual FP_PRECISION getFSRSource(int fsr_id, int energy_group) =0; - - virtual void setGeometry(Geometry* geometry); - virtual void setTrackGenerator(TrackGenerator* track_generator); - virtual void setPolarQuadratureType(quadratureType quadrature_type); - virtual void setNumPolarAngles(int num_polar); - virtual void setSourceConvergenceThreshold(FP_PRECISION source_thresh); - - void useExponentialInterpolation(); - void useExponentialIntrinsic(); - - virtual FP_PRECISION convergeSource(int max_iterations); - -/** - * @brief Computes the volume-weighted, energy integrated fission rate in - * each FSR and stores them in an array indexed by FSR ID. - * @details This is a helper method for SWIG to allow users to retrieve - * FSR fission rates as a NumPy array. An example of how this method - * can be called from Python is as follows: - * - * @code - * num_FSRs = geometry.getNumFSRs() - * fission_rates = solver.computeFSRFissionRates(num_FSRs) - * @endcode - * - * @param fission_rates an array to store the fission rates (implicitly passed - * in as a NumPy array from Python) - * @param num_FSRs the number of FSRs passed in from Python - */ - virtual void computeFSRFissionRates(double* fission_rates, int num_FSRs) =0; + virtual void transportSweep() = 0; + + void computeFlux(int max_iters=1000, solverMode mode=FORWARD, + bool only_fixed_source=true); + void computeSource(int max_iters=1000, solverMode mode=FORWARD, + double k_eff=1.0, residualType res_type=TOTAL_SOURCE); + void computeEigenvalue(int max_iters=1000, solverMode mode=FORWARD, + residualType res_type=FISSION_SOURCE); + + /** + * @brief Computes the volume-weighted, energy integrated fission rate in + * each FSR and stores them in an array indexed by FSR ID. + * @details This is a helper method for SWIG to allow users to retrieve + * FSR fission rates as a NumPy array. An example of how this method + * can be called from Python is as follows: + * + * @code + * num_FSRs = geometry.getNumFSRs() + * fission_rates = solver.computeFSRFissionRates(num_FSRs) + * @endcode + * + * @param fission_rates an array to store the fission rates (implicitly passed + * in as a NumPy array from Python) + * @param num_FSRs the number of FSRs passed in from Python + */ + virtual void computeFSRFissionRates(double* fission_rates, int num_FSRs) = 0; void printTimerReport(); }; -/** - * @brief Rounds a single precision floating point value to an integer. - * @param x a float precision floating point value - * @brief the rounded integer value - */ -inline int Solver::round_to_int(float x) { - return lrintf(x); -} - - -/** - * @brief Rounds a double precision floating point value to an integer. - * @param x a double precision floating point value - * @brief the rounded integer value - */ -inline int Solver::round_to_int(double x) { - return lrint(x); -} - - #endif /* SOLVER_H_ */ diff --git a/src/Surface.cpp b/src/Surface.cpp index e9e45820a..db688460f 100644 --- a/src/Surface.cpp +++ b/src/Surface.cpp @@ -2,7 +2,7 @@ int Surface::_n = 0; -static int auto_id = 10000; +static int auto_id = DEFAULT_INIT_ID; /** * @brief Returns an auto-generated unique surface ID. @@ -13,7 +13,7 @@ static int auto_id = 10000; * first ID begins at 10000. Hence, user-defined surface IDs greater * than or equal to 10000 are prohibited. */ -int surf_id() { +int surface_id() { int id = auto_id; auto_id++; return id; @@ -23,8 +23,23 @@ int surf_id() { /** * @brief Resets the auto-generated unique Surface ID counter to 10000. */ -void reset_surf_id() { - auto_id = 10000; +void reset_surface_id() { + auto_id = DEFAULT_INIT_ID; +} + + +/** + * @brief Maximize the auto-generated unique Surface ID counter. + * @details This method updates the auto-generated unique Surface ID + * counter if the input parameter is greater than the present + * value. This is useful for the OpenCG compatibility module + * to ensure that the auto-generated Surface IDs do not + * collide with those created in OpenCG. + * @param surface_id the id assigned to the auto-generated counter + */ +void maximize_surface_id(int surface_id) { + if (surface_id > auto_id) + auto_id = surface_id; } @@ -35,11 +50,11 @@ void reset_surf_id() { * @param id an optional user-defined Surface ID * @param name an optional user-defined Surface name */ -Surface::Surface(const int id, const char* name){ +Surface::Surface(const int id, const char* name) { /* If the user did not define an optional ID, create one */ if (id == 0) - _id = surf_id(); + _id = surface_id(); /* Use the user-defined ID */ else @@ -52,6 +67,10 @@ Surface::Surface(const int id, const char* name){ setName(name); _boundary_type = BOUNDARY_NONE; + + /* Initialize empty vectors of neighbor Cells for each halfspace */ + _neighbors[-1] = new std::vector(); + _neighbors[+1] = new std::vector(); } @@ -61,6 +80,14 @@ Surface::Surface(const int id, const char* name){ Surface::~Surface() { if (_name != NULL) delete [] _name; + + if (!_neighbors.empty()) { + _neighbors[-1]->clear(); + _neighbors[+1]->clear(); + delete _neighbors[-1]; + delete _neighbors[+1]; + _neighbors.clear(); + } } @@ -92,7 +119,7 @@ char* Surface::getName() const { /** - * @brief Return the type of Surface (ie, XPLANE, CIRCLE, etc). + * @brief Return the type of Surface (ie, XPLANE, ZCYLINDER, etc). * @return the Surface type */ surfaceType Surface::getSurfaceType() { @@ -105,7 +132,7 @@ surfaceType Surface::getSurfaceType() { * VACUUM or BOUNDARY_NONE) * @return the type of boundary condition type for this Surface */ -boundaryType Surface::getBoundaryType(){ +boundaryType Surface::getBoundaryType() { return _boundary_type; } @@ -139,6 +166,43 @@ void Surface::setBoundaryType(boundaryType boundary_type) { } +/** + * @brief Adds a neighbor Cell to this Surface's collection of neighbors. + * @param halfspace the +/-1 halfspace for the neighboring Cell + * @param cell a pointer to the neighboring Cell + */ +void Surface::addNeighborCell(int halfspace, Cell* cell) { + + if (halfspace != -1 && halfspace != +1) + log_printf(ERROR, "Unable to add neighbor Cell %d to Surface %d since the " + "halfspace %d is not -1 or 1", cell->getId(), _id, halfspace); + + /* Get pointer to vector of neighbor Cells for this halfspace */ + std::vector* neighbors = _neighbors[halfspace]; + + /* Add the neighbor Cell if the collection does not already contain it*/ + if (std::find(neighbors->begin(), neighbors->end(), cell) == neighbors->end()) + neighbors->push_back(cell); + + /* Update Cells with the neighbor Cells on the opposite Surface halfspace */ + std::vector::iterator iter1; + std::vector::iterator iter2; + for (iter1 = _neighbors[-1]->begin(); + iter1 != _neighbors[-1]->end(); ++iter1) { + for (iter2 = _neighbors[1]->begin(); + iter2 != _neighbors[1]->end(); ++iter2) + (*iter1)->addNeighborCell(*iter2); + } + + for (iter1 = _neighbors[1]->begin(); + iter1 != _neighbors[1]->end(); ++iter1) { + for (iter2 = _neighbors[-1]->begin(); + iter2 != _neighbors[-1]->end(); ++iter2) + (*iter1)->addNeighborCell(*iter2); + } +} + + /** * @brief Return true or false if a Point is on or off of a Surface. * @param point pointer to the Point of interest @@ -147,7 +211,7 @@ void Surface::setBoundaryType(boundaryType boundary_type) { bool Surface::isPointOnSurface(Point* point) { /* Uses a threshold to determine whether the point is on the Surface */ - if (abs(evaluate(point)) < ON_SURFACE_THRESH) + if (fabs(evaluate(point)) < ON_SURFACE_THRESH) return true; else return false; @@ -164,6 +228,46 @@ bool Surface::isCoordOnSurface(LocalCoords* coord) { } +/** + * @brief Finds the minimum distance to a Surface. + * @details Finds the miniumum distance to a Surface from a LocalCoords + * with a trajectory defined by an angle to this Surface. If the + * trajectory will not intersect the Surface, returns INFINITY. + * @param coords a pointer to a localcoords object + * @return the minimum distance to the Surface + */ +double Surface::getMinDistance(LocalCoords* coords) { + + Point* point = coords->getPoint(); + double phi = coords->getPhi(); + + /* Point array for intersections with this Surface */ + Point intersections[2]; + + /* Find the intersection Point(s) */ + int num_inters = this->intersection(point, phi, intersections); + double distance = INFINITY; + + /* If there is one intersection Point */ + if (num_inters == 1) + distance = intersections[0].distanceToPoint(point); + + /* If there are two intersection Points */ + else if (num_inters == 2) { + double dist1 = intersections[0].distanceToPoint(point); + double dist2 = intersections[1].distanceToPoint(point); + + /* Determine which intersection Point is nearest */ + if (dist1 < dist2) + distance = dist1; + else + distance = dist2; + } + + return distance; +} + + /** * @brief Prints a string representation of all of the Surface's objects to * the console. @@ -175,20 +279,22 @@ void Surface::printString() { /** * @brief Constructor. - * @param A the first coefficient in \f$ A * x + B * y + C = 0 \f$ - * @param B the second coefficient in \f$ A * x + B * y + C = 0 \f$ - * @param C the third coefficient in \f$ A * x + B * y + C = 0 \f$ + * @param A the first coefficient in \f$ A * x + B * y + C * z + D = 0 \f$ + * @param B the second coefficient in \f$ A * x + B * y + C * z + D = 0 \f$ + * @param C the third coefficient in \f$ A * x + B * y + C * z + D = 0 \f$ + * @param D the fourth coefficient in \f$ A * x + B * y + C * z + D = 0 \f$ * @param id the optional Surface ID * @param name the optional name of the Surface */ Plane::Plane(const double A, const double B, - const double C, const int id, const char* name): + const double C, const double D, const int id, const char* name): Surface(id, name) { _surface_type = PLANE; _A = A; _B = B; _C = C; + _D = D; } @@ -197,7 +303,7 @@ Plane::Plane(const double A, const double B, * @param halfspace the halfspace of the Surface to consider * @return the minimum x value of -INFINITY */ -double Plane::getMinX(int halfspace){ +double Plane::getMinX(int halfspace) { return -std::numeric_limits::infinity(); } @@ -207,7 +313,7 @@ double Plane::getMinX(int halfspace){ * @param halfspace the halfspace of the Surface to consider * @return the maximum x value of INFINITY */ -double Plane::getMaxX(int halfspace){ +double Plane::getMaxX(int halfspace) { return std::numeric_limits::infinity(); } @@ -217,7 +323,7 @@ double Plane::getMaxX(int halfspace){ * @param halfspace the halfspace of the Surface to consider * @return the minimum y value of -INFINITY */ -double Plane::getMinY(int halfspace){ +double Plane::getMinY(int halfspace) { return -std::numeric_limits::infinity(); } @@ -227,7 +333,7 @@ double Plane::getMinY(int halfspace){ * @param halfspace the halfspace of the Surface to consider * @return the maximum y value of INFINITY */ -double Plane::getMaxY(int halfspace){ +double Plane::getMaxY(int halfspace) { return std::numeric_limits::infinity(); } @@ -237,7 +343,7 @@ double Plane::getMaxY(int halfspace){ * @param halfspace the halfspace of the Surface to consider * @return the minimum z value of -INFINITY */ -double Plane::getMinZ(int halfspace){ +double Plane::getMinZ(int halfspace) { return -std::numeric_limits::infinity(); } @@ -247,7 +353,7 @@ double Plane::getMinZ(int halfspace){ * @param halfspace the halfspace of the Surface to consider * @return the maximum z value of INFINITY */ -double Plane::getMaxZ(int halfspace){ +double Plane::getMaxZ(int halfspace) { return std::numeric_limits::infinity(); } @@ -262,7 +368,7 @@ double Plane::getA() { /** - * @brief Returns the B coefficient multiplying x in the surface equation + * @brief Returns the B coefficient multiplying y in the surface equation * @return the value for the B coefficient */ double Plane::getB() { @@ -271,7 +377,7 @@ double Plane::getB() { /** - * @brief Returns the C coefficient multiplying x in the surface equation + * @brief Returns the C coefficient multiplying z in the surface equation * @return the value for the C coefficient */ double Plane::getC() { @@ -279,6 +385,15 @@ double Plane::getC() { } +/** + * @brief Returns the D constant coefficient + * @return the value for the D coefficient + */ +double Plane::getD() { + return _D; +} + + /** * @brief Finds the intersection Point with this Plane from a given Point and * trajectory defined by an angle. @@ -291,53 +406,35 @@ inline int Plane::intersection(Point* point, double angle, Point* points) { double x0 = point->getX(); double y0 = point->getY(); + double z0 = point->getZ(); + double l; int num = 0; /* number of intersections */ - double xcurr, ycurr; /* coordinates of current intersection point */ - - /* The track is vertical */ - if ((fabs(angle - (M_PI / 2))) < 1.0e-10) { - - /* The plane is also vertical => no intersections */ - if (_B == 0) - return 0; - - /* The plane is not vertical */ - else { - xcurr = x0; - ycurr = (-_A * x0 - _C) / _B; - points->setCoords(xcurr, ycurr); - - /* Check that point is in same direction as angle */ - if (angle < M_PI && ycurr > y0) - num++; - else if (angle > M_PI && ycurr < y0) - num++; - return num; + double xcurr, ycurr, zcurr; /* coordinates of current intersection point */ + double mx = cos(angle); + double my = sin(angle); + + /* The track and plane are parallel */ + if ((fabs(mx) < 1.e-10 && fabs(_A) > 1.e-10) || + (fabs(my) < 1.e-10 && fabs(_B) > 1.e-10)) + return 0; + + /* The track is not parallel to the plane */ + else{ + + l = - (_A*x0 + _B*y0 + _C*z0 + _D) / + (_A * mx + _B * my); + xcurr = x0 + l * mx; + ycurr = y0 + l * my; + zcurr = z0; + + if (l > 0.0) { + points[num].setCoords(xcurr, ycurr, zcurr); + num++; } } - /* If the track isn't vertical */ - else { - double m = sin(angle) / cos(angle); - - /* The plane and track are parallel, no intersections */ - if (fabs(-_A/_B - m) < 1e-11 && _B != 0) - return 0; - - else { - xcurr = -(_B * (y0 - m * x0) + _C) / (_A + _B * m); - ycurr = y0 + m * (xcurr - x0); - points->setCoords(xcurr, ycurr); - - if (angle < M_PI && ycurr > y0) - num++; - else if (angle > M_PI && ycurr < y0) - num++; - - return num; - } - } + return num; } @@ -355,7 +452,8 @@ std::string Plane::toString() { string << "Surface ID = " << _id << ", name = " << _name << ", type = PLANE " - << ", A = " << _A << ", B = " << _B << ", C = " << _C; + << ", A = " << _A << ", B = " << _B << ", C = " << _C + << ", D = " << _D; return string.str(); } @@ -368,7 +466,7 @@ std::string Plane::toString() { * @param name the optional name of the XPlane */ XPlane::XPlane(const double x, const int id, const char* name): - Plane(1, 0, -x, id) { + Plane(1, 0, 0, -x, id, name) { _surface_type = XPLANE; _x = x; @@ -381,6 +479,7 @@ XPlane::XPlane(const double x, const int id, const char* name): */ void XPlane::setX(const double x) { _x = x; + _D = -x; } @@ -398,8 +497,8 @@ double XPlane::getX() { * @param halfspace the halfspace of the XPlane to consider * @return the minimum x value */ -double XPlane::getMinX(int halfspace){ - if(halfspace == +1) +double XPlane::getMinX(int halfspace) { + if (halfspace == +1) return _x; else return -std::numeric_limits::infinity(); @@ -411,8 +510,8 @@ double XPlane::getMinX(int halfspace){ * @param halfspace the halfspace of the XPlane to consider * @return the maximum x value */ -double XPlane::getMaxX(int halfspace){ - if(halfspace == -1) +double XPlane::getMaxX(int halfspace) { + if (halfspace == -1) return _x; else return std::numeric_limits::infinity(); @@ -422,7 +521,7 @@ double XPlane::getMaxX(int halfspace){ /** * @brief Converts this XPlane's attributes to a character array. * @details The character array returned conatins the type of Plane (ie, - * XPLANE) and the A, B, and C coefficients in the + * XPLANE) and the A, B, C, and D coefficients in the * quadratic Surface equation and the location of the Plane on * the x-axis. * @return a character array of this XPlane's attributes @@ -435,7 +534,8 @@ std::string XPlane::toString() { << ", name = " << _name << ", type = XPLANE " << ", A = " << _A << ", B = " << _B - << ", C = " << _C << ", x = " << _x; + << ", C = " << _C << ", D = " << _D + << ", x = " << _x; return string.str(); } @@ -448,7 +548,7 @@ std::string XPlane::toString() { * @param name the optional Surface name */ YPlane::YPlane(const double y, const int id, const char* name): - Plane(0, 1, -y, id) { + Plane(0, 1, 0, -y, id, name) { _surface_type = YPLANE; _y = y; @@ -461,6 +561,7 @@ YPlane::YPlane(const double y, const int id, const char* name): */ void YPlane::setY(const double y) { _y = y; + _D = -y; } @@ -478,8 +579,8 @@ double YPlane::getY() { * @param halfspace the halfspace of the YPlane to consider * @return the minimum y value */ -double YPlane::getMinY(int halfspace){ - if(halfspace == +1) +double YPlane::getMinY(int halfspace) { + if (halfspace == +1) return _y; else return -std::numeric_limits::infinity(); @@ -491,8 +592,8 @@ double YPlane::getMinY(int halfspace){ * @param halfspace the halfspace of the YPlane to consider * @return the maximum y value */ -double YPlane::getMaxY(int halfspace){ - if(halfspace == -1) +double YPlane::getMaxY(int halfspace) { + if (halfspace == -1) return _y; else return std::numeric_limits::infinity(); @@ -502,7 +603,7 @@ double YPlane::getMaxY(int halfspace){ /** * @brief Converts this yplane's attributes to a character array * @details The character array returned conatins the type of Plane (ie, - * YPLANE) and the A, B, and C coefficients in the quadratic + * YPLANE) and the A, B, C, and D coefficients in the quadratic * Surface equation and the location of the Plane on the y-axis. * @return a character array of this YPlane's attributes */ @@ -514,7 +615,8 @@ std::string YPlane::toString() { << ", name = " << _name << ", type = YPLANE " << ", A = " << _A << ", B = " << _B - << ", C = " << _C << ", y = " << _y; + << ", C = " << _C << ", D = " << _D + << ", y = " << _y; return string.str(); } @@ -527,7 +629,7 @@ std::string YPlane::toString() { * @param name the optional Surface name */ ZPlane::ZPlane(const double z, const int id, const char* name): - Plane(0, 0, -z, id, name) { + Plane(0, 0, 1, -z, id, name) { _surface_type = ZPLANE; _z = z; @@ -540,6 +642,7 @@ ZPlane::ZPlane(const double z, const int id, const char* name): */ void ZPlane::setZ(const double z) { _z = z; + _D = -z; } @@ -557,8 +660,8 @@ double ZPlane::getZ() { * @param halfspace the halfspace of the ZPlane to consider * @return the minimum z value */ -double ZPlane::getMinZ(int halfspace){ - if(halfspace == +1) +double ZPlane::getMinZ(int halfspace) { + if (halfspace == +1) return _z; else return -std::numeric_limits::infinity(); @@ -570,8 +673,8 @@ double ZPlane::getMinZ(int halfspace){ * @param halfspace the halfspace of the ZPlane to consider * @return the maximum z value */ -double ZPlane::getMaxZ(int halfspace){ - if(halfspace == -1) +double ZPlane::getMaxZ(int halfspace) { + if (halfspace == -1) return _z; else return std::numeric_limits::infinity(); @@ -581,7 +684,7 @@ double ZPlane::getMaxZ(int halfspace){ /** * @brief Converts this ZPlane's attributes to a character array. * @details The character array returned conatins the type of Plane (ie, - * ZPLANE) and the A, B, and C coefficients in the + * ZPLANE) and the A, B, C, and D coefficients in the * quadratic Surface equation and the location of the Plane along * the z-axis. * @return a character array of this ZPlane's attributes @@ -594,7 +697,8 @@ std::string ZPlane::toString() { << ", name = " << _name << ", type = ZPLANE " << ", A = " << _A << ", B = " << _B - << ", C = " << _C << ", z = " << _z; + << ", C = " << _C << ", D = " << _D + << ", z = " << _z; return string.str(); } @@ -602,17 +706,17 @@ std::string ZPlane::toString() { /** * @brief constructor. - * @param x the x-coordinte of the Circle center - * @param y the y-coordinate of the Circle center - * @param radius the radius of the Circle + * @param x the x-coordinte of the ZCylinder center + * @param y the y-coordinate of the ZCylinder center + * @param radius the radius of the ZCylinder * @param id the optional Surface ID * @param name the optional Surface name */ -Circle::Circle(const double x, const double y, - const double radius, const int id, const char* name): - Surface(id, name) { +ZCylinder::ZCylinder(const double x, const double y, + const double radius, const int id, const char* name): + Surface(id, name) { - _surface_type = CIRCLE; + _surface_type = ZCYLINDER; _A = 1.; _B = 1.; _C = -2.*x; @@ -625,29 +729,29 @@ Circle::Circle(const double x, const double y, /** - * @brief Return the x-coordinate of the Circle's center Point. - * @return the x-coordinate of the Circle center + * @brief Return the x-coordinate of the ZCylinder's center Point. + * @return the x-coordinate of the ZCylinder center */ -double Circle::getX0() { +double ZCylinder::getX0() { return _center.getX(); } /** - * @brief Return the y-coordinate of the Circle's center Point. - * @return the y-coordinate of the Circle center + * @brief Return the y-coordinate of the ZCylinder's center Point. + * @return the y-coordinate of the ZCylinder center */ -double Circle::getY0() { +double ZCylinder::getY0() { return _center.getY(); } /** - * @brief Returns the minimum x value for one of this Circle's halfspaces. - * @param halfspace the halfspace of the Circle to consider + * @brief Returns the minimum x value for one of this ZCylinder's halfspaces. + * @param halfspace the halfspace of the ZCylinder to consider * @return the minimum x value */ -double Circle::getMinX(int halfspace){ +double ZCylinder::getMinX(int halfspace) { if (halfspace == -1) return _center.getX() - _radius; else @@ -656,11 +760,11 @@ double Circle::getMinX(int halfspace){ /** - * @brief Returns the maximum x value for one of this Circle's halfspaces. - * @param halfspace the halfspace of the Circle to consider + * @brief Returns the maximum x value for one of this ZCylinder's halfspaces. + * @param halfspace the halfspace of the ZCylinder to consider * @return the maximum x value */ -double Circle::getMaxX(int halfspace){ +double ZCylinder::getMaxX(int halfspace) { if (halfspace == -1) return _center.getX() + _radius; else @@ -669,11 +773,11 @@ double Circle::getMaxX(int halfspace){ /** - * @brief Returns the minimum y value for one of this Circle's halfspaces. - * @param halfspace the halfspace of the Circle to consider + * @brief Returns the minimum y value for one of this ZCylinder's halfspaces. + * @param halfspace the halfspace of the ZCylinder to consider * @return the minimum y value */ -double Circle::getMinY(int halfspace){ +double ZCylinder::getMinY(int halfspace) { if (halfspace == -1) return _center.getY() - _radius; else @@ -682,11 +786,11 @@ double Circle::getMinY(int halfspace){ /** - * @brief Returns the maximum y value for one of this Circle's halfspaces. - * @param halfspace the halfspace of the Circle to consider + * @brief Returns the maximum y value for one of this ZCylinder's halfspaces. + * @param halfspace the halfspace of the ZCylinder to consider * @return the maximum y value */ -double Circle::getMaxY(int halfspace){ +double ZCylinder::getMaxY(int halfspace) { if (halfspace == -1) return _center.getY() + _radius; else @@ -696,52 +800,55 @@ double Circle::getMaxY(int halfspace){ /** * @brief Returns the minimum z value of -INFINITY. - * @param halfspace the halfspace of the Circle to consider + * @param halfspace the halfspace of the ZCylinder to consider * @return the minimum z value of -INFINITY */ -double Circle::getMinZ(int halfspace){ +double ZCylinder::getMinZ(int halfspace) { return -std::numeric_limits::infinity(); } /** * @brief Returns the maximum z value of INFINITY. - * @param halfspace the halfspace of the Circle to consider + * @param halfspace the halfspace of the ZCylinder to consider * @return the maximum z value of INFINITY */ -double Circle::getMaxZ(int halfspace){ +double ZCylinder::getMaxZ(int halfspace) { return std::numeric_limits::infinity(); } /** - * @brief Finds the intersection Point with this circle from a given Point and + * @brief Finds the intersection Point with this zcylinder from a given Point and * trajectory defined by an angle (0, 1, or 2 points). * @param point pointer to the Point of interest * @param angle the angle defining the trajectory in radians * @param points pointer to a an array of Points to store intersection Points + * @param polar the polar angle defining the trajectory in radians * @return the number of intersection Points (0 or 1) */ -int Circle::intersection(Point* point, double angle, Point* points) { +int ZCylinder::intersection(Point* point, double angle, Point* points) { double x0 = point->getX(); double y0 = point->getY(); - double xcurr, ycurr; + double z0 = point->getZ(); + double xcurr, ycurr, zcurr; int num = 0; /* Number of intersection Points */ double a, b, c, q, discr; - /* If the track is vertical */ - if ((fabs(angle - (M_PI / 2))) < 1.0e-10) { + /* If the track is vertical in y */ + if ((fabs(angle - M_PI_2)) < 1.0e-10) { /* Solve for where the line x = x0 and the Surface F(x,y) intersect * Find the y where F(x0, y) = 0 * Substitute x0 into F(x,y) and rearrange to put in - * the form of the quadratic formula: ay^2 + by + c = 0 */ - a = _B * _B; + * the form of the quadratic formula: ay^2 + by + c = 0 + * This is simplified for a z-cylinder with a vertical axis */ + a = 1.; b = _D; c = _A * x0 * x0 + _C * x0 + _E; - discr = b*b - 4*a*c; + discr = b*b - 4*c; /* There are no intersections */ if (discr < 0) @@ -750,32 +857,39 @@ int Circle::intersection(Point* point, double angle, Point* points) { /* There is one intersection (ie on the Surface) */ else if (discr == 0) { xcurr = x0; - ycurr = -b / (2*a); - points[num].setCoords(xcurr, ycurr); + ycurr = -b / 2; + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); + + /* Check that point is in same direction as angle */ if (angle < M_PI && ycurr > y0) num++; else if (angle > M_PI && ycurr < y0) num++; + return num; } /* There are two intersections */ else { xcurr = x0; - ycurr = (-b + sqrt(discr)) / (2 * a); - points[num].setCoords(xcurr, ycurr); + ycurr = (-b + sqrt(discr)) / 2; + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); if (angle < M_PI && ycurr > y0) num++; else if (angle > M_PI && ycurr < y0) num++; xcurr = x0; - ycurr = (-b - sqrt(discr)) / (2 * a); - points[num].setCoords(xcurr, ycurr); + ycurr = (-b - sqrt(discr)) / 2; + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); if (angle < M_PI && ycurr > y0) num++; else if (angle > M_PI && ycurr < y0) num++; + return num; } } @@ -788,51 +902,68 @@ int Circle::intersection(Point* point, double angle, Point* points) { * rearrange to put in the form of the quadratic formula: * ax^2 + bx + c = 0 */ - double m = sin(angle) / cos(angle); + double m = tan(angle); q = y0 - m * x0; - a = _A + _B * _B * m * m; - b = 2 * _B * m * q + _C + _D * m; - c = _B * q * q + _D * q + _E; + a = 1 + m * m; + b = 2 * m * q + _C + _D * m; + c = q * q + _D * q + _E; discr = b*b - 4*a*c; + /* Boolean value describing whether the track is traveling to the right */ + bool right = angle < M_PI / 2. || angle > 3. * M_PI / 2.; + /* There are no intersections */ if (discr < 0) return 0; /* There is one intersection (ie on the Surface) */ else if (discr == 0) { + + /* Determine the point of intersection */ xcurr = -b / (2*a); - ycurr = y0 + m * (points[0].getX() - x0); - points[num].setCoords(xcurr, ycurr); - if (angle < M_PI && ycurr > y0) + ycurr = y0 + m * (points[num].getX() - x0); + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); + + /* Increase the number of intersections if the intersection is in the + * direction of the track is heading */ + if (right && xcurr > x0) num++; - else if (angle > M_PI && ycurr < y0) + else if (!right && xcurr < x0) num++; + return num; } /* There are two intersections */ else { + + /* Determine the point of intersection */ xcurr = (-b + sqrt(discr)) / (2*a); ycurr = y0 + m * (xcurr - x0); - points[num].setCoords(xcurr, ycurr); - if (angle < M_PI && ycurr > y0) { + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); + + /* Increase the number of intersections if the intersection is in the + * direction of the track is heading */ + if (right && xcurr > x0) num++; - } - else if (angle > M_PI && ycurr < y0) { + else if (!right && xcurr < x0) num++; - } + /* Determine the point of intersection */ xcurr = (-b - sqrt(discr)) / (2*a); ycurr = y0 + m * (xcurr - x0); - points[num].setCoords(xcurr, ycurr); - if (angle < M_PI && ycurr > y0) { + zcurr = z0; + points[num].setCoords(xcurr, ycurr, zcurr); + + /* Increase the number of intersections if the intersection is in the + * direction of the track is heading */ + if (right && xcurr > x0) num++; - } - else if (angle > M_PI && ycurr < y0) { + else if (!right && xcurr < x0) num++; - } return num; } @@ -841,19 +972,19 @@ int Circle::intersection(Point* point, double angle, Point* points) { /** - * @brief Converts this Circle's attributes to a character array. + * @brief Converts this ZCylinder's attributes to a character array. * @details The character array returned conatins the type of Plane (ie, - * CIRCLE) and the A, B, C, D and E coefficients in the + * ZCYLINDER) and the A, B, C, D and E coefficients in the * quadratic Surface equation. - * @return a character array of this Circle's attributes + * @return a character array of this ZCylinder's attributes */ -std::string Circle::toString() { +std::string ZCylinder::toString() { std::stringstream string; string << "Surface ID = " << _id << ", name " << _name - << ", type = CIRCLE " + << ", type = ZCYLINDER " << ", A = " << _A << ", B = " << _B << ", C = " << _C << ", D = " << _D << ", E = " << _E << ", x0 = " << _center.getX() diff --git a/src/Surface.h b/src/Surface.h index 5fbc9b91e..8e1aaf70d 100644 --- a/src/Surface.h +++ b/src/Surface.h @@ -10,22 +10,27 @@ #define SURFACE_H_ #ifdef __cplusplus -#include +#ifdef SWIG +#include "Python.h" +#endif +#include "constants.h" #include "LocalCoords.h" #include "boundary_type.h" +#include +#include +#include +#include #endif -/** Error threshold for determining how close a point needs to be to a surface - * to be considered on it */ -#define ON_SURFACE_THRESH 1E-12 - /* Forward declarations to resolve circular dependencies */ class LocalCoords; +class Cell; -int surf_id(); -void reset_surf_id(); +int surface_id(); +void reset_surface_id(); +void maximize_surface_id(int surface_id); /** @@ -33,11 +38,11 @@ void reset_surf_id(); * @brief The types of surfaces supported by OpenMOC. */ enum surfaceType { - /** A general plane perpendicular to the 2D xy plane */ + /** A general plane */ PLANE, - /** A circle with axis parallel to the z-axis */ - CIRCLE, + /** A cylinder with axis parallel to the z-axis */ + ZCYLINDER, /** A plane perpendicular to the x-axis */ XPLANE, @@ -56,7 +61,7 @@ enum surfaceType { /** * @class Surface Surface.h "src/Surface.h" - * @brief Represents a general Surface in the 2D xy-plane + * @brief Represents a general Surface in 3D. * @details The Surface class and its subclasses are used to define the * geometry for an OpenMOC simulation using a constructive solid * geometry (CSG) formalism. Surfaces are used during ray tracing @@ -78,13 +83,16 @@ class Surface { /** A user-defined name for the Surface */ char* _name; - /** The type of Surface (ie, XPLANE, CIRCLE, etc) */ + /** The type of Surface (ie, XPLANE, ZCYLINDER, etc) */ surfaceType _surface_type; /** The type of boundary condition to be used for this Surface * (ie, VACUUM or REFLECTIVE) */ boundaryType _boundary_type; + /* Vector of neighboring Cells */ + std::map* > _neighbors; + public: Surface(const int id=0, const char* name=""); virtual ~Surface(); @@ -100,45 +108,46 @@ class Surface { * @param halfspace the halfspace of the Surface to consider * @return the minimum x value */ - virtual double getMinX(int halfspace) =0; + virtual double getMinX(int halfspace) = 0; /** * @brief Returns the maximum x value for one of this Surface's halfspaces. * @param halfspace the halfspace of the Surface to consider * @return the maximum x value */ - virtual double getMaxX(int halfspace) =0; + virtual double getMaxX(int halfspace) = 0; /** * @brief Returns the minimum y value for one of this Surface's halfspaces. * @param halfspace the halfspace of the Surface to consider * @return the minimum y value */ - virtual double getMinY(int halfspace) =0; + virtual double getMinY(int halfspace) = 0; /** * @brief Returns the maximum y value for one of this Surface's halfspaces. * @param halfspace the halfspace of the Surface to consider * @return the maximum y value */ - virtual double getMaxY(int halfspace) =0; + virtual double getMaxY(int halfspace) = 0; /** * @brief Returns the minimum z value for one of this Surface's halfspaces. * @param halfspace the halfspace of the Surface to consider * @return the minimum z value */ - virtual double getMinZ(int halfspace) =0; + virtual double getMinZ(int halfspace) = 0; /** * @brief Returns the maximum z value for one of this Surface's halfspaces. * @param halfspace the halfspace of the Surface to consider * @return the maximum z value */ - virtual double getMaxZ(int halfspace) =0; + virtual double getMaxZ(int halfspace) = 0; void setName(const char* name); void setBoundaryType(const boundaryType boundary_type); + void addNeighborCell(int halfspace, Cell* cell); /** * @brief Evaluate a Point using the Surface's potential equation. @@ -147,7 +156,7 @@ class Surface { * @param point a pointer to the Soint of interest * @return the value of Point in the Plane's potential equation. */ - virtual double evaluate(const Point* point) const =0; + virtual double evaluate(const Point* point) const = 0; /** * @brief Finds the intersection Point with this Surface from a given @@ -157,11 +166,11 @@ class Surface { * @param points pointer to a Point to store the intersection Point * @return the number of intersection Points (0 or 1) */ - virtual int intersection(Point* point, double angle, Point* points) =0; + virtual int intersection(Point* point, double angle, Point* points) = 0; bool isPointOnSurface(Point* point); bool isCoordOnSurface(LocalCoords* coord); - double getMinDistance(Point* point, double angle, Point* intersection); + double getMinDistance(LocalCoords* coords); /** * @brief Converts this Surface's attributes to a character array. @@ -169,7 +178,7 @@ class Surface { * PLANE) and the coefficients in the potential equation. * @return a character array of this Surface's attributes */ - virtual std::string toString() =0; + virtual std::string toString() = 0; void printString(); }; @@ -189,18 +198,21 @@ class Plane: public Surface { /** The coefficient for the linear term in y */ double _B; - /** The constant offset */ + /** The coefficient for the linear term in z */ double _C; + /** The constant offset */ + double _D; + /** The Plane is a friend of class Surface */ friend class Surface; - /** The Plane is a friend of class Circle */ - friend class Circle; + /** The Plane is a friend of class Zcylinder */ + friend class ZCylinder; public: - Plane(const double A, const double B, const double C, + Plane(const double A, const double B, const double C, const double D, const int id=0, const char* name=""); double getMinX(int halfspace); @@ -212,6 +224,7 @@ class Plane: public Surface { double getA(); double getB(); double getC(); + double getD(); double evaluate(const Point* point) const; int intersection(Point* point, double angle, Point* points); @@ -293,17 +306,17 @@ class ZPlane: public Plane { /** - * @class Circle Surface.h "src/Surface.h" - * @brief Represents a Circle in the xy-plane. + * @class ZCylinder Surface.h "src/Surface.h" + * @brief Represents a Cylinder with axis parallel to the z-axis. */ -class Circle: public Surface { +class ZCylinder: public Surface { private: - /** A 2D point for the Circle's center */ + /** A point for the ZCylinder's center */ Point _center; - /** The Circle's radius */ + /** The ZCylinder's radius */ double _radius; /** The coefficient of the x-squared term */ @@ -321,15 +334,15 @@ class Circle: public Surface { /** The constant offset */ double _E; - /** The Circle is a friend of the Surface class */ + /** The ZCylinder is a friend of the Surface class */ friend class Surface; - /** The Circle is a friend of the Plane class */ + /** The ZCylinder is a friend of the Plane class */ friend class Plane; public: - Circle(const double x, const double y, const double radius, - const int id=0, const char* name=""); + ZCylinder(const double x, const double y, const double radius, + const int id=0, const char* name=""); double getX0(); double getY0(); @@ -348,55 +361,6 @@ class Circle: public Surface { }; -/** - * @brief Finds the minimum distance to a Surface. - * @details Finds the miniumum distance to a Surface from a Point with a - * given trajectory defined by an angle to this Surface. If the - * trajectory will not intersect the Surface, returns INFINITY. - * @param point a pointer to the Point of interest - * @param angle the angle defining the trajectory in radians - * @param intersection a pointer to a Point for storing the intersection - * @return the minimum distance to the Surface - */ -inline double Surface::getMinDistance(Point* point, double angle, - Point* intersection) { - - /* Point array for intersections with this Surface */ - Point intersections[2]; - - /* Find the intersection Point(s) */ - int num_inters = this->intersection(point, angle, intersections); - double distance = INFINITY; - - /* If there is one intersection Point */ - if (num_inters == 1) { - distance = intersections[0].distanceToPoint(point); - intersection->setX(intersections[0].getX()); - intersection->setY(intersections[0].getY()); - } - - /* If there are two intersection Points */ - else if (num_inters == 2) { - double dist1 = intersections[0].distanceToPoint(point); - double dist2 = intersections[1].distanceToPoint(point); - - /* Determine which intersection Point is nearest */ - if (dist1 < dist2) { - distance = dist1; - intersection->setX(intersections[0].getX()); - intersection->setY(intersections[0].getY()); - } - else { - distance = dist2; - intersection->setX(intersections[1].getX()); - intersection->setY(intersections[1].getY()); - } - } - - return distance; -} - - /** * @brief Evaluate a Point using the Plane's quadratic Surface equation. * @param point a pointer to the Point of interest @@ -405,27 +369,27 @@ inline double Surface::getMinDistance(Point* point, double angle, inline double Plane::evaluate(const Point* point) const { double x = point->getX(); double y = point->getY(); + double z = point->getZ(); - //TODO: does not support ZPlanes - return (_A * x + _B * y + _C); + return (_A * x + _B * y + _C * z + _D); } /** - * @brief Return the radius of the Circle. - * @return the radius of the Circle + * @brief Return the radius of the ZCylinder. + * @return the radius of the ZCylinder */ -inline double Circle::getRadius() { +inline double ZCylinder::getRadius() { return this->_radius; } /** - * @brief Evaluate a Point using the Circle's quadratic Surface equation. + * @brief Evaluate a Point using the ZCylinder's quadratic Surface equation. * @param point a pointer to the Point of interest * @return the value of Point in the equation */ -inline double Circle::evaluate(const Point* point) const { +inline double ZCylinder::evaluate(const Point* point) const { double x = point->getX(); double y = point->getY(); return (_A * x * x + _B * y * y + _C * x + _D * y + _E); diff --git a/src/Timer.h b/src/Timer.h index ba4851a77..3d11fc467 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -9,6 +9,10 @@ #define TIMER_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "log.h" #include #include #include @@ -18,7 +22,6 @@ #include #include #include -#include "log.h" #endif diff --git a/src/Track.cpp b/src/Track.cpp index 54e73a9ce..c906a4659 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -4,7 +4,16 @@ /* * @brief Constructor initializes an empty Track. */ -Track::Track() { } +Track::Track() { + + /* Initialize the periodic track index to -1, indicating it has not + * been set */ + _periodic_track_index = -1; + + /* Initialize the reflective track index to -1, indicating it has not + * been set */ + _reflective_track_index = -1; +} @@ -20,15 +29,18 @@ Track::~Track() { * @brief Set the values for the Track's start and end point and angle. * @param start_x the x-coordinate at the starting point * @param start_y the y-coordinate at the starting point + * @param start_z the z-coordinate at the starting point * @param end_x the x-coordinate at the ending point * @param end_y the y-coordinate at the ending point + * @param end_z the z-coordinate at the ending point * @param phi the track's azimuthal angle (\f$ \theta \in [0, \pi] \f$) */ void Track::setValues(const double start_x, const double start_y, - const double end_x, const double end_y, + const double start_z, const double end_x, + const double end_y, const double end_z, const double phi) { - _start.setCoords(start_x, start_y); - _end.setCoords(end_x, end_y); + _start.setCoords(start_x, start_y, start_z); + _end.setCoords(end_x, end_y, end_z); _phi = phi; } @@ -64,65 +76,115 @@ void Track::setAzimAngleIndex(const int index) { } +/** + * @brief Set the index of a track in a periodic cycle. + * @details Tracks form periodic track cycles as they traverse the geometry. + * Tracks can be arbitrarily decomposed into periodic track cycles + * and this index indicates the index in a particular cycle. + * @param index of the track in a periodic cycle + */ +void Track::setPeriodicTrackIndex(const int index) { + _periodic_track_index = index; +} + + +/** + * @brief Set the index of a track in a reflective cycle. + * @details Tracks form reflective track cycles as they traverse the geometry. + * Tracks can be arbitrarily decomposed into reflective track cycles + * and this index indicates the index in a particular cycle. + * @param index of the track in a reflective cycle + */ +void Track::setReflectiveTrackIndex(const int index) { + _reflective_track_index = index; +} + + /** * @brief Adds a segment pointer to this Track's list of segments. * @details This method assumes that segments are added in order of their * starting location from the Track's start point. - * @param segment a pointer to the segment + * @param to_add a pointer to the segment to add */ -void Track::addSegment(segment* segment) { +void Track::addSegment(segment* to_add) { + try { + _segments.push_back(*to_add); + } + catch (std::exception &e) { + log_printf(ERROR, "Unable to add a segment to Track"); + } +} + + +/** + * @brief Removes a segment from this Track's list of segments. + * @param index the index of the segment to remove + */ +void Track::removeSegment(int index) { + try { + _segments.erase(_segments.begin()+index); + } + catch (std::exception &e) { + log_printf(ERROR, "Unable to remove a segment from Track"); + } +} + +/** + * @brief Inserts a segment pointer into this Track's list of segments. + * @details This method appends the new segment directly behind another + * segment in the Track. This is a helper method for the + * TrackGenerator::splitTracks(...) routine. + * @param index the index of the segment to insert behind in the list + * @param segment a pointer to the segment to insert + */ +void Track::insertSegment(int index, segment* segment) { try { - _segments.push_back(*segment); + _segments.insert(_segments.begin()+index, *segment); } catch (std::exception &e) { - log_printf(ERROR, "Unable to add a segment to Track. Backtrace:" - "\n%s", e.what()); + log_printf(ERROR, "Unable to insert a segment into Track"); } } /** * @brief Sets the direction in which the flux leaving this Track along its - * "forward" direction is passed to reflective Track for boundary - * conditions. + * "forward" direction is passed. * @details Sets whether or not to pass the outgoing flux from this Track * along its "forward" direction to the "forward" direction (false) - * or "reverse" direction (true) of the Track reflecting out of this - * one at the boundary. This is used for reflective boundary - * conditions. - * @param refl_in the "forward" (false) or "reverse (true) direction + * or "reverse" direction (true) of the next Track after intersection + * with the geometry boundary. + * @param next_in the "forward" (false) or "reverse (true) direction */ -void Track::setReflIn(const bool refl_in) { - _refl_in = refl_in; +void Track::setNextIn(const bool next_in) { + _next_in = next_in; } /** - * @brief Sets the direction in which the flux leaving this Track along - * its "reverse" direction is passed to reflective track for boundary - * conditions. + * @brief Sets the direction in which the flux leaving this Track along its + * "reverse" direction is passed. * @details Sets whether or not to pass the outgoing flux from this Track * along its "reverse" direction to the "forward" direction (false) - * or "reverse" direction (true) of the Track reflecting out of this - * one at the boundary. This is used for reflective boundary - * conditions. - * @param refl_out "forward" (false) or "reverse (true) direction + * or "reverse" direction (true) of the next Track after intersection + * with the geometry boundary. + * @param next_out the "forward" (false) or "reverse (true) direction */ -void Track::setReflOut(const bool refl_out) { - _refl_out = refl_out; +void Track::setNextOut(const bool next_out) { + _next_out = next_out; } /** * @brief Sets the boundary condition for the incoming flux along the Track's * "forward" direction. - * @details The boolean represents vacuum (false) or reflective (true) - * boundary conditions. + * @details The boundaryType represents vacuum (0), reflective (1), or + * periodic (2) boundary conditions. * @param bc_in boundary condition for the incoming flux in the "forward" * direction */ -void Track::setBCIn(const bool bc_in) { +void Track::setBCIn(const boundaryType bc_in) { _bc_in = bc_in; } @@ -130,19 +192,19 @@ void Track::setBCIn(const bool bc_in) { /** * @brief Sets the boundary condition for the incoming flux along the Track's * "reverse" direction. - * @details The boolean represents vacuum (false) or reflective (true) - * boundary conditions. + * @details The boundaryType represents vacuum (0), reflective (1), or + * periodic (2) boundary conditions. * @param bc_out boundary condition for the incoming flux in the "reverse" * direction */ -void Track::setBCOut(const bool bc_out) { +void Track::setBCOut(const boundaryType bc_out) { _bc_out = bc_out; } /** - * @brief Sets the track reflecting into this Track's "forward" direction. - * @param track_in pointer to the Track reflecting into the "forward" direction + * @brief Sets the track going out along this Track's "forward" direction. + * @param track_in pointer to the Track going out in the "forward" direction */ void Track::setTrackIn(Track* track_in) { _track_in = track_in; @@ -150,8 +212,8 @@ void Track::setTrackIn(Track* track_in) { /** - * @brief Sets the track reflecting into this Track's "reverse" direction. - * @param track_out pointer to the Track reflecting into the "reverse" direction + * @brief Sets the track going out along this Track's "reverse" direction. + * @param track_out pointer to the Track going out in the "reverse" direction */ void Track::setTrackOut(Track* track_out) { _track_out = track_out; @@ -159,84 +221,80 @@ void Track::setTrackOut(Track* track_out) { /** - * @brief Sets the first index of the track reflecting into this Track's - * "forward" direction in the 2D jagged array of tracks. - * @param i the first index of the incoming track along the "forward" direction + * @brief Returns whether to give the outgoing flux to the "forward" (false) or + * "reverse" (true) direction of the next Track when traveling along + * this Tracks's "forward" direction. + * @return "forward" (false) "reverse" (true) direction of outgoing Track */ -void Track::setTrackInI(int i) { - _track_in_i = i; +bool Track::isNextIn() const { + return _next_in; } /** - * @brief Sets the second index of the track reflecting into this Track's - * "forward" direction in the 2D jagged array of tracks. - * @param j the second index of the incoming track along the "forward" direction + * @brief Returns whether to give the outgoing flux to the "forward" (false) or + * "reverse" (true) direction of the next Track when traveling along + * this Track's "reverse" direction. + * @return "forward" (false) "reverse" (true) direction of outgoing Track */ -void Track::setTrackInJ(int j) { - _track_in_j = j; +bool Track::isNextOut() const { + return _next_out; } /** - * @brief Sets the first index of the track reflecting into this Track's - * "reverse" direction in the 2D jagged array of Tracks. - * @param i the first index of the incoming Track along the "reverse" direction + * @brief Returns the boundary condition for the flux along the Track's + * "forward" direction. + * @return vacuum (0), reflective (1), or periodic (2) reflective + * boundary conditions */ -void Track::setTrackOutI(int i) { - _track_out_i = i; +boundaryType Track::getBCIn() const { + return _bc_in; } /** - * @brief Sets the second index of the Track reflecting into this Track's - * "reverse" direction in the 2D jagged array of tracks. - * @param j the second index of the incoming Track along the "reverse" direction + * @brief Returns the boundary condition for the flux along the Track's + * "reverse" direction. + * @return vacuum (0), reflective (1), or periodic (2) reflective + * boundary conditions */ -void Track::setTrackOutJ(int j) { - _track_out_j = j; +boundaryType Track::getBCOut() const { + return _bc_out; } /** - * @brief Returns whether to give the outgoing flux to the "forward" (false) or - * "reverse" (true) direction of the Track reflecting out of this one - * along its "forward" direction. - * @return "forward" (false) "reverse" (true) direction of outgoing Track + * @brief Returns a boolean to indicate whether the outgoing flux along this + * Track's "forward" direction should be transferred to the outgoing + * Track. + * @details The bool with be false for vacuum BCs and true for all other BCs. + * @return bool indicating whether the flux should be passed when tracking in + * the "forward" direction. */ -bool Track::isReflIn() const { - return _refl_in; -} - +bool Track::getTransferFluxIn() const { -/** - * @brief Returns whether to give the outgoing flux to the "forward" (false) or - * "reverse" (true) direction of the Track reflecting out of this one - * along its "reverse" direction. - * @return "forward" (false) "reverse" (true) direction of outgoing Track - */ -bool Track::isReflOut() const { - return _refl_out; + if (_bc_in == VACUUM) + return false; + else + return true; } /** - * @brief Returns the boundary condition for the flux along the Track's - * "forward" direction. - * @return vacuum (false) or reflective (true) reflective boundary conditions + * @brief Returns a boolean to indicate whether the outgoing flux along this + * Track's "reverse" direction should be transferred to the incoming + * Track. + * @details The bool with be false for vacuum BCs and true for all other BCs. + * @return bool indicating whether the flux should be passed when tracking in + * the "reverse" direction. */ -bool Track::getBCIn() const { - return _bc_in; -} - +bool Track::getTransferFluxOut() const { -/** - * @brief Returns the boundary condition for the flux along the Track's - * "reverse" direction. - * @return vacuum (false) or reflective (true) reflective boundary conditions - */ -bool Track::getBCOut() const { - return _bc_out; + if (_bc_out == VACUUM) + return false; + else + return true; } @@ -278,93 +336,20 @@ int Track::getAzimAngleIndex() const { /** - * @brief Returns the first index of the Track reflecting out of this one along - * its "forward" direction in the 2D jagged array of all Tracks. - * @return the first index of the reflecting Track + * @brief Get the index of a track in a periodic cycle. + * @return index of the track in a periodic cycle */ -int Track::getTrackInI() const { - return _track_in_i; +int Track::getPeriodicTrackIndex() const { + return _periodic_track_index; } /** - * @brief Returns the second index of the Track reflecting out of this one along - * its "forward" direction in the 2D jagged array of all Tracks. - * @return the second index of the reflecting Track + * @brief Get the index of a track in a reflective cycle. + * @return index of the track in a reflective cycle */ -int Track::getTrackInJ() const { - return _track_in_j; -} - - - -/** - * @brief Returns the first index of the Track reflecting out of this one along - * its "reverse" direction in the 2D jagged array of all Tracks. - * @return the first index of the reflecting Track - */ -int Track::getTrackOutI() const { - return _track_out_i; -} - - -/** - * @brief Returns the second index of the Track reflecting out of this one along - * its "reverse" direction in the 2D jagged array of all Tracks. - * @return the second index of the reflecting Track - */ -int Track::getTrackOutJ() const { - return _track_out_j; -} - - -/** - * @brief Checks whether a Point is contained along this Track. - * @param point a pointer to the Point of interest - * @return true if the Point is on the Track, false otherwise - */ -bool Track::contains(Point* point) { - - /* The slope of the Track */ - double m; - - /* The distance from the Point to the Track */ - double dist; - - /* If the Point is outside of the bounds of the start and end Points of the - * Track it does not lie on the Track */ - if (!(((point->getX() <= _start.getX()+1.0E-2 && - point->getX() >= _end.getX()-1.0E-2) - || (point->getX() >= _start.getX()-1.0E-2 && - point->getX() <= _end.getX()+1.0E-2)) && - ((point->getY() <= _start.getY()+1.0E-2 && - point->getY() >= _end.getY()-1.0E-2) - || (point->getY() >= _start.getY()-1.0E-2 && - point->getY() <= _end.getY()+1.0E-2)))) { - - return false; - } - - - /* If the Track is vertical */ - if (fabs(_phi - M_PI / 2) < 1E-10) { - if (fabs(point->getX() - _start.getX()) < 1E-10) - return true; - else - return false; - } - - /* If the track is not vertical */ - else { - m = sin(_phi) / cos(_phi); - dist = point->getY() - (_start.getY() + m * (point->getX()-_start.getX())); - - /* Use point-slope formula */ - if (fabs(dist) < 1e-10) - return true; - else - return false; - } +int Track::getReflectiveTrackIndex() const { + return _reflective_track_index; } @@ -385,7 +370,9 @@ void Track::clearSegments() { std::string Track::toString() { std::stringstream string; string << "Track: start, x = " << _start.getX() << ", y = " << - _start.getY() << " end, x = " << _end.getX() << ", y = " - << _end.getY() << ", phi = " << _phi; + _start.getY() << ", z = " << _start.getZ() << ", end, x = " << + _end.getX() << ", y = " << _end.getY() << ", z = " << _end.getZ() << + ", phi = " << _phi; + return string.str(); } diff --git a/src/Track.h b/src/Track.h index cb1cfa9da..cc22ba86c 100644 --- a/src/Track.h +++ b/src/Track.h @@ -9,9 +9,14 @@ #define TRACK_H_ #ifdef __cplusplus -#include +#ifdef SWIG +#include "Python.h" +#endif #include "Point.h" #include "Material.h" +#include "boundary_type.h" +#include +#include #endif /** @@ -35,6 +40,12 @@ struct segment { /** The ID for the mesh surface crossed by the Track start point */ int _cmfd_surface_bwd; + + /** Constructor initializes CMFD surfaces */ + segment() { + _cmfd_surface_fwd = -1; + _cmfd_surface_bwd = -1; + } }; @@ -62,97 +73,79 @@ class Track { /** The azimuthal angle index into the global 2D ragged array of Tracks */ int _azim_angle_index; + /** The track index in the periodic cycle */ + int _periodic_track_index; + + /** The track index in the reflective cycle */ + int _reflective_track_index; + /** A dynamically sized vector of segments making up this Track */ std::vector _segments; - /** The Track which reflects out of this Track along its "forward" - * direction for reflective boundary conditions. */ + /** The next Track when traveling along this Track in the "forward" + * direction. */ Track* _track_in; - /** The Track which reflects out of this Track along its "reverse" - * direction for reflective boundary conditions. */ + /** The next Track when traveling along this Track in the "reverse" + * direction. */ Track* _track_out; - /** The first index into the global 2D ragged array of Tracks for the Track - * that reflects out of this Track along its "forward" direction for - * reflective boundary conditions. */ - int _track_in_i; - - /** The second index into the global 2D ragged array of Tracks for the Track - * that reflects out of this Track along its "forward" direction for - * reflective boundary conditions. */ - int _track_in_j; - - /** The first index into the global 2D ragged array of Tracks for the Track - * that reflects out of this Track along its "reverse" direction for - * reflective boundary conditions. */ - int _track_out_i; - - /** The second index into the global 2D ragged array of Tracks for the Track - * that reflects out of this Track along its "reverse" direction for - * reflective boundary conditions */ - int _track_out_j; - /** A boolean to indicate whether to give the flux to the "forward" (false) - * or "reverse" (true) direction of the Track reflecting out of this one - * along its "forward" direction for reflective boundary conditions.*/ - bool _refl_in; + * or "reverse" (true) direction of the next Track going in the "forward" + * direction. */ + bool _next_in; /** A boolean to indicate whether to give the flux to the "forward" (false) - * or "reverse" (true) direction of the Track reflecting out of this one - * along its "forward" direction for reflective boundary conditions. */ - bool _refl_out; + * or "reverse" (true) direction of the next Track going in the "reverse" + * direction. */ + bool _next_out; - /** A boolean to indicate whether the outgoing angular flux along this - * Track's "forward" direction should be zeroed out for vacuum boundary - * conditions. */ - bool _bc_in; + /** An enum to indicate the boundary condition in the "forward" direction. */ + boundaryType _bc_in; - /** A boolean to indicate whether the outgoing angular flux along this - * Track's "reverse" direction should be zeroed out for vacuum boundary - * conditions. */ - bool _bc_out; + /** An enum to indicate the boundary condition in the "reverse" direction. */ + boundaryType _bc_out; public: Track(); virtual ~Track(); void setValues(const double start_x, const double start_y, - const double end_x, const double end_y, const double phi); + const double start_z, const double end_x, + const double end_y, const double end_z, const double phi); void setUid(int uid); void setPhi(const double phi); void setAzimAngleIndex(const int index); - void setReflIn(const bool refl_in); - void setReflOut(const bool refl_out); - void setBCIn(const bool bc_in); - void setBCOut(const bool bc_out); + void setPeriodicTrackIndex(const int index); + void setReflectiveTrackIndex(const int index); + void setNextIn(const bool next_in); + void setNextOut(const bool next_out); + void setBCIn(const boundaryType bc_in); + void setBCOut(const boundaryType bc_out); void setTrackIn(Track *track_in); void setTrackOut(Track *track_out); - void setTrackInI(int i); - void setTrackInJ(int j); - void setTrackOutI(int i); - void setTrackOutJ(int j); int getUid(); Point* getEnd(); Point* getStart(); double getPhi() const; int getAzimAngleIndex() const; + int getPeriodicTrackIndex() const; + int getReflectiveTrackIndex() const; segment* getSegment(int s); segment* getSegments(); int getNumSegments(); Track *getTrackIn() const; Track *getTrackOut() const; - int getTrackInI() const; - int getTrackInJ() const; - int getTrackOutI() const; - int getTrackOutJ() const; - bool isReflIn() const; - bool isReflOut() const; - bool getBCIn() const; - bool getBCOut() const; - - bool contains(Point* point); - void addSegment(segment* segment); + bool isNextIn() const; + bool isNextOut() const; + boundaryType getBCIn() const; + boundaryType getBCOut() const; + bool getTransferFluxIn() const; + bool getTransferFluxOut() const; + + void addSegment(segment* to_add); + void removeSegment(int index); + void insertSegment(int index, segment* segment); void clearSegments(); std::string toString(); }; @@ -196,7 +189,7 @@ inline segment* Track::getSegment(int segment) { /* If Track doesn't contain this segment, exits program */ if (segment >= (int)_segments.size()) - log_printf(ERROR, "Attempted to retrieve segment s = %d but Track only" + log_printf(ERROR, "Attempted to retrieve segment s = %d but Track only " "has %d segments", segment, _segments.size()); return &_segments[segment]; diff --git a/src/TrackGenerator.cpp b/src/TrackGenerator.cpp index 721ccc179..95aac0920 100644 --- a/src/TrackGenerator.cpp +++ b/src/TrackGenerator.cpp @@ -1,6 +1,5 @@ #include "TrackGenerator.h" - /** * @brief Constructor for the TrackGenerator assigns default values. * @param geometry a pointer to a Geometry object @@ -15,13 +14,12 @@ TrackGenerator::TrackGenerator(Geometry* geometry, const int num_azim, _geometry = geometry; setNumAzim(num_azim); setTrackSpacing(spacing); - _tot_num_tracks = 0; - _tot_num_segments = 0; - _num_segments = NULL; _contains_tracks = false; _use_input_file = false; _tracks_filename = ""; - _max_optical_length = 10; + _z_coord = 0.0; + _phi = NULL; + _FSR_locks = NULL; } @@ -33,43 +31,21 @@ TrackGenerator::~TrackGenerator() { /* Deletes Tracks arrays if Tracks have been generated */ if (_contains_tracks) { delete [] _num_tracks; - delete [] _num_segments; delete [] _num_x; delete [] _num_y; delete [] _azim_weights; + delete [] _num_tracks_by_parallel_group; + delete [] _phi; for (int i = 0; i < _num_azim; i++) delete [] _tracks[i]; delete [] _tracks; + delete [] _tracks_by_parallel_group; } -} - - -/** - * @brief Sets the number of shared memory OpenMP threads to use (>0). - * @param num_threads the number of threads - */ -void TrackGenerator::setNumThreads(int num_threads) { - - if (num_threads <= 0) - log_printf(ERROR, "Unable to set the number of threads for the " - "TrackGenerator to %d since it is less than or equal to 0" - , num_threads); - - _num_threads = num_threads; - - /* Set the number of threads for OpenMP */ - omp_set_num_threads(_num_threads); -} - -/** - * @brief Returns the number of shared memory OpenMP threads in use. - * @return the number of threads - */ -int TrackGenerator::getNumThreads() { - return _num_threads; + if (_FSR_locks != NULL) + delete [] _FSR_locks; } @@ -78,7 +54,7 @@ int TrackGenerator::getNumThreads() { * @return the number of azimuthal angles in \f$ 2\pi \f$ */ int TrackGenerator::getNumAzim() { - return _num_azim * 2.0; + return _num_azim * 2; } @@ -108,55 +84,119 @@ Geometry* TrackGenerator::getGeometry() { /** - * @brief Return the total number of Tracks across the Geometry. - * @return the total number of Tracks + * @brief Return the array of FSR locks for atomic FSR operations. + * @return an array of FSR locks */ -int TrackGenerator::getNumTracks() { +omp_lock_t* TrackGenerator::getFSRLocks() { + if (_FSR_locks == NULL) + log_printf(ERROR, "Unable to return the TrackGenerator's FSR locks " + "since they have not yet been created"); + + return _FSR_locks; +} + +/** + * @brief Return the total number of Tracks generated. + * @return The number of Tracks generated + */ +int TrackGenerator::getNumTracks() { if (!_contains_tracks) log_printf(ERROR, "Unable to return the total number of Tracks since " "Tracks have not yet been generated."); - return _tot_num_tracks; + int num_tracks = 0; + + for (int i=0; i < _num_azim; i++) { + num_tracks += _num_tracks[i]; + } + + return num_tracks; } + /** - * @brief Return an array of the number of Tracks for each azimuthal angle. - * @return array with the number of Tracks + * @brief Return the number of parallel track groups. + * @return The number of parallel track groups */ -int* TrackGenerator::getNumTracksArray() { +int TrackGenerator::getNumParallelTrackGroups() { + if (!_contains_tracks) - log_printf(ERROR, "Unable to return the array of the number of Tracks per " - "azimuthal angle since Tracks have not yet been generated."); + log_printf(ERROR, "Unable to return the number of parallel track groups " + "since Tracks have not yet been generated."); - return _num_tracks; + return _num_parallel_track_groups; } /** - * @brief Return the total number of Track segments across the Geometry. - * @return the total number of Track segments + * @brief Return the number of tracks on the x-axis for a given azimuthal angle. + * @param azim An azimuthal angle index + * @return The number of Tracks on the x-axis */ -int TrackGenerator::getNumSegments() { +int TrackGenerator::getNumX(int azim) { + if (!_contains_tracks) + log_printf(ERROR, "Unable to return the number of Tracks on the x-axis" + " for azimuthal angle %d since Tracks have not yet been " + "generated.", azim); + + return _num_x[azim]; +} + +/** + * @brief Return the number of tracks on the y-axis for a given azimuthal angle. + * @param azim An azimuthal angle index + * @return The number of Tracks on the y-axis + */ +int TrackGenerator::getNumY(int azim) { if (!_contains_tracks) - log_printf(ERROR, "Unable to return the total number of segments since " - "Tracks have not yet been generated."); + log_printf(ERROR, "Unable to return the number of Tracks on the y-axis" + " for azimuthal angle %d since Tracks have not yet been " + "generated.", azim); + + return _num_y[azim]; +} + + +/** + * @brief Return the number of tracks in a given parallel track group. + * @return the number of tracks in a given parallel track group. + */ +int TrackGenerator::getNumTracksByParallelGroup(int group) { + + if (group < 0 || group >= _num_parallel_track_groups) + log_printf(ERROR, "Unable to return the number of tracks in parallel track" + " group %d which is not between 0 and the number of parallel " + "groups, %d", group, _num_parallel_track_groups); + + if (!_contains_tracks) + log_printf(ERROR, "Unable to return the number of tracks in the parallel " + "track group %d since Tracks have not yet been generated." + , group); - return _tot_num_segments; + return _num_tracks_by_parallel_group[group]; } /** - * @brief Return an array of the number of segments per Track. - * @return array with the number of segments per Track + * @brief Return the total number of Track segments across the Geometry. + * @return the total number of Track segments */ -int* TrackGenerator::getNumSegmentsArray() { +int TrackGenerator::getNumSegments() { if (!_contains_tracks) - log_printf(ERROR, "Unable to return the array of the number of segments " - "per Track since Tracks have not yet been generated."); + log_printf(ERROR, "Unable to return the total number of segments since " + "Tracks have not yet been generated."); - return _num_segments; + int num_segments = 0; + + for (int i=0; i < _num_azim; i++) { +#pragma omp parallel for reduction(+:num_segments) + for (int j=0; j < _num_tracks[i]; j++) + num_segments += _tracks[i][j].getNumSegments(); + } + + return num_segments; } @@ -175,6 +215,23 @@ Track **TrackGenerator::getTracks() { } +/** + * @brief Returns a 1D array of Track pointers. + * @details The tracks in the _tracks_by_parallel_group array are organized + * by parallel track group. The index into the array is also the + * corresponding Track's UID. + * @return The 1D array of Track pointers + */ +Track **TrackGenerator::getTracksByParallelGroup() { + if (!_contains_tracks) + log_printf(ERROR, "Unable to return the 1D array of the Track pointers " + "arranged by parallel group since Tracks have not yet been " + "generated."); + + return _tracks_by_parallel_group; +} + + /** * @brief Return a pointer to the array of azimuthal angle quadrature weights. * @return the array of azimuthal angle quadrature weights @@ -188,6 +245,224 @@ FP_PRECISION* TrackGenerator::getAzimWeights() { } +/** + * @brief Returns the number of shared memory OpenMP threads in use. + * @return the number of threads + */ +int TrackGenerator::getNumThreads() { + return _num_threads; +} + + +/** + * @brief Returns the z-coord where the 2D Tracks should be created. + * @return the z-coord where the 2D Tracks should be created. + */ +double TrackGenerator::getZCoord() { + return _z_coord; +} + + +/** + * @brief Computes and returns an array of volumes indexed by FSR. + * @details Note: It is the function caller's responsibility to deallocate + * the memory reserved for the FSR volume array. + * @return a pointer to the array of FSR volumes + */ +FP_PRECISION* TrackGenerator::getFSRVolumes() { + + if (!containsTracks()) + log_printf(ERROR, "Unable to get the FSR volumes since tracks " + "have not yet been generated"); + + int num_FSRs = _geometry->getNumFSRs(); + FP_PRECISION* FSR_volumes = new FP_PRECISION[num_FSRs]; + memset(FSR_volumes, 0., num_FSRs*sizeof(FP_PRECISION)); + +#pragma omp parallel + { + int azim_index, fsr_id; + segment* curr_segment; + FP_PRECISION volume; + + /* Calculate each FSR's "volume" by accumulating the total length of * + * all Track segments multipled by the Track "widths" for each FSR. */ + for (int i=0; i < _num_azim; i++) { +#pragma omp for + for (int j=0; j < _num_tracks[i]; j++) { + + azim_index = _tracks[i][j].getAzimAngleIndex(); + + for (int s=0; s < _tracks[i][j].getNumSegments(); s++) { + curr_segment = _tracks[i][j].getSegment(s); + volume = curr_segment->_length * _azim_weights[azim_index]; + fsr_id = curr_segment->_region_id; + + /* Set FSR mutual exclusion lock */ + omp_set_lock(&_FSR_locks[fsr_id]); + + FSR_volumes[fsr_id] += volume; + + /* Release FSR mutual exclusion lock */ + omp_unset_lock(&_FSR_locks[fsr_id]); + } + } + } + } + + return FSR_volumes; +} + + +/** + * @brief Computes and returns the volume of an FSR. + * @param fsr_id the ID for the FSR of interest + * @return the FSR volume + */ +FP_PRECISION TrackGenerator::getFSRVolume(int fsr_id) { + + if (!containsTracks()) + log_printf(ERROR, "Unable to get the FSR %d volume since tracks " + "have not yet been generated"); + + else if (fsr_id < 0 || fsr_id > _geometry->getNumFSRs()) + log_printf(ERROR, "Unable to get the volume for FSR %d since the FSR IDs " + "lie in the range (0, %d)", fsr_id, _geometry->getNumFSRs()); + + segment* curr_segment; + FP_PRECISION volume = 0; + + /* Calculate the FSR's "volume" by accumulating the total length of * + * all Track segments multipled by the Track "widths" for the FSR. */ + for (int i=0; i < _num_azim; i++) { +#pragma omp parallel for reduction(+:volume) private(curr_segment) + for (int j=0; j < _num_tracks[i]; j++) { + for (int s=0; s < _tracks[i][j].getNumSegments(); s++) { + curr_segment = _tracks[i][j].getSegment(s); + if (curr_segment->_region_id == fsr_id) + volume += curr_segment->_length * _azim_weights[i]; + } + } + } + + return volume; +} + + +/** + * @brief Finds and returns the maximum optical length amongst all segments. + * @return the maximum optical path length + */ +FP_PRECISION TrackGenerator::getMaxOpticalLength() { + + FP_PRECISION max_optical_length = 0.; + +#pragma omp parallel + { + segment* curr_segment; + FP_PRECISION length; + Material* material; + FP_PRECISION* sigma_t; + + /* Iterate over all tracks, segments, groups to find max optical length */ + for (int i=0; i < _num_azim; i++) { +#pragma omp for reduction(max:max_optical_length) + for (int j=0; j < _num_tracks[i]; j++) { + for (int s=0; s < _tracks[i][j].getNumSegments(); s++) { + curr_segment = _tracks[i][j].getSegment(s); + length = curr_segment->_length; + material = curr_segment->_material; + sigma_t = material->getSigmaT(); + + for (int e=0; e < material->getNumEnergyGroups(); e++) + max_optical_length = std::max(max_optical_length, length*sigma_t[e]); + } + } + } + } + + return max_optical_length; +} + + +/** + * @brief Sets the number of shared memory OpenMP threads to use (>0). + * @param num_threads the number of threads + */ +void TrackGenerator::setNumThreads(int num_threads) { + + if (num_threads <= 0) + log_printf(ERROR, "Unable to set the number of threads for the " + "TrackGenerator to %d since it is less than or equal to 0" + , num_threads); + + _num_threads = num_threads; + + /* Set the number of threads for OpenMP */ + omp_set_num_threads(_num_threads); +} + + +/** + * @brief Sets the z-coord where the 2D Tracks should be created. + * @param z_coord the z-coord where the 2D Tracks should be created. + */ +void TrackGenerator::setZCoord(double z_coord) { + _z_coord = z_coord; +} + + +/** + * @brief Set the number of azimuthal angles in \f$ [0, 2\pi] \f$. + * @param num_azim the number of azimuthal angles in \f$ 2\pi \f$ + */ +void TrackGenerator::setNumAzim(int num_azim) { + + if (num_azim < 0) + log_printf(ERROR, "Unable to set a negative number of azimuthal angles " + "%d for the TrackGenerator.", num_azim); + + if (num_azim % 4 != 0) + log_printf(ERROR, "Unable to set the number of azimuthal angles to %d for " + "the TrackGenerator since it is not a multiple of 4", num_azim); + + /* Subdivide out angles in [pi,2pi] */ + _num_azim = num_azim / 2; + + _contains_tracks = false; + _use_input_file = false; + _tracks_filename = ""; +} + + +/** + * @brief Set the suggested track spacing (cm). + * @param spacing the suggested track spacing + */ +void TrackGenerator::setTrackSpacing(double spacing) { + if (spacing < 0) + log_printf(ERROR, "Unable to set a negative track spacing %f for the " + "TrackGenerator.", spacing); + + _spacing = spacing; + _contains_tracks = false; + _use_input_file = false; + _tracks_filename = ""; +} + + +/** + * @brief Set a pointer to the Geometry to use for track generation. + * @param geometry a pointer to the Geometry + */ +void TrackGenerator::setGeometry(Geometry* geometry) { + _geometry = geometry; + _contains_tracks = false; + _use_input_file = false; + _tracks_filename = ""; +} + + /** * @brief Returns whether or not the TrackGenerator contains Track that are * for its current number of azimuthal angles, track spacing and @@ -200,7 +475,7 @@ bool TrackGenerator::containsTracks() { /** - * @brief Fills an array with the x,y coordinates for each Track. + * @brief Fills an array with the x,y,z coordinates for each Track. * @details This class method is intended to be called by the OpenMOC * Python "plotter" module as a utility to assist in plotting * tracks. Although this method appears to require two arguments, @@ -209,19 +484,22 @@ bool TrackGenerator::containsTracks() { * * @code * num_tracks = track_generator.getNumTracks() - * coords = track_generator.retrieveTrackCoords(num_tracks*4) + * coords = track_generator.retrieveTrackCoords + * (num_tracks*NUM_VALUES_PER_RETRIEVED_TRACK) * @endcode * - * @param coords an array of coords of length 4 times the number of Tracks - * @param num_tracks the total number of Tracks + * @param coords an array of coords of length NUM_VALUES_PER_RETRIEVED_TRACK + * times the number of Tracks + * @param length_coords the total number of Tracks times + * NUM_VALUES_PER_RETRIEVED_TRACK */ -void TrackGenerator::retrieveTrackCoords(double* coords, int num_tracks) { +void TrackGenerator::retrieveTrackCoords(double* coords, int length_coords) { - if (num_tracks != 4*getNumTracks()) + if (length_coords != NUM_VALUES_PER_RETRIEVED_TRACK*getNumTracks()) log_printf(ERROR, "Unable to retrieve the Track coordinates since the " - "TrackGenerator contains %d Tracks with %d coordinates but an " - "array of length %d was input", - getNumTracks(), 4*getNumTracks(), num_tracks); + "TrackGenerator contains %d Tracks with %d coordinates per track" + " but an array of length %d was input", getNumTracks(), + NUM_VALUES_PER_RETRIEVED_TRACK, length_coords); /* Fill the array of coordinates with the Track start and end points */ int counter = 0; @@ -229,9 +507,11 @@ void TrackGenerator::retrieveTrackCoords(double* coords, int num_tracks) { for (int j=0; j < _num_tracks[i]; j++) { coords[counter] = _tracks[i][j].getStart()->getX(); coords[counter+1] = _tracks[i][j].getStart()->getY(); - coords[counter+2] = _tracks[i][j].getEnd()->getX(); - coords[counter+3] = _tracks[i][j].getEnd()->getY(); - counter += 4; + coords[counter+2] = _tracks[i][j].getStart()->getZ(); + coords[counter+3] = _tracks[i][j].getEnd()->getX(); + coords[counter+4] = _tracks[i][j].getEnd()->getY(); + coords[counter+5] = _tracks[i][j].getEnd()->getZ(); + counter += NUM_VALUES_PER_RETRIEVED_TRACK; } } @@ -240,7 +520,7 @@ void TrackGenerator::retrieveTrackCoords(double* coords, int num_tracks) { /** - * @brief Fills an array with the x,y coordinates for each Track segment. + * @brief Fills an array with the x,y,z coordinates for each Track segment. * @details This class method is intended to be called by the OpenMOC * Python "plotter" module as a utility to assist in plotting * segments. Although this method appears to require two arguments, @@ -249,22 +529,25 @@ void TrackGenerator::retrieveTrackCoords(double* coords, int num_tracks) { * * @code * num_segments = track_generator.getNumSegments() - * coords = track_generator.retrieveSegmentCoords(num_segments*5) + * coords = track_generator.retrieveSegmentCoords + * (num_segments*NUM_VALUES_PER_RETRIEVED_SEGMENT) * @endcode * - * @param coords an array of coords of length 5 times the number of segments - * @param num_segments the total number of Track segments + * @param coords an array of coords of length NUM_VALUES_PER_RETRIEVED_SEGMENT + * times the number of segments + * @param length_coords the total number of Track segments times + * NUM_VALUES_PER_RETRIEVED_SEGMENT */ -void TrackGenerator::retrieveSegmentCoords(double* coords, int num_segments) { +void TrackGenerator::retrieveSegmentCoords(double* coords, int length_coords) { - if (num_segments != 5*getNumSegments()) + if (length_coords != NUM_VALUES_PER_RETRIEVED_SEGMENT*getNumSegments()) log_printf(ERROR, "Unable to retrieve the Track segment coordinates since " - "the TrackGenerator contains %d segments with %d coordinates " - "but an array of length %d was input", - getNumSegments(), 5*getNumSegments(), num_segments); + "the TrackGenerator contains %d segments with %d values per " + "segment but an array of length %d was input", getNumSegments(), + NUM_VALUES_PER_RETRIEVED_SEGMENT, length_coords); segment* curr_segment = NULL; - double x0, x1, y0, y1; + double x0, x1, y0, y1, z; double phi; segment* segments; @@ -277,6 +560,7 @@ void TrackGenerator::retrieveSegmentCoords(double* coords, int num_segments) { x0 = _tracks[i][j].getStart()->getX(); y0 = _tracks[i][j].getStart()->getY(); + z = _tracks[i][j].getStart()->getZ(); phi = _tracks[i][j].getPhi(); segments = _tracks[i][j].getSegments(); @@ -288,17 +572,19 @@ void TrackGenerator::retrieveSegmentCoords(double* coords, int num_segments) { coords[counter+1] = x0; coords[counter+2] = y0; + coords[counter+3] = z; x1 = x0 + cos(phi) * curr_segment->_length; y1 = y0 + sin(phi) * curr_segment->_length; - coords[counter+3] = x1; - coords[counter+4] = y1; + coords[counter+4] = x1; + coords[counter+5] = y1; + coords[counter+6] = z; x0 = x1; y0 = y1; - counter += 5; + counter += NUM_VALUES_PER_RETRIEVED_SEGMENT; } } } @@ -307,69 +593,15 @@ void TrackGenerator::retrieveSegmentCoords(double* coords, int num_segments) { } -/** - * @brief Set the number of azimuthal angles in \f$ [0, 2\pi] \f$. - * @param num_azim the number of azimuthal angles in \f$ 2\pi \f$ - */ -void TrackGenerator::setNumAzim(int num_azim) { - - if (num_azim < 0) - log_printf(ERROR, "Unable to set a negative number of azimuthal angles " - "%d for the TrackGenerator.", num_azim); - - if (num_azim % 4 != 0) - log_printf(ERROR, "Unable to set the number of azimuthal angles to %d for " - "the TrackGenerator since it is not a multiple of 4", num_azim); - - /* Subdivide out angles in [pi,2pi] */ - _num_azim = num_azim / 2.0; - - _contains_tracks = false; - _use_input_file = false; - _tracks_filename = ""; -} - - -/** - * @brief Set the suggested track spacing (cm). - * @param spacing the suggested track spacing - */ -void TrackGenerator::setTrackSpacing(double spacing) { - if (spacing < 0) - log_printf(ERROR, "Unable to set a negative track spacing %f for the " - "TrackGenerator.", spacing); - - _spacing = spacing; - _tot_num_tracks = 0; - _tot_num_segments = 0; - _contains_tracks = false; - _use_input_file = false; - _tracks_filename = ""; -} - - -/** - * @brief Set a pointer to the Geometry to use for track generation. - * @param geometry a pointer to the Geometry - */ -void TrackGenerator::setGeometry(Geometry* geometry) { - _geometry = geometry; - _tot_num_tracks = 0; - _tot_num_segments = 0; - _contains_tracks = false; - _use_input_file = false; - _tracks_filename = ""; -} - - /** * @brief Generates tracks for some number of azimuthal angles and track spacing * @details Computes the effective angles and track spacing. Computes the * number of Tracks for each azimuthal angle, allocates memory for * all Tracks at each angle and sets each Track's starting and ending * Points, azimuthal angle, and azimuthal angle quadrature weight. + * @brief neighbor_cells whether to use neighbor cell optimizations */ -void TrackGenerator::generateTracks() { +void TrackGenerator::generateTracks(bool neighbor_cells) { if (_geometry == NULL) log_printf(ERROR, "Unable to generate Tracks since no Geometry " @@ -378,10 +610,12 @@ void TrackGenerator::generateTracks() { /* Deletes Tracks arrays if Tracks have been generated */ if (_contains_tracks) { delete [] _num_tracks; - delete [] _num_segments; + delete [] _num_tracks_by_parallel_group; delete [] _num_x; delete [] _num_y; delete [] _azim_weights; + delete [] _tracks_by_parallel_group; + delete [] _phi; for (int i = 0; i < _num_azim; i++) delete [] _tracks[i]; @@ -389,6 +623,13 @@ void TrackGenerator::generateTracks() { delete [] _tracks; } + /* Initialize the CMFD object */ + if (_geometry->getCmfd() != NULL) + _geometry->initializeCmfd(); + + /* Initialize FSRs with pin cell discretization and neighbor cell lists */ + _geometry->initializeFSRs(neighbor_cells); + initializeTrackFileDirectory(); /* If not Tracks input file exists, generate Tracks */ @@ -401,19 +642,19 @@ void TrackGenerator::generateTracks() { _num_y = new int[_num_azim]; _azim_weights = new FP_PRECISION[_num_azim]; _tracks = new Track*[_num_azim]; + _phi = new double[_num_azim]; } catch (std::exception &e) { - log_printf(ERROR, "Unable to allocate memory for TrackGenerator. " - "Backtrace:\n%s", e.what()); + log_printf(ERROR, "Unable to allocate memory for TrackGenerator"); } - /* Check to make sure that height, width of the Geometry are nonzero */ - if (_geometry->getHeight() <= 0 || _geometry->getHeight() <= 0) - log_printf(ERROR, "The total height and width of the Geometry must be " - "nonzero for Track generation. Create a CellFill which " + /* Check to make sure that width of the Geometry in x and y are nonzero */ + if (_geometry->getWidthX() <= 0 || _geometry->getWidthY() <= 0) + log_printf(ERROR, "The total x-width and y-width of the Geometry must be " + "non-zero for Track generation. Create a Cell which " "is filled by the entire geometry and bounded by XPlanes " "and YPlanes to enable the Geometry to determine the total " - "width and height of the model."); + "x-width and y-width of the model."); /* Generate Tracks, perform ray tracing across the geometry, and store * the data to a Track file */ @@ -424,16 +665,44 @@ void TrackGenerator::generateTracks() { dumpTracksToFile(); } catch (std::exception &e) { - log_printf(ERROR, "Unable to allocate memory needed to generate " - "Tracks. Backtrace:\n%s", e.what()); + log_printf(ERROR, "Unable to allocate memory for Tracks"); } } + /* Initialize the track boundary conditions and set the track UIDs */ initializeBoundaryConditions(); + initializeTrackCycleIndices(PERIODIC); + initializeTrackUids(); + initializeFSRLocks(); + initializeVolumes(); + return; } +/** + * @brief Create an array of OpenMP mutual exclusion locks for each FSR. + * @details This method allocates and initializes an array of OpenMP + * mutual exclusion locks for each FSR for use in loops that + * set or update values by FSR. + */ +void TrackGenerator::initializeFSRLocks() { + + /* Delete old FSR locks, if they exist */ + if (_FSR_locks != NULL) + delete [] _FSR_locks; + + /* Allocate array of mutex locks for each FSR */ + int num_FSRs = _geometry->getNumFSRs(); + _FSR_locks = new omp_lock_t[num_FSRs]; + + /* Loop over all FSRs to initialize OpenMP locks */ +#pragma omp parallel for schedule(guided) + for (int r=0; r < num_FSRs; r++) + omp_init_lock(&_FSR_locks[r]); +} + + /** * @brief This method creates a directory to store Track files, and reads * in ray tracing data for Tracks and segments from a Track file @@ -455,28 +724,30 @@ void TrackGenerator::initializeTrackFileDirectory() { directory << get_output_directory() << "/tracks"; struct stat st; - if (!stat(directory.str().c_str(), &st) == 0) + if ((!stat(directory.str().c_str(), &st)) == 0) mkdir(directory.str().c_str(), S_IRWXU); - if (_geometry->getCmfd() != NULL){ + if (_geometry->getCmfd() != NULL) { test_filename << directory.str() << "/" << _num_azim*2.0 << "_angles_" - << _spacing << "_cm_spacing_cmfd_" - << _geometry->getCmfd()->getNumX() + << _spacing << "_cm_spacing_z_" + << _z_coord << "_(" + << _geometry->getCmfd()->getNumX() << "x" << _geometry->getCmfd()->getNumY() - << ".data"; + << ")_cmfd.data"; } else{ test_filename << directory.str() << "/" << _num_azim*2.0 << "_angles_" - << _spacing << "_cm_spacing.data"; + << _spacing << "_cm_spacing_z_" + << _z_coord << ".data"; } _tracks_filename = test_filename.str(); /* Check to see if a Track file exists for this geometry, number of azimuthal * angles, and track spacing, and if so, import the ray tracing data */ - if (!stat(_tracks_filename.c_str(), &buffer)) { + if ((!stat(_tracks_filename.c_str(), &buffer))) { if (readTracksFromFile()) { _use_input_file = true; _contains_tracks = true; @@ -502,13 +773,10 @@ void TrackGenerator::initializeTracks() { double* dy_eff = new double[_num_azim]; double* d_eff = new double[_num_azim]; - /* Effective azimuthal angles with respect to positive x-axis */ - double* phi_eff = new double[_num_azim]; - double x1, x2; double iazim = _num_azim*2.0; - double width = _geometry->getWidth(); - double height = _geometry->getHeight(); + double width_x = _geometry->getWidthX(); + double width_y = _geometry->getWidthY(); /* Determine azimuthal angles and track spacing */ for (int i = 0; i < _num_azim; i++) { @@ -518,121 +786,379 @@ void TrackGenerator::initializeTracks() { double phi = 2.0 * M_PI / iazim * (0.5 + i); /* The number of intersections with x,y-axes */ - _num_x[i] = (int) (fabs(width / _spacing * sin(phi))) + 1; - _num_y[i] = (int) (fabs(height / _spacing * cos(phi))) + 1; + _num_x[i] = (int) (fabs(width_x / _spacing * sin(phi))) + 1; + _num_y[i] = (int) (fabs(width_y / _spacing * cos(phi))) + 1; /* Total number of Tracks */ _num_tracks[i] = _num_x[i] + _num_y[i]; /* Effective/actual angle (not the angle we desire, but close) */ - phi_eff[i] = atan((height * _num_x[i]) / (width * _num_y[i])); + _phi[i] = atan((width_y * _num_x[i]) / (width_x * _num_y[i])); /* Fix angles in range(pi/2, pi) */ if (phi > M_PI / 2) - phi_eff[i] = M_PI - phi_eff[i]; + _phi[i] = M_PI - _phi[i]; + + /* Effective Track spacing (not spacing we desire, but close) */ + dx_eff[i] = (width_x / _num_x[i]); + dy_eff[i] = (width_y / _num_y[i]); + d_eff[i] = (dx_eff[i] * sin(_phi[i])); + } + + /* Compute azimuthal angle quadrature weights */ + for (int i = 0; i < _num_azim; i++) { + + if (i < _num_azim - 1) + x1 = 0.5 * (_phi[i+1] - _phi[i]); + else + x1 = 2 * M_PI / 2.0 - _phi[i]; + + if (i >= 1) + x2 = 0.5 * (_phi[i] - _phi[i-1]); + else + x2 = _phi[i]; + + /* Multiply weight by 2 because angles are in [0, Pi] */ + _azim_weights[i] = (x1 + x2) / (2 * M_PI) * d_eff[i] * 2; + } + + log_printf(INFO, "Generating Track start and end points..."); + + /* Compute Track starting and end points */ + for (int i = 0; i < _num_azim; i++) { + + /* Tracks for azimuthal angle i */ + _tracks[i] = new Track[_num_tracks[i]]; + + /* Compute start points for Tracks starting on x-axis */ + for (int j = 0; j < _num_x[i]; j++) { + if (i < _num_azim / 2) + _tracks[i][j].getStart()->setCoords( + dx_eff[i] * (_num_x[i] - j - 0.5), 0, _z_coord); + else + _tracks[i][j].getStart()->setCoords(dx_eff[i] * (0.5 + j), 0, _z_coord); + } + + /* Compute start points for Tracks starting on y-axis */ + for (int j = 0; j < _num_y[i]; j++) { + + /* If Track points to the upper right */ + if (i < _num_azim / 2) + _tracks[i][_num_x[i]+j].getStart()->setCoords( + 0, dy_eff[i] * (0.5 + j), _z_coord); + + /* If Track points to the upper left */ + else + _tracks[i][_num_x[i]+j].getStart()->setCoords( + width_x, dy_eff[i] * (0.5 + j), _z_coord); + } + + /* Compute the exit points for each Track */ + for (int j = 0; j < _num_tracks[i]; j++) { + + /* Set the Track's end point */ + Point* start = _tracks[i][j].getStart(); + Point* end = _tracks[i][j].getEnd(); + computeEndPoint(start, end, _phi[i], width_x, width_y); + + /* Set the Track's azimuthal angle */ + _tracks[i][j].setPhi(_phi[i]); + } + } + + delete [] dx_eff; + delete [] dy_eff; + delete [] d_eff; +} + + +/** + * @brief Recalibrates Track start and end points to the origin of the Geometry. + * @details The origin of the Geometry is designated at its center by + * convention, but for track initialization the origin is assumed to be + * at the bottom right corner for simplicity. This method corrects + * for this by re-assigning the start and end Point coordinates. + */ +void TrackGenerator::recalibrateTracksToOrigin() { + + /* Recalibrate the tracks to the origin. */ + for (int a=0; a < _num_azim; a++) { + for (int i=0; i < _num_tracks[a]; i++) { + + double x0 = _tracks[a][i].getStart()->getX(); + double y0 = _tracks[a][i].getStart()->getY(); + double x1 = _tracks[a][i].getEnd()->getX(); + double y1 = _tracks[a][i].getEnd()->getY(); + double new_x0 = x0 + _geometry->getMinX(); + double new_y0 = y0 + _geometry->getMinY(); + double new_x1 = x1 + _geometry->getMinX(); + double new_y1 = y1 + _geometry->getMinY(); + double phi = _tracks[a][i].getPhi(); + + /* The z-coordinates don't need to be recalibrated to the origin. */ + double z0 = _tracks[a][i].getStart()->getZ(); + double z1 = _tracks[a][i].getEnd()->getZ(); + + _tracks[a][i].setValues(new_x0, new_y0, z0, new_x1, new_y1, z1, phi); + _tracks[a][i].setAzimAngleIndex(a); + } + } +} + + +/** + * @brief Set the cycle index for each track in a PERIODIC or REFLECTIVE cycle. + * @details The tracks can be separated into cycles as they traverse the + * geometry. It is important to set the periodic cycle indices for + * problems with periodic boundary conditions so transport sweeps can + * be performed in parallel over groups of tracks that do not transfer + * their flux into each other. In this method, all tracks are looped + * over; if the track's cycle index has not been set, the cycle index + * for the input boundaryType is incremented and the cycle index is set + * for that track and all tracks in its cycle. + */ +void TrackGenerator::initializeTrackCycleIndices(boundaryType bc) { + + if (bc != REFLECTIVE && bc != PERIODIC) + log_printf(ERROR, "Cannot initialize Track cycle indices for boundaryType" + " other than REFLECTIVE or PERIODIC"); + + Track* track; + int track_index; + int next_i, next_a; + bool fwd; + + /* Loop over all tracks */ + for (int a=0; a < _num_azim; a++) { + for (int i=0; i < _num_tracks[a]; i++) { + + /* Get the current track */ + track = &_tracks[a][i]; + + /* Set the track indices for PERIODIC boundaryType */ + if (bc == PERIODIC) { + + /* Check if track index has been set */ + if (track->getPeriodicTrackIndex() == -1) { + + /* Initialize the track index counter */ + track_index = 0; + next_i = i; + + /* Set the periodic track indexes for all tracks in periodic cycle */ + while (track->getPeriodicTrackIndex() == -1) { + + /* Set the track periodic cycle */ + track->setPeriodicTrackIndex(track_index); + + /* Get the xy index of the next track in cycle */ + if (next_i < _num_y[a]) + next_i +=_num_x[a]; + else + next_i -=_num_y[a]; + + /* Set the next track in cycle */ + track = &_tracks[a][next_i]; + + /* Increment index counter */ + track_index++; + } + } + } + + /* Set the track indices for REFLECTIVE boundaryType */ + else { + + /* Check if track index has been set */ + if (track->getReflectiveTrackIndex() == -1) { + + /* Initialize the track index counter */ + track_index = 0; + next_i = i; + next_a = a; + fwd = true; + + /* Set the reflective track indexes for all tracks in reflective + * cycle */ + while (track->getReflectiveTrackIndex() == -1) { + + /* Set the track reflective cycle */ + track->setReflectiveTrackIndex(track_index); + + /* Set the azimuthal angle of the next track in the cycle */ + next_a = _num_azim - next_a - 1; + + /* Set the xy index and direction of the next track in the cycle */ + if (fwd) { + if (next_i < _num_y[a]) { + next_i = next_i + _num_x[a]; + fwd = true; + } + else { + next_i = _num_x[a] + 2*_num_y[a] - next_i - 1; + fwd = false; + } + } + + else { + if (next_i < _num_x[a]) { + next_i = _num_x[a] - next_i - 1; + fwd = true; + } + else{ + next_i = next_i - _num_x[a]; + fwd = false; + } + } + + /* Set the next track in cycle */ + track = &_tracks[next_a][next_i]; + + /* Increment index counter */ + track_index++; + } + } + } + } + } +} + - /* Effective Track spacing (not spacing we desire, but close) */ - dx_eff[i] = (width / _num_x[i]); - dy_eff[i] = (height / _num_y[i]); - d_eff[i] = (dx_eff[i] * sin(phi_eff[i])); - } +/** + * @brief Set the Track UIDs for all tracks and generate the 1D array of + * track pointers that separates the groups of tracks by parallel group. + * @details The Solver requires the tracks to be separated into groups of tracks + * that can be looped over in parallel without data races. This method + * creates a 1D array of Track pointers where the tracks are arranged + * by parallel group. If the geometry has a periodic BC, 6 periodic + * groups are created; otherwise, 2 periodic groups are created. The + * Track UIDs are also set to their index in the tracks by periodic + * group array. + */ +void TrackGenerator::initializeTrackUids() { - /* Compute azimuthal angle quadrature weights */ - for (int i = 0; i < _num_azim; i++) { + Track* track; + bool periodic; + int uid = 0; + int azim_group_id, periodic_group_id; + int track_azim_group_id, track_periodic_group_id; + int track_periodic_index; + int num_tracks; + + /* If periodic boundary conditions are present, set the number of parallel + * track groups to 6; else, set the number of parallel track groups to 2. Also + * set the periodic boolean indicating whether periodic bcs are present. */ + if (_geometry->getMinXBoundaryType() == PERIODIC || + _geometry->getMinYBoundaryType() == PERIODIC) { + _num_parallel_track_groups = 6; + periodic = true; + } + else { + _num_parallel_track_groups = 2; + periodic = false; + } - if (i < _num_azim - 1) - x1 = 0.5 * (phi_eff[i+1] - phi_eff[i]); - else - x1 = 2 * M_PI / 2.0 - phi_eff[i]; + /* Allocate memory for the num tracks by parallel group array */ + _num_tracks_by_parallel_group = new int[_num_parallel_track_groups]; - if (i >= 1) - x2 = 0.5 * (phi_eff[i] - phi_eff[i-1]); - else - x2 = phi_eff[i]; + /* Allocate memory for the tracks by parallel group array */ + _tracks_by_parallel_group = new Track*[getNumTracks()]; - /* Multiply weight by 2 because angles are in [0, Pi] */ - _azim_weights[i] = (x1 + x2) / (2 * M_PI) * d_eff[i] * 2; - } + /* Loop over the parallel track groups */ + for (int g = 0; g < _num_parallel_track_groups; g++) { - log_printf(INFO, "Generating Track start and end points..."); + /* Initialize the number of tracks counter */ + num_tracks = 0; - /* Compute Track starting and end points */ - for (int i = 0; i < _num_azim; i++) { + /* Set the azimuthal and periodic group ids */ + azim_group_id = g % 2; + periodic_group_id = g / 2; - /* Tracks for azimuthal angle i */ - _tracks[i] = new Track[_num_tracks[i]]; + /* Loop over all tracks and add all tracks belonging to the current + * parallel group to the tracks by parallel groups array */ + for (int a=0; a < _num_azim; a++) { + for (int i=0; i < _num_tracks[a]; i++) { - /* Compute start points for Tracks starting on x-axis */ - for (int j = 0; j < _num_x[i]; j++) - _tracks[i][j].getStart()->setCoords(dx_eff[i] * (0.5+j), 0); + /* Get current track */ + track = &_tracks[a][i]; - /* Compute start points for Tracks starting on y-axis */ - for (int j = 0; j < _num_y[i]; j++) { + /* Get the track azim group id */ + track_azim_group_id = a / (_num_azim / 2); - /* If Track points to the upper right */ - if (sin(phi_eff[i]) > 0 && cos(phi_eff[i]) > 0) - _tracks[i][_num_x[i]+j].getStart()->setCoords(0, - dy_eff[i] * (0.5 + j)); + /* Get the track periodic group id */ + if (periodic) { + track_periodic_index = track->getPeriodicTrackIndex(); - /* If Track points to the upper left */ - else if (sin(phi_eff[i]) > 0 && cos(phi_eff[i]) < 0) - _tracks[i][_num_x[i]+j].getStart()->setCoords(width, - dy_eff[i] * (0.5 + j)); - } + /* If the track is the first track in periodic cycle, assign it a + * periodic group id of 0 */ + if (track_periodic_index == 0) + track_periodic_group_id = 0; - /* Compute the exit points for each Track */ - for (int j = 0; j < _num_tracks[i]; j++) { + /* If the track has an odd periodic cycle index, assign it a periodic + * group id of 1 */ + else if (track_periodic_index % 2 == 1) + track_periodic_group_id = 1; - /* Set the Track's end point */ - Point* start = _tracks[i][j].getStart(); - Point* end = _tracks[i][j].getEnd(); - computeEndPoint(start, end, phi_eff[i], width, height); + /* Else the track must have an even periodic cycle index and not be + * the first track in the periodic cycle; assign it a periodic group + * id of 2 */ + else + track_periodic_group_id = 2; + } - /* Set the Track's azimuthal angle */ - _tracks[i][j].setPhi(phi_eff[i]); + /* If the geometry does not have any periodic BCs, assign the track a + * periodic group id of 0 */ + else + track_periodic_group_id = 0; + + /* Check if track has current azim_group_id and periodic_group_id */ + if (azim_group_id == track_azim_group_id && + periodic_group_id == track_periodic_group_id) { + track->setUid(uid); + _tracks_by_parallel_group[uid] = track; + uid++; + num_tracks++; + } + } } - } - delete [] dx_eff; - delete [] dy_eff; - delete [] d_eff; - delete [] phi_eff; + /* Set the number of tracks in this parallel group */ + _num_tracks_by_parallel_group[g] = num_tracks; + } } /** - * @brief Recalibrates Track start and end points to the origin of the Geometry. - * @details The origin of the Geometry is designated at its center by - * convention, but for track initialization the origin is assumed to be - * at the bottom right corner for simplicity. This method corrects - * for this by re-assigning the start and end Point coordinates. + * @brief Computes the volumes/areas of each Cell and Material in the Geometry. + * @details This computes the volumes/areas of each Cell and Material in the + * Geometry from the length of track segments crossing each Cell. This + * routine assigns the volume and number of instances to each Cell and + * Material. This is a helper routine that is called after track + * segmentation is complete in TrackGenerator::generateTracks(). */ -void TrackGenerator::recalibrateTracksToOrigin() { +void TrackGenerator::initializeVolumes() { - int uid = 0; - - for (int i = 0; i < _num_azim; i++) { - _tot_num_tracks += _num_tracks[i]; - - for (int j = 0; j < _num_tracks[i]; j++) { + if (!containsTracks()) + log_printf(ERROR, "Unable to initialize volumes since tracks " + "have not yet been generated"); - _tracks[i][j].setUid(uid); - uid++; + Cell* cell; + Material* material; + int num_FSRs = _geometry->getNumFSRs(); + FP_PRECISION* fsr_volumes = getFSRVolumes(); - double x0 = _tracks[i][j].getStart()->getX(); - double y0 = _tracks[i][j].getStart()->getY(); - double x1 = _tracks[i][j].getEnd()->getX(); - double y1 = _tracks[i][j].getEnd()->getY(); - double new_x0 = x0 + _geometry->getMinX(); - double new_y0 = y0 + _geometry->getMinY(); - double new_x1 = x1 + _geometry->getMinX(); - double new_y1 = y1 + _geometry->getMinY(); - double phi = _tracks[i][j].getPhi(); + /* Compute volume and number of instances for each Cell and Material */ + for (int i=0; i < num_FSRs; i++) { + cell = _geometry->findCellContainingFSR(i); + cell->incrementVolume(fsr_volumes[i]); + cell->incrementNumInstances(); - _tracks[i][j].setValues(new_x0, new_y0, new_x1,new_y1, phi); - _tracks[i][j].setAzimAngleIndex(i); - } + material = cell->getFillMaterial(); + material->incrementVolume(fsr_volumes[i]); + material->incrementNumInstances(); } + + delete [] fsr_volumes; } @@ -644,25 +1170,26 @@ void TrackGenerator::recalibrateTracksToOrigin() { * @param start pointer to the Track start Point * @param end pointer to a Point to store the end Point coordinates * @param phi the azimuthal angle - * @param width the width of the Geometry (cm) - * @param height the height of the Geometry (cm) + * @param width_x the x-width of the Geometry (cm) + * @param width_y the y-width of the Geometry (cm) */ void TrackGenerator::computeEndPoint(Point* start, Point* end, - const double phi, const double width, - const double height) { + const double phi, const double width_x, + const double width_y) { double m = sin(phi) / cos(phi); /* slope */ - double yin = start->getY(); /* y-coord */ double xin = start->getX(); /* x-coord */ + double yin = start->getY(); /* y-coord */ + double zin = start->getZ(); /* z-coord */ /* Allocate memory for the possible intersection points */ Point *points = new Point[4]; /* Determine all possible Points */ - points[0].setCoords(0, yin - m * xin); - points[1].setCoords(width, yin + m * (width - xin)); - points[2].setCoords(xin - yin / m, 0); - points[3].setCoords(xin - (yin - height) / m, height); + points[0].setCoords(0, yin - m * xin, zin); + points[1].setCoords(width_x, yin + m * (width_x - xin), zin); + points[2].setCoords(xin - yin / m, 0, zin); + points[3].setCoords(xin - (yin - width_y) / m, width_y, zin); /* For each of the possible intersection Points */ for (int i = 0; i < 4; i++) { @@ -670,13 +1197,13 @@ void TrackGenerator::computeEndPoint(Point* start, Point* end, if (points[i].getX() == xin && points[i].getY() == yin) { } /* The Point to return will be within the bounds of the cell */ - else if (points[i].getX() >= 0 && points[i].getX() <= width - && points[i].getY() >= 0 && points[i].getY() <= height) { - end->setCoords(points[i].getX(), points[i].getY()); + else if (points[i].getX() >= 0 && points[i].getX() <= width_x + && points[i].getY() >= 0 && points[i].getY() <= width_y) { + end->setCoords(points[i].getX(), points[i].getY(), zin); } } - delete[] points; + delete [] points; return; } @@ -692,291 +1219,94 @@ void TrackGenerator::initializeBoundaryConditions() { log_printf(INFO, "Initializing Track boundary conditions..."); - /* nxi = number of tracks starting on y-axis for angle i - * nyi = number of tracks starting on y-axis for angle i - * nti = total number of tracks for angle i */ - int nxi, nyi, nti; - - Track *curr; - Track *refl; - - /* Loop over only half the angles since we will set the pointers for - * connecting Tracks at the same time */ - for (int i = 0; i < floor(_num_azim / 2); i++) { - nxi = _num_x[i]; - nyi = _num_y[i]; - nti = _num_tracks[i]; - curr = _tracks[i]; - refl = _tracks[_num_azim - i - 1]; - - /* Loop over all of the Tracks for this angle */ - for (int j = 0; j < nti; j++) { - - /* More Tracks starting along x-axis than y-axis */ - if (nxi <= nyi) { - - /* Bottom to right hand side */ - if (j < nxi) { - curr[j].setTrackIn(&refl[j]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j); - - refl[j].setTrackIn(&curr[j]); - refl[j].setTrackInI(i); - refl[j].setTrackInJ(j); - - curr[j].setReflIn(false); - refl[j].setReflIn(false); - - if (_geometry->getMinYBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j].setBCIn(1); - } - else { - curr[j].setBCIn(0); - refl[j].setBCIn(0); - } - - curr[j].setTrackOut(&refl[2 * nxi - 1 - j]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(2 * nxi - 1 - j); - - refl[2 * nxi - 1 - j].setTrackIn(&curr[j]); - refl[2 * nxi - 1 - j].setTrackInI(i); - refl[2 * nxi - 1 - j].setTrackInJ(j); - - curr[j].setReflOut(false); - refl[2 * nxi - 1 - j].setReflIn(true); - - if (_geometry->getMinXBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[2 * nxi - 1 - j].setBCIn(1); - } - else { - curr[j].setBCOut(0); - refl[2 * nxi - 1 - j].setBCIn(0); - } - } - - /* Left hand side to right hand side */ - else if (j < nyi) { - curr[j].setTrackIn(&refl[j - nxi]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j - nxi); - - refl[j - nxi].setTrackOut(&curr[j]); - refl[j - nxi].setTrackOutI(i); - refl[j - nxi].setTrackOutJ(j); + /* Check for symmetry of periodic boundary conditions */ + if ((_geometry->getMinXBoundaryType() == PERIODIC && + _geometry->getMaxXBoundaryType() != PERIODIC) || + (_geometry->getMinXBoundaryType() != PERIODIC && + _geometry->getMaxXBoundaryType() == PERIODIC)) + log_printf(ERROR, "Cannot create tracks with only one x boundary" + " set to PERIODIC"); + else if ((_geometry->getMinYBoundaryType() == PERIODIC && + _geometry->getMaxYBoundaryType() != PERIODIC) || + (_geometry->getMinYBoundaryType() != PERIODIC && + _geometry->getMaxYBoundaryType() == PERIODIC)) + log_printf(ERROR, "Cannot create tracks with only one y boundary" + " set to PERIODIC"); + Track* track; + int ic; - curr[j].setReflIn(true); - refl[j - nxi].setReflOut(false); + /* Loop over the all the tracks and set the incoming and outgoing tracks + * and incoming and outgoing boundary conditions. */ + for (int i=0; i < _num_azim; i++) { + ic = _num_azim - i - 1; + for (int j=0; j < _num_tracks[i]; j++) { - if (_geometry->getMinXBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j - nxi].setBCOut(1); - } - else { - curr[j].setBCIn(0); - refl[j - nxi].setBCOut(0); - } + /* Get current track */ + track = &_tracks[i][j]; - curr[j].setTrackOut(&refl[j + nxi]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(j + nxi); + /* Set boundary conditions for tracks in [0, PI/2] */ + if (i < _num_azim/2) { + if (j < _num_y[i]) + track->setBCOut(_geometry->getMaxXBoundaryType()); + else + track->setBCOut(_geometry->getMaxYBoundaryType()); - refl[j + nxi].setTrackIn(&curr[j]); - refl[j + nxi].setTrackInI(i); - refl[j + nxi].setTrackInJ(j); + if (j < _num_x[i]) + track->setBCIn(_geometry->getMinYBoundaryType()); + else + track->setBCIn(_geometry->getMinXBoundaryType()); + } - curr[j].setReflOut(false); - refl[j + nxi].setReflIn(true); + /* Set boundary conditions for tracks in [PI/2, PI] */ + else{ + if (j < _num_y[i]) + track->setBCOut(_geometry->getMinXBoundaryType()); + else + track->setBCOut(_geometry->getMaxYBoundaryType()); + + if (j < _num_x[i]) + track->setBCIn(_geometry->getMinYBoundaryType()); + else + track->setBCIn(_geometry->getMaxXBoundaryType()); + } - if (_geometry->getMaxXBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[j + nxi].setBCIn(1); - } - else { - curr[j].setBCOut(0); - refl[j + nxi].setBCIn(0); - } + /* Set connecting tracks in forward direction */ + if (j < _num_y[i]) { + track->setNextOut(false); + if (track->getBCOut() == PERIODIC) + track->setTrackOut(&_tracks[i][j + _num_x[i]]); + else + track->setTrackOut(&_tracks[ic][j + _num_x[i]]); + } + else{ + if (track->getBCOut() == PERIODIC) { + track->setNextOut(false); + track->setTrackOut(&_tracks[i][j - _num_y[i]]); } - - /* Left hand side to top (j > ny) */ - else { - curr[j].setTrackIn(&refl[j - nxi]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j - nxi); - - refl[j - nxi].setTrackOut(&curr[j]); - refl[j - nxi].setTrackOutI(i); - refl[j - nxi].setTrackOutJ(j); - - curr[j].setReflIn(true); - refl[j - nxi].setReflOut(false); - - if (_geometry->getMinXBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j - nxi].setBCOut(1); - } - else { - curr[j].setBCIn(0); - refl[j - nxi].setBCOut(0); - } - - curr[j].setTrackOut(&refl[2 * nti - nxi - j - 1]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(2 * nti - nxi - j - 1); - - refl[2 * nti - nxi - j - 1].setTrackOut(&curr[j]); - refl[2 * nti - nxi - j - 1].setTrackOutI(i); - refl[2 * nti - nxi - j - 1].setTrackOutJ(j); - - curr[j].setReflOut(true); - refl[2 * nti - nxi - j - 1].setReflOut(true); - - if (_geometry->getMaxYBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[2 * nti - nxi - j - 1].setBCOut(1); - } - else { - curr[j].setBCOut(0); - refl[2 * nti - nxi - j - 1].setBCOut(0); - } + else{ + track->setNextOut(true); + track->setTrackOut(&_tracks[ic][_num_x[i] + 2*_num_y[i] - j - 1]); } } - /* More Tracks starting on y-axis than on x-axis */ - else { - - /* Bottom to top */ - if (j < nxi - nyi) { - curr[j].setTrackIn(&refl[j]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j); - - refl[j].setTrackIn(&curr[j]); - refl[j].setTrackInI(i); - refl[j].setTrackInJ(j); - - curr[j].setReflIn(false); - refl[j].setReflIn(false); - - if (_geometry->getMinYBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j].setBCIn(1); - } - else { - curr[j].setBCIn(0); - refl[j].setBCIn(0); - } - - curr[j].setTrackOut(&refl[nti - (nxi - nyi) + j]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(nti - (nxi - nyi) + j); - - refl[nti - (nxi - nyi) + j].setTrackOut(&curr[j]); - refl[nti - (nxi - nyi) + j].setTrackOutI(i); - refl[nti - (nxi - nyi) + j].setTrackOutJ(j); - - curr[j].setReflOut(true); - refl[nti - (nxi - nyi) + j].setReflOut(true); - - if (_geometry->getMaxYBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[nti - (nxi - nyi) + j].setBCOut(1); - } - else { - curr[j].setBCOut(0); - refl[nti - (nxi - nyi) + j].setBCOut(0); - } - } - - /* Bottom to right hand side */ - else if (j < nxi) { - curr[j].setTrackIn(&refl[j]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j); - - refl[j].setTrackIn(&curr[j]); - refl[j].setTrackInI(i); - refl[j].setTrackInJ(j); - - curr[j].setReflIn(false); - refl[j].setReflIn(false); - - if (_geometry->getMinYBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j].setBCIn(1); - } - else { - curr[j].setBCIn(0); - refl[j].setBCIn(0); - } - - curr[j].setTrackOut(&refl[nxi + (nxi - j) - 1]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(nxi + (nxi - j) - 1); - - refl[nxi + (nxi - j) - 1].setTrackIn(&curr[j]); - refl[nxi + (nxi - j) - 1].setTrackInI(i); - refl[nxi + (nxi - j) - 1].setTrackInJ(j); - - curr[j].setReflOut(false); - refl[nxi + (nxi - j) - 1].setReflIn(true); - - if (_geometry->getMinXBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[nxi + (nxi - j) - 1].setBCIn(1); - } - else { - curr[j].setBCOut(0); - refl[nxi + (nxi - j) - 1].setBCIn(0); - } + /* Set connecting tracks in backward direction */ + if (j < _num_x[i]) { + if (track->getBCIn() == PERIODIC) { + track->setNextIn(true); + track->setTrackIn(&_tracks[i][j + _num_y[i]]); } - - /* Left-hand side to top (j > nx) */ - else { - curr[j].setTrackIn(&refl[j - nxi]); - curr[j].setTrackInI(_num_azim - i - 1); - curr[j].setTrackInJ(j - nxi); - - refl[j - nxi].setTrackOut(&curr[j]); - refl[j - nxi].setTrackOutI(i); - refl[j - nxi].setTrackOutJ(j); - - curr[j].setReflIn(true); - refl[j - nxi].setReflOut(false); - - if (_geometry->getMinXBoundaryType() == REFLECTIVE) { - curr[j].setBCIn(1); - refl[j - nxi].setBCOut(1); - } - else { - curr[j].setBCIn(0); - refl[j - nxi].setBCOut(0); - } - - curr[j].setTrackOut(&refl[nyi + (nti - j) - 1]); - curr[j].setTrackOutI(_num_azim - i - 1); - curr[j].setTrackOutJ(nyi + (nti - j) - 1); - - refl[nyi + (nti - j) - 1].setTrackOut(&curr[j]); - refl[nyi + (nti - j) - 1].setTrackOutI(i); - refl[nyi + (nti - j) - 1].setTrackOutJ(j); - - curr[j].setReflOut(true); - refl[nyi + (nti - j) - 1].setReflOut(true); - - if (_geometry->getMaxYBoundaryType() == REFLECTIVE) { - curr[j].setBCOut(1); - refl[nyi + (nti - j) - 1].setBCOut(1); - } - else { - curr[j].setBCOut(0); - refl[nyi + (nti - j) - 1].setBCOut(0); - } + else{ + track->setNextIn(false); + track->setTrackIn(&_tracks[ic][_num_x[i] - j - 1]); } } + else{ + track->setNextIn(true); + if (track->getBCIn() == PERIODIC) + track->setTrackIn(&_tracks[i][j - _num_x[i]]); + else + track->setTrackIn(&_tracks[ic][j - _num_x[i]]); + } } } @@ -993,37 +1323,22 @@ void TrackGenerator::segmentize() { Track* track; - if (_num_segments != NULL) - delete [] _num_segments; - /* This section loops over all Track and segmentizes each one if the * Tracks were not read in from an input file */ if (!_use_input_file) { /* Loop over all Tracks */ for (int i=0; i < _num_azim; i++) { - #pragma omp parallel for private(track) - for (int j=0; j < _num_tracks[i]; j++){ - track = &_tracks[i][j]; - log_printf(DEBUG, "Segmenting Track %d/%d with i = %d, j = %d", - track->getUid(), _tot_num_tracks, i, j); - _geometry->segmentize(track,_max_optical_length); - } - } - - /* Compute the total number of segments in the simulation */ - _num_segments = new int[_tot_num_tracks]; - _tot_num_segments = 0; - - for (int i=0; i < _num_azim; i++) { +#pragma omp parallel for private(track) for (int j=0; j < _num_tracks[i]; j++) { track = &_tracks[i][j]; - _num_segments[track->getUid()] = track->getNumSegments(); - _tot_num_segments += _num_segments[track->getUid()]; + _geometry->segmentize(track); } } } + _geometry->initializeFSRVectors(); + _contains_tracks = true; return; @@ -1068,10 +1383,10 @@ void TrackGenerator::dumpTracksToFile() { for (int i=0; i < _num_azim; i++) azim_weights[i] = _azim_weights[i]; fwrite(azim_weights, sizeof(double), _num_azim, out); - free(azim_weights); + delete [] azim_weights; Track* curr_track; - double x0, y0, x1, y1; + double x0, y0, z0, x1, y1, z1; double phi; int azim_angle_index; int num_segments; @@ -1093,8 +1408,10 @@ void TrackGenerator::dumpTracksToFile() { curr_track = &_tracks[i][j]; x0 = curr_track->getStart()->getX(); y0 = curr_track->getStart()->getY(); + z0 = curr_track->getStart()->getZ(); x1 = curr_track->getEnd()->getX(); y1 = curr_track->getEnd()->getY(); + z1 = curr_track->getEnd()->getZ(); phi = curr_track->getPhi(); azim_angle_index = curr_track->getAzimAngleIndex(); num_segments = curr_track->getNumSegments(); @@ -1102,8 +1419,10 @@ void TrackGenerator::dumpTracksToFile() { /* Write data for this Track to the Track file */ fwrite(&x0, sizeof(double), 1, out); fwrite(&y0, sizeof(double), 1, out); + fwrite(&z0, sizeof(double), 1, out); fwrite(&x1, sizeof(double), 1, out); fwrite(&y1, sizeof(double), 1, out); + fwrite(&z1, sizeof(double), 1, out); fwrite(&phi, sizeof(double), 1, out); fwrite(&azim_angle_index, sizeof(int), 1, out); fwrite(&num_segments, sizeof(int), 1, out); @@ -1123,7 +1442,7 @@ void TrackGenerator::dumpTracksToFile() { fwrite(®ion_id, sizeof(int), 1, out); /* Write CMFD-related data for the Track if needed */ - if (cmfd != NULL){ + if (cmfd != NULL) { cmfd_surface_fwd = curr_segment->_cmfd_surface_fwd; cmfd_surface_bwd = curr_segment->_cmfd_surface_bwd; fwrite(&cmfd_surface_fwd, sizeof(int), 1, out); @@ -1134,61 +1453,68 @@ void TrackGenerator::dumpTracksToFile() { } /* Get FSR vector maps */ - std::unordered_map FSR_keys_map = _geometry->getFSRKeysMap(); - std::unordered_map::iterator iter; - std::vector FSRs_to_keys = _geometry->getFSRsToKeys(); - std::vector FSRs_to_material_IDs = _geometry->getFSRsToMaterialIDs(); - std::size_t fsr_key; + ParallelHashMap& FSR_keys_map = + _geometry->getFSRKeysMap(); + std::vector& FSRs_to_keys = _geometry->getFSRsToKeys(); + std::string fsr_key; int fsr_id; - int fsr_counter = 0; - double x, y; + double x, y, z; /* Write number of FSRs */ int num_FSRs = _geometry->getNumFSRs(); fwrite(&num_FSRs, sizeof(int), 1, out); /* Write FSR vector maps to file */ - for (iter = FSR_keys_map.begin(); iter != FSR_keys_map.end(); ++iter){ + std::string* fsr_key_list = FSR_keys_map.keys(); + fsr_data** fsr_data_list = FSR_keys_map.values(); + for (int i=0; i < num_FSRs; i++) { + + /* Write key to file from FSR_keys_map */ + fsr_key = fsr_key_list[i]; + string_length = fsr_key.length() + 1; + fwrite(&string_length, sizeof(int), 1, out); + fwrite(fsr_key.c_str(), sizeof(char)*string_length, 1, out); /* Write data to file from FSR_keys_map */ - fsr_key = iter->first; - fsr_id = iter->second._fsr_id; - x = iter->second._point->getX(); - y = iter->second._point->getY(); - fwrite(&fsr_key, sizeof(std::size_t), 1, out); + fsr_id = fsr_data_list[i]->_fsr_id; + x = fsr_data_list[i]->_point->getX(); + y = fsr_data_list[i]->_point->getY(); + z = fsr_data_list[i]->_point->getZ(); fwrite(&fsr_id, sizeof(int), 1, out); fwrite(&x, sizeof(double), 1, out); fwrite(&y, sizeof(double), 1, out); - - /* Write data to file from FSRs_to_material_IDs */ - fwrite(&(FSRs_to_material_IDs.at(fsr_counter)), sizeof(int), 1, out); + fwrite(&z, sizeof(double), 1, out); /* Write data to file from FSRs_to_keys */ - fwrite(&(FSRs_to_keys.at(fsr_counter)), sizeof(std::size_t), 1, out); - - /* Increment FSR ID counter */ - fsr_counter++; + fsr_key = FSRs_to_keys.at(i); + string_length = fsr_key.length() + 1; + fwrite(&string_length, sizeof(int), 1, out); + fwrite(fsr_key.c_str(), sizeof(char)*string_length, 1, out); } /* Write cmfd_fsrs vector of vectors to file */ - if (cmfd != NULL){ - std::vector< std::vector > cell_fsrs = cmfd->getCellFSRs(); + if (cmfd != NULL) { + std::vector< std::vector >* cell_fsrs = cmfd->getCellFSRs(); std::vector::iterator iter; int num_cells = cmfd->getNumCells(); fwrite(&num_cells, sizeof(int), 1, out); /* Loop over CMFD cells */ - for (int cell=0; cell < num_cells; cell++){ - num_FSRs = cell_fsrs.at(cell).size(); + for (int cell=0; cell < num_cells; cell++) { + num_FSRs = cell_fsrs->at(cell).size(); fwrite(&num_FSRs, sizeof(int), 1, out); /* Loop over FSRs within cell */ - for (iter = cell_fsrs.at(cell).begin(); iter != cell_fsrs.at(cell).end(); - ++iter) + for (iter = cell_fsrs->at(cell).begin(); + iter != cell_fsrs->at(cell).end(); ++iter) fwrite(&(*iter), sizeof(int), 1, out); } } + /* Delete key and value lists */ + delete [] fsr_key_list; + delete [] fsr_data_list; + /* Close the Track file */ fclose(out); @@ -1212,10 +1538,10 @@ bool TrackGenerator::readTracksFromFile() { /* Deletes Tracks arrays if tracks have been generated */ if (_contains_tracks) { delete [] _num_tracks; - delete [] _num_segments; delete [] _num_x; delete [] _num_y; delete [] _azim_weights; + delete [] _phi; for (int i = 0; i < _num_azim; i++) delete [] _tracks[i]; @@ -1226,7 +1552,6 @@ bool TrackGenerator::readTracksFromFile() { int ret; FILE* in; in = fopen(_tracks_filename.c_str(), "r"); - int string_length; /* Import Geometry metadata from the Track file */ @@ -1251,6 +1576,7 @@ bool TrackGenerator::readTracksFromFile() { _num_tracks = new int[_num_azim]; _num_x = new int[_num_azim]; _num_y = new int[_num_azim]; + _phi = new double[_num_azim]; _azim_weights = new FP_PRECISION[_num_azim]; double* azim_weights = new double[_num_azim]; _tracks = new Track*[_num_azim]; @@ -1264,10 +1590,10 @@ bool TrackGenerator::readTracksFromFile() { for (int i=0; i < _num_azim; i++) _azim_weights[i] = azim_weights[i]; - free(azim_weights); + delete [] azim_weights; Track* curr_track; - double x0, y0, x1, y1; + double x0, y0, z0, x1, y1, z1; double phi; int azim_angle_index; int num_segments; @@ -1283,19 +1609,8 @@ bool TrackGenerator::readTracksFromFile() { std::map materials = _geometry->getAllMaterials(); - /* Calculate the total number of Tracks */ - for (int i=0; i < _num_azim; i++) - _tot_num_tracks += _num_tracks[i]; - - /* Allocate memory for the number of segments per Track array */ - _num_segments = new int[_tot_num_tracks]; - - int uid = 0; - _tot_num_segments = 0; - /* Loop over Tracks */ for (int i=0; i < _num_azim; i++) { - _tracks[i] = new Track[_num_tracks[i]]; for (int j=0; j < _num_tracks[i]; j++) { @@ -1303,20 +1618,19 @@ bool TrackGenerator::readTracksFromFile() { /* Import data for this Track from Track file */ ret = fread(&x0, sizeof(double), 1, in); ret = fread(&y0, sizeof(double), 1, in); + ret = fread(&z0, sizeof(double), 1, in); ret = fread(&x1, sizeof(double), 1, in); ret = fread(&y1, sizeof(double), 1, in); + ret = fread(&z1, sizeof(double), 1, in); ret = fread(&phi, sizeof(double), 1, in); ret = fread(&azim_angle_index, sizeof(int), 1, in); ret = fread(&num_segments, sizeof(int), 1, in); - _tot_num_segments += num_segments; - _num_segments[uid] += num_segments; - /* Initialize a Track with this data */ curr_track = &_tracks[i][j]; - curr_track->setValues(x0, y0, x1, y1, phi); - curr_track->setUid(uid); + curr_track->setValues(x0, y0, z0, x1, y1, z1, phi); curr_track->setAzimAngleIndex(azim_angle_index); + _phi[azim_angle_index] = phi; /* Loop over all segments in this Track */ for (int s=0; s < num_segments; s++) { @@ -1332,7 +1646,7 @@ bool TrackGenerator::readTracksFromFile() { curr_segment._region_id = region_id; /* Import CMFD-related data if needed */ - if (cmfd != NULL){ + if (cmfd != NULL) { ret = fread(&cmfd_surface_fwd, sizeof(int), 1, in); ret = fread(&cmfd_surface_bwd, sizeof(int), 1, in); curr_segment._cmfd_surface_fwd = cmfd_surface_fwd; @@ -1342,74 +1656,73 @@ bool TrackGenerator::readTracksFromFile() { /* Add this segment to the Track */ curr_track->addSegment(&curr_segment); } - - uid++; } } /* Create FSR vector maps */ - std::unordered_map FSR_keys_map; - std::vector FSRs_to_material_IDs; - std::vector FSRs_to_keys; + ParallelHashMap& FSR_keys_map = + _geometry->getFSRKeysMap(); + std::vector& FSRs_to_keys = + _geometry->getFSRsToKeys(); + FSR_keys_map.clear(); + FSRs_to_keys.clear(); int num_FSRs; - std::size_t fsr_key; + std::string fsr_key; int fsr_key_id; - double x, y; + double x, y, z; /* Get number of FSRs */ ret = fread(&num_FSRs, sizeof(int), 1, in); - _geometry->setNumFSRs(num_FSRs); /* Read FSR vector maps from file */ - for (int fsr_id=0; fsr_id < num_FSRs; fsr_id++){ + for (int fsr_id=0; fsr_id < num_FSRs; fsr_id++) { + + /* Read key for FSR_keys_map */ + ret = fread(&string_length, sizeof(int), 1, in); + char* char_buffer1 = new char[string_length]; + ret = fread(char_buffer1, sizeof(char)*string_length, 1, in); + fsr_key = std::string(char_buffer1); /* Read data from file for FSR_keys_map */ - ret = fread(&fsr_key, sizeof(std::size_t), 1, in); ret = fread(&fsr_key_id, sizeof(int), 1, in); ret = fread(&x, sizeof(double), 1, in); ret = fread(&y, sizeof(double), 1, in); + ret = fread(&z, sizeof(double), 1, in); fsr_data* fsr = new fsr_data; fsr->_fsr_id = fsr_key_id; Point* point = new Point(); - point->setCoords(x,y); + point->setCoords(x,y,z); fsr->_point = point; - FSR_keys_map[fsr_key] = *fsr; - - /* Read data from file for FSR_to_materials_IDs */ - ret = fread(&material_id, sizeof(int), 1, in); - FSRs_to_material_IDs.push_back(material_id); + FSR_keys_map.insert(fsr_key, fsr); /* Read data from file for FSR_to_keys */ - ret = fread(&fsr_key, sizeof(std::size_t), 1, in); + ret = fread(&string_length, sizeof(int), 1, in); + char* char_buffer2 = new char[string_length]; + ret = fread(char_buffer2, sizeof(char)*string_length, 1, in); + fsr_key = std::string(char_buffer2); FSRs_to_keys.push_back(fsr_key); } - /* Set FSR vector maps */ - _geometry->setFSRKeysMap(FSR_keys_map); - _geometry->setFSRsToMaterialIDs(FSRs_to_material_IDs); - _geometry->setFSRsToKeys(FSRs_to_keys); - /* Read cmfd cell_fsrs vector of vectors from file */ - if (cmfd != NULL){ + if (cmfd != NULL) { std::vector< std::vector > cell_fsrs; int num_cells, fsr_id; ret = fread(&num_cells, sizeof(int), 1, in); /* Loop over CMFD cells */ - for (int cell=0; cell < num_cells; cell++){ - std::vector *fsrs = new std::vector; - cell_fsrs.push_back(*fsrs); + for (int cell=0; cell < num_cells; cell++) { + cell_fsrs.push_back(std::vector()); ret = fread(&num_FSRs, sizeof(int), 1, in); /* Loop over FRSs within cell */ - for (int fsr = 0; fsr < num_FSRs; fsr++){ + for (int fsr = 0; fsr < num_FSRs; fsr++) { ret = fread(&fsr_id, sizeof(int), 1, in); cell_fsrs.at(cell).push_back(fsr_id); } } /* Set CMFD cell_fsrs vector of vectors */ - cmfd->setCellFSRs(cell_fsrs); + cmfd->setCellFSRs(&cell_fsrs); } /* Inform the rest of the class methods that Tracks have been initialized */ @@ -1424,38 +1737,302 @@ bool TrackGenerator::readTracksFromFile() { /** - * @brief Set the maximum allowable optical length for a track segment - * @param max_optical_length The max optical length + * @brief Assign a correct volume for some FSR. + * @details This routine adjusts the length of each track segment crossing + * a FSR such that the integrated volume is identical to the true + * volume assigned by the user. + * @param fsr_id the ID of the FSR of interest + * @param fsr_volume the correct FSR volume to use */ -void TrackGenerator::setMaxOpticalLength(FP_PRECISION max_optical_length) { - if (max_optical_length <= 0) - log_printf(ERROR, "Cannot set max optical length to %f because it " - "must be positive.", max_optical_length); - - _max_optical_length = max_optical_length; +void TrackGenerator::correctFSRVolume(int fsr_id, FP_PRECISION fsr_volume) { + + if (!_contains_tracks) + log_printf(ERROR, "Unable to correct FSR volume since " + "tracks have not yet been generated"); + + /* Compute the current volume approximation for the flat source region */ + FP_PRECISION curr_volume = getFSRVolume(fsr_id); + + log_printf(INFO, "Correcting FSR %d volume from %f to %f", + fsr_id, curr_volume, fsr_volume); + + int num_segments, azim_index; + double dx_eff, d_eff; + double volume, corr_factor; + segment* curr_segment; + segment* segments; + + /* Correct volume separately for each azimuthal angle */ + for (int i=0; i < _num_azim; i++) { + + /* Initialize volume to zero for this azimuthal angle */ + volume = 0; + + /* Compute effective track spacing for this azimuthal angle */ + dx_eff = (_geometry->getWidthX() / _num_x[i]); + d_eff = (dx_eff * sin(_tracks[i][0].getPhi())); + + /* Compute the current estimated volume of the FSR for this angle */ +#pragma omp parallel for private(num_segments, segments, curr_segment) \ + reduction(+:volume) + for (int j=0; j < _num_tracks[i]; j++) { + + num_segments = _tracks[i][j].getNumSegments(); + segments = _tracks[i][j].getSegments(); + + for (int s=0; s < num_segments; s++) { + curr_segment = &segments[s]; + if (curr_segment->_region_id == fsr_id) + volume += curr_segment->_length * d_eff; + } + } + + /* Compute correction factor to the volume */ + corr_factor = fsr_volume / volume; + + log_printf(DEBUG, "Volume correction factor for FSR %d and azim " + "angle %d is %f", fsr_id, i, corr_factor); + + /* Correct the length of each segment which crosses the FSR */ +#pragma omp parallel for private(num_segments, segments, curr_segment) + for (int j=0; j < _num_tracks[i]; j++) { + + num_segments = _tracks[i][j].getNumSegments(); + segments = _tracks[i][j].getSegments(); + + for (int s=0; s < num_segments; s++) { + curr_segment = &segments[s]; + if (curr_segment->_region_id == fsr_id) + curr_segment->_length *= corr_factor; + } + } + } } + /** - * @brief Get the maximum allowable optical lenght for a track segment - * @return The max optical length + * @brief Generates the numerical centroids of the FSRs. + * @details This routine generates the numerical centroids of the FSRs + * by weighting the average x and y values of each segment in the + * FSR by the segment's length and azimuthal weight. The numerical + * centroid fomula can be found in R. Ferrer et. al. "Linear Source + * Approximation in CASMO 5", PHYSOR 2012. */ -FP_PRECISION TrackGenerator::getMaxOpticalLength() { - return _max_optical_length; +void TrackGenerator::generateFSRCentroids() { + + int num_FSRs = _geometry->getNumFSRs(); + FP_PRECISION* FSR_volumes = getFSRVolumes(); + + /* Create array of centroids and initialize to origin */ + Point** centroids = new Point*[num_FSRs]; +#pragma omp parallel for + for (int r=0; r < num_FSRs; r++) { + centroids[r] = new Point(); + centroids[r]->setCoords(0.0, 0.0, 0.0); + } + + /* Generate the fsr centroids */ + for (int i=0; i < _num_azim; i++) { +#pragma omp parallel for + for (int j=0; j < _num_tracks[i]; j++) { + + int num_segments = _tracks[i][j].getNumSegments(); + segment* segments = _tracks[i][j].getSegments(); + double x = _tracks[i][j].getStart()->getX(); + double y = _tracks[i][j].getStart()->getY(); + double z = _tracks[i][j].getStart()->getZ(); + double phi = _tracks[i][j].getPhi(); + + for (int s=0; s < num_segments; s++) { + segment* curr_segment = &segments[s]; + int fsr = curr_segment->_region_id; + double volume = FSR_volumes[fsr]; + + /* Set FSR mutual exclusion lock */ + omp_set_lock(&_FSR_locks[fsr]); + + centroids[fsr]->setX(centroids[fsr]->getX() + _azim_weights[i] * + (x + cos(phi) * curr_segment->_length / 2.0) * + curr_segment->_length / FSR_volumes[fsr]); + centroids[fsr]->setY(centroids[fsr]->getY() + _azim_weights[i] * + (y + sin(phi) * curr_segment->_length / 2.0) * + curr_segment->_length / FSR_volumes[fsr]); + centroids[fsr]->setZ(z); + + /* Release FSR mutual exclusion lock */ + omp_unset_lock(&_FSR_locks[fsr]); + + x += cos(phi) * curr_segment->_length; + y += sin(phi) * curr_segment->_length; + } + } + } + + /* Set the centroid for the FSR */ +#pragma omp parallel for + for (int r=0; r < num_FSRs; r++) + _geometry->setFSRCentroid(r, centroids[r]); + + /* Delete temporary array of FSR volumes and centroids */ + delete [] centroids; + delete [] FSR_volumes; } + /** - * @brief Get the total number of tracks in the TrackGenerator - * @return the total number of tracks + * @brief Splits Track segments into sub-segments for a user-defined + * maximum optical length for the problem. + * @details This routine is needed so that all segment lengths fit + * within the exponential interpolation table used in the MOC + * transport sweep. + * @param max_optical_length the maximum optical length */ -int TrackGenerator::getTotNumTracks() { - return _tot_num_tracks; +void TrackGenerator::splitSegments(FP_PRECISION max_optical_length) { + + if (!_contains_tracks) + log_printf(ERROR, "Unable to split segments since " + "tracks have not yet been generated"); + +#pragma omp parallel + { + + int num_cuts, min_num_cuts; + segment* curr_segment; + + FP_PRECISION length, tau; + int fsr_id; + Material* material; + FP_PRECISION* sigma_t; + int num_groups; + int cmfd_surface_fwd, cmfd_surface_bwd; + + /* Iterate over all Tracks */ + for (int i=0; i < _num_azim; i++) { +#pragma omp for + for (int j=0; j < _num_tracks[i]; j++) { + for (int s=0; s < _tracks[i][j].getNumSegments(); s+=min_num_cuts) { + + /* Extract data from this segment to compute it optical length */ + curr_segment = _tracks[i][j].getSegment(s); + material = curr_segment->_material; + length = curr_segment->_length; + fsr_id = curr_segment->_region_id; + cmfd_surface_fwd = curr_segment->_cmfd_surface_fwd; + cmfd_surface_bwd = curr_segment->_cmfd_surface_bwd; + + /* Compute number of segments to split this segment into */ + min_num_cuts = 1; + num_groups = material->getNumEnergyGroups(); + sigma_t = material->getSigmaT(); + + for (int g=0; g < num_groups; g++) { + tau = length * sigma_t[g]; + num_cuts = ceil(tau / max_optical_length); + min_num_cuts = std::max(num_cuts, min_num_cuts); + } + + /* If the segment does not need subdivisions, go to next segment */ + if (min_num_cuts == 1) + continue; + + /* Split the segment into sub-segments */ + for (int k=0; k < min_num_cuts; k++) { + + /* Create a new Track segment */ + segment* new_segment = new segment; + new_segment->_material = material; + new_segment->_length = length / FP_PRECISION(min_num_cuts); + new_segment->_region_id = fsr_id; + + /* Assign CMFD surface boundaries */ + if (k == 0) + new_segment->_cmfd_surface_bwd = cmfd_surface_bwd; + + if (k == min_num_cuts-1) + new_segment->_cmfd_surface_fwd = cmfd_surface_fwd; + + /* Insert the new segment to the Track */ + _tracks[i][j].insertSegment(s+k+1, new_segment); + } + + /* Remove the original segment from the Track */ + _tracks[i][j].removeSegment(s); + } + } + } + } } + /** - * @brief Get the total number of track segments in the TrackGenerator - * @return the total number of track segments + * @brief Initialize track segments with pointers to FSR Materials. + * @details This is called by the Solver at simulation time. This + * initialization is necessary since Materials in each FSR + * may be interchanged by the user in between different + * simulations. This method links each segment and fsr_data + * struct with the current Material found in each FSR. */ -int TrackGenerator::getTotNumSegments() { - return _tot_num_segments; +void TrackGenerator::initializeSegments() { + + if (!_contains_tracks) + log_printf(ERROR, "Unable to initialize segments since " + "tracks have not yet been generated"); + + /* Get all of the Materials from the Geometry */ + std::map materials = _geometry->getAllMaterials(); + + /* Get the mappings of FSR to keys to fsr_data to update Materials */ + ParallelHashMap& FSR_keys_map = + _geometry->getFSRKeysMap(); + std::vector& FSRs_to_keys = _geometry->getFSRsToKeys(); + +#pragma omp parallel + { + + int region_id, mat_id; + segment* curr_segment; + Material* mat; + + /* Set the Material for each FSR */ +#pragma omp for + for (int r=0; r < _geometry->getNumFSRs(); r++) { + mat = _geometry->findFSRMaterial(r); + FSR_keys_map.at(FSRs_to_keys.at(r))->_mat_id = mat->getId(); + } + + /* Set the Material for each segment */ + for (int i=0; i < _num_azim; i++) { +#pragma omp for + for (int j=0; j < _num_tracks[i]; j++) { + for (int s=0; s < _tracks[i][j].getNumSegments(); s++) { + curr_segment = _tracks[i][j].getSegment(s); + region_id = curr_segment->_region_id; + mat_id = FSR_keys_map.at(FSRs_to_keys.at(region_id))->_mat_id; + curr_segment->_material = materials[mat_id]; + } + } + } + } } + +/** + * @brief Returns the azimuthal angle for a given azimuthal angle index. + * @param the azimuthal angle index. + * @return the desired azimuthal angle. + */ +double TrackGenerator::getPhi(int azim) { + + if (!_contains_tracks) + log_printf(ERROR, "Unable to get Phi since the TrackGenerator does not" + " contain tracks."); + + if (azim < 0 || azim >= _num_azim*2) + log_printf(ERROR, "Unable to get Phi for azimuthal angle %d since there" + " %d azimuthal angles", azim, _num_azim*2); + + if (azim < _num_azim) + return _phi[azim]; + else + return 2 * M_PI - _phi[azim - _num_azim]; +} diff --git a/src/TrackGenerator.h b/src/TrackGenerator.h index 8a3a4ffa5..a4f76106c 100644 --- a/src/TrackGenerator.h +++ b/src/TrackGenerator.h @@ -11,13 +11,16 @@ #ifdef __cplusplus #define _USE_MATH_DEFINES +#ifdef SWIG +#include "Python.h" +#endif +#include "Track.h" +#include "Geometry.h" #include #include #include #include #include -#include "Track.h" -#include "Geometry.h" #endif @@ -41,17 +44,18 @@ class TrackGenerator { /** The track spacing (cm) */ double _spacing; + /** The azimuthal angles (radians) */ + double* _phi; + /** An integer array of the number of Tracks for each azimuthal angle */ int* _num_tracks; - /** The total number of Tracks for all azimuthal angles */ - int _tot_num_tracks; - - /** An integer array of the number of segments per Track */ - int* _num_segments; + /** An integer array with the number of Tracks in each parallel track group */ + int* _num_tracks_by_parallel_group; - /** The total number of segments for all Tracks */ - int _tot_num_segments; + /** The number of the track groups needed to ensure data races don't occur + * during the Solver's transportSweep */ + int _num_parallel_track_groups; /** An integer array of the number of Tracks starting on the x-axis for each * azimuthal angle */ @@ -60,9 +64,6 @@ class TrackGenerator { /** An integer array of the number of Tracks starting on the y-axis for each * azimuthal angle */ int* _num_y; - - /** The maximum optical length a track is allowed to have */ - FP_PRECISION _max_optical_length; /** An array of the azimuthal angle quadrature weights */ FP_PRECISION* _azim_weights; @@ -70,6 +71,9 @@ class TrackGenerator { /** A 2D ragged array of Tracks */ Track** _tracks; + /** A 1D array of Track pointers arranged by parallel group */ + Track** _tracks_by_parallel_group; + /** Pointer to the Geometry */ Geometry* _geometry; @@ -79,51 +83,72 @@ class TrackGenerator { /** Filename for the *.tracks input / output file */ std::string _tracks_filename; + /** OpenMP mutual exclusion locks for atomic FSR operations */ + omp_lock_t* _FSR_locks; + /** Boolean whether the Tracks have been generated (true) or not (false) */ bool _contains_tracks; + /** The z-coord where the 2D Tracks should be created */ + double _z_coord; + void computeEndPoint(Point* start, Point* end, const double phi, - const double width, const double height); + const double width_x, const double width_y); void initializeTrackFileDirectory(); void initializeTracks(); void recalibrateTracksToOrigin(); + void initializeTrackUids(); void initializeBoundaryConditions(); + void initializeTrackCycleIndices(boundaryType bc); + void initializeVolumes(); + void initializeFSRLocks(); void segmentize(); void dumpTracksToFile(); bool readTracksFromFile(); public: + TrackGenerator(Geometry* geometry, int num_azim, double spacing); virtual ~TrackGenerator(); /* Get parameters */ int getNumAzim(); + double getPhi(int azim); double getTrackSpacing(); Geometry* getGeometry(); int getNumTracks(); - int* getNumTracksArray(); + int getNumX(int azim); + int getNumY(int azim); + int getNumTracksByParallelGroup(int group); + int getNumParallelTrackGroups(); int getNumSegments(); - int* getNumSegmentsArray(); Track** getTracks(); + Track** getTracksByParallelGroup(); FP_PRECISION* getAzimWeights(); - FP_PRECISION getMaxOpticalLength(); - int getTotNumSegments(); - int getTotNumTracks(); int getNumThreads(); + FP_PRECISION* getFSRVolumes(); + FP_PRECISION getFSRVolume(int fsr_id); + FP_PRECISION getMaxOpticalLength(); + double getZCoord(); + omp_lock_t* getFSRLocks(); /* Set parameters */ void setNumAzim(int num_azim); void setTrackSpacing(double spacing); void setGeometry(Geometry* geometry); - void setMaxOpticalLength(FP_PRECISION max_optical_length); void setNumThreads(int num_threads); + void setZCoord(double z_coord); /* Worker functions */ bool containsTracks(); void retrieveTrackCoords(double* coords, int num_tracks); void retrieveSegmentCoords(double* coords, int num_segments); - void generateTracks(); + void generateTracks(bool neighbor_cells=false); + void correctFSRVolume(int fsr_id, FP_PRECISION fsr_volume); + void generateFSRCentroids(); + void splitSegments(FP_PRECISION max_optical_length); + void initializeSegments(); }; #endif /* TRACKGENERATOR_H_ */ diff --git a/src/Universe.cpp b/src/Universe.cpp index 71e3206ae..077b0c741 100644 --- a/src/Universe.cpp +++ b/src/Universe.cpp @@ -3,8 +3,7 @@ int Universe::_n = 0; -static int auto_id = 10000; - +static int auto_id = DEFAULT_INIT_ID; /** * @brief Returns an auto-generated unique Universe ID. @@ -26,7 +25,22 @@ int universe_id() { * @brief Resets the auto-generated unique Universe ID counter to 10000. */ void reset_universe_id() { - auto_id = 10000; + auto_id = DEFAULT_INIT_ID; +} + + +/** + * @brief Maximize the auto-generated unique Universe ID counter. + * @details This method updates the auto-generated unique Universe ID + * counter if the input parameter is greater than the present + * value. This is useful for the OpenCG compatibility module + * to ensure that the auto-generated Universe IDs do not + * collide with those created in OpenCG. + * @param universe_id the id assigned to the auto-generated counter + */ +void maximize_universe_id(int universe_id) { + if (universe_id > auto_id) + auto_id = universe_id; } @@ -38,8 +52,8 @@ void reset_universe_id() { Universe::Universe(const int id, const char* name) { /* If the user did not define an optional ID, create one */ - if (id == 0) - _id = cell_id(); + if (id == -1) + _id = universe_id(); /* Use the user-defined ID */ else @@ -62,10 +76,12 @@ Universe::Universe(const int id, const char* name) { * @brief Destructor clears the Cell pointers container. */ Universe::~Universe() { - _cells.clear(); if (_name != NULL) delete [] _name; + + /* Clear the map of Cells */ + _cells.clear(); } @@ -122,15 +138,31 @@ int Universe::getNumCells() const { */ double Universe::getMinX() { - double min_x = std::numeric_limits::infinity(); + double min_x = -std::numeric_limits::infinity(); + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { + /* Check if the universe contains a cell with an x-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::map surfs = c_iter->second->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; - if (min_x > iter->second->getMinX()) - min_x = iter->second->getMinX(); + if (surf->getSurfaceType() == XPLANE && halfspace == +1 && + surf->getBoundaryType() != BOUNDARY_NONE) + return surf->getMinX(halfspace); + } } + /* If a x-min boundary was not found, get the x-min from the bounding boxes + * of the cells */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) + min_x = std::min(min_x, c_iter->second->getMinX()); + return min_x; } @@ -141,14 +173,30 @@ double Universe::getMinX() { */ double Universe::getMaxX() { - double max_x = -std::numeric_limits::infinity(); - - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_x < iter->second->getMaxX()) - max_x = iter->second->getMaxX(); + double max_x = std::numeric_limits::infinity(); + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; + + /* Check if the universe contains a cell with an x-max boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::map surfs = c_iter->second->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + if (surf->getSurfaceType() == XPLANE && halfspace == -1 && + surf->getBoundaryType() != BOUNDARY_NONE) + return surf->getMaxX(halfspace); + } } + /* If a x-max boundary was not found, get the x-max from the bounding boxes + * of the cells */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) + max_x = std::max(max_x, c_iter->second->getMaxX()); + return max_x; } @@ -159,14 +207,31 @@ double Universe::getMaxX() { */ double Universe::getMinY() { - double min_y = std::numeric_limits::infinity(); + double min_y = -std::numeric_limits::infinity(); + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (min_y > iter->second->getMinY()) - min_y = iter->second->getMinY(); + /* Check if the universe contains a cell with an y-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::map surfs = c_iter->second->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + + if (surf->getSurfaceType() == YPLANE && halfspace == +1 && + surf->getBoundaryType() != BOUNDARY_NONE) + return surf->getMinY(halfspace); + } } + /* If a y-min boundary was not found, get the y-min from the bounding boxes + * of the cells */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) + min_y = std::min(min_y, c_iter->second->getMinY()); + return min_y; } @@ -175,16 +240,32 @@ double Universe::getMinY() { * @brief Returns the maximum reachable y-coordinate in the Universe. * @return the maximum reachable y-coordinate */ -double Universe::getMaxY(){ +double Universe::getMaxY() { - double max_y = -std::numeric_limits::infinity(); + double max_y = std::numeric_limits::infinity(); + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_y < iter->second->getMaxY()) - max_y = iter->second->getMaxY(); + /* Check if the universe contains a cell with an y-max boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::mapsurfs = c_iter->second->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + if (surf->getSurfaceType() == YPLANE && halfspace == -1 && + surf->getBoundaryType() != BOUNDARY_NONE) + return surf->getMaxY(halfspace); + } } + /* If a y-max boundary was not found, get the y-max from the bounding boxes + * of the cells */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) + max_y = std::max(max_y, c_iter->second->getMaxY()); + return max_y; } @@ -194,13 +275,12 @@ double Universe::getMaxY(){ * @return the minimum reachable z-coordinate */ double Universe::getMinZ() { - double min_z = std::numeric_limits::infinity(); + double min_z = -std::numeric_limits::infinity(); std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (min_z > iter->second->getMinZ()) - min_z = iter->second->getMinZ(); - } + + for (iter = _cells.begin(); iter != _cells.end(); ++iter) + min_z = std::min(min_z, iter->second->getMinZ()); return min_z; } @@ -212,13 +292,11 @@ double Universe::getMinZ() { */ double Universe::getMaxZ() { - double max_z = -std::numeric_limits::infinity(); - + double max_z = std::numeric_limits::infinity(); std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_z < iter->second->getMaxZ()) - max_z = iter->second->getMaxZ(); - } + + for (iter = _cells.begin(); iter != _cells.end(); ++iter) + max_z = std::max(max_z, iter->second->getMaxZ()); return max_z; } @@ -231,15 +309,23 @@ double Universe::getMaxZ() { */ boundaryType Universe::getMinXBoundaryType() { - double min_x = std::numeric_limits::infinity(); - boundaryType bc_x = REFLECTIVE; + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; + boundaryType bc_x = BOUNDARY_NONE; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { + /* Check if the universe contains a cell with an x-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::mapsurfs = c_iter->second->getSurfaces(); - if (min_x > iter->second->getMinX()) { - min_x = iter->second->getMinX(); - bc_x = iter->second->getMinXBoundaryType(); + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + + if (surf->getSurfaceType() == XPLANE && halfspace == +1 && + surf->getBoundaryType() != BOUNDARY_NONE) + bc_x = surf->getBoundaryType(); } } @@ -254,14 +340,23 @@ boundaryType Universe::getMinXBoundaryType() { */ boundaryType Universe::getMaxXBoundaryType() { - double max_x = -std::numeric_limits::infinity(); - boundaryType bc_x = REFLECTIVE; + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; + boundaryType bc_x = BOUNDARY_NONE; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_x < iter->second->getMaxX()) { - max_x = iter->second->getMaxX(); - bc_x = iter->second->getMaxXBoundaryType(); + /* Check if the universe contains a cell with an x-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::mapsurfs = c_iter->second->getSurfaces(); + + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + + if (surf->getSurfaceType() == XPLANE && halfspace == -1 && + surf->getBoundaryType() != BOUNDARY_NONE) + bc_x = surf->getBoundaryType(); } } @@ -276,15 +371,23 @@ boundaryType Universe::getMaxXBoundaryType() { */ boundaryType Universe::getMinYBoundaryType() { - double min_y = std::numeric_limits::infinity(); - boundaryType bc_y = REFLECTIVE; + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; + boundaryType bc_y = BOUNDARY_NONE; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { + /* Check if the universe contains a cell with an x-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::mapsurfs = c_iter->second->getSurfaces(); - if (min_y > iter->second->getMinY()) { - min_y = iter->second->getMinY(); - bc_y = iter->second->getMinYBoundaryType(); + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; + + if (surf->getSurfaceType() == YPLANE && halfspace == +1 && + surf->getBoundaryType() != BOUNDARY_NONE) + bc_y = surf->getBoundaryType(); } } @@ -299,63 +402,27 @@ boundaryType Universe::getMinYBoundaryType() { */ boundaryType Universe::getMaxYBoundaryType() { - double max_y = -std::numeric_limits::infinity(); - boundaryType bc_y = REFLECTIVE; - - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_y < iter->second->getMaxY()) { - max_y = iter->second->getMaxY(); - bc_y = iter->second->getMaxYBoundaryType(); - } - } + std::map::iterator c_iter; + std::map::iterator s_iter; + Surface* surf; + int halfspace; + boundaryType bc_y = BOUNDARY_NONE; - return bc_y; -} - - -/** - * @brief Returns the boundary conditions (VACUUM or REFLECTIVE) at the minimum - * reachable z-coordinate in the Universe. - * @return the boundary conditions at the minimum reachable z-coordinate - */ -boundaryType Universe::getMinZBoundaryType() { + /* Check if the universe contains a cell with an x-min boundary */ + for (c_iter = _cells.begin(); c_iter != _cells.end(); ++c_iter) { + std::mapsurfs = c_iter->second->getSurfaces(); - double min_z = std::numeric_limits::infinity(); - boundaryType bc_z = REFLECTIVE; + for (s_iter = surfs.begin(); s_iter != surfs.end(); ++s_iter) { + surf = s_iter->second->_surface; + halfspace = s_iter->second->_halfspace; - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - - if (min_z > iter->second->getMinZ()) { - min_z = iter->second->getMinZ(); - bc_z = iter->second->getMinZBoundaryType(); - } - } - - return bc_z; -} - - -/** - * @brief Returns the boundary conditions (VACUUM or REFLECTIVE) at the maximum - * reachable z-coordinate in the Universe. - * @return the boundary conditions at the maximum reachable z-coordinate - */ -boundaryType Universe::getMaxZBoundaryType() { - - double max_z = -std::numeric_limits::infinity(); - boundaryType bc_z = REFLECTIVE; - - std::map::iterator iter; - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - if (max_z < iter->second->getMaxZ()) { - max_z = iter->second->getMaxZ(); - bc_z = iter->second->getMaxZBoundaryType(); + if (surf->getSurfaceType() == YPLANE && halfspace == -1 && + surf->getBoundaryType() != BOUNDARY_NONE) + bc_y = surf->getBoundaryType(); } } - return bc_z; + return bc_y; } @@ -383,47 +450,6 @@ std::map Universe::getCells() const { } -/** - * @brief Returns a CellFill in this Universe. - * @param cell_id the integer the cell_id - * @return Returns the CellFill pointer. - */ -CellFill* Universe::getCellFill(int cell_id) { - - CellFill* cell = NULL; - if (_cells.find(cell_id) == _cells.end()) - log_printf(ERROR, "Unable to return Cell with ID = %d from Universe with " - "ID = %d since it does not contain this Cell", cell_id, _id); - - cell = static_cast(_cells.at(cell_id)); - if (cell->getType() != FILL) - log_printf(WARNING, "Retrieving Cell %d from Universe %d, but it " - "is not a FILL type Cell", cell->getId(), _id); - return cell; -} - - -/** - * @brief Returns a CellBasic in this Universe. - * @param cell_id the integer the cell_id - * @return Returns the CellFill pointer. - */ -CellBasic* Universe::getCellBasic(int cell_id) { - - CellBasic* cell = NULL; - if (_cells.find(cell_id) == _cells.end()) - log_printf(ERROR, "Unable to return Cell with ID = %d from Universe with " - "ID = %d since the it does not contain this Cell", cell_id, _id); - - cell = static_cast(_cells.at(cell_id)); - if (cell->getType() != MATERIAL) - log_printf(WARNING, "Retrieving Cell %d from Universe %d, but it " - "is not a MATERIAL type Cell", cell->getId(), _id); - - return cell; -} - - /** * @brief Returns the std::map of Cell IDs and Cell pointers in this Universe * at all nested Universe levels. @@ -446,6 +472,7 @@ std::map Universe::getAllCells() { return cells; } + /** * @brief Returns the std::map of all IDs and Material pointers filling this Universe. @@ -464,7 +491,7 @@ std::map Universe::getAllMaterials() { cell = iter->second; if (cell->getType() == MATERIAL) { - material = static_cast(cell)->getMaterial(); + material = cell->getFillMaterial(); materials[material->getId()] = material; } } @@ -484,12 +511,13 @@ std::map Universe::getAllUniverses() { std::map cells = getAllCells(); std::map universes; + universes[_id] = this; std::map::iterator iter; Cell* cell; /* Append all Universes containing each Cell to the map */ for (iter = cells.begin(); iter != cells.end(); ++iter) { - cell = (*iter).second; + cell = iter->second; std::map nested_universes = cell->getAllUniverses(); universes.insert(nested_universes.begin(), nested_universes.end()); } @@ -591,44 +619,71 @@ void Universe::removeCell(Cell* cell) { */ Cell* Universe::findCell(LocalCoords* coords) { - Cell* return_cell = NULL; Cell* cell; - std::map::iterator iter; + std::vector cells; + std::vector::iterator iter; /* Sets the LocalCoord type to UNIV at this level */ coords->setType(UNIV); - /* Loop over all Cells in this Universe */ - for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - cell = iter->second; + /* If the LocalCoords is populated with Universe/Cell already, we assume + * that we are looking for the location in a neighboring Cell */ + if (coords->getCell() != NULL) + cells = coords->getCell()->getNeighbors(); + + /* Add all of Universe's Cells to the back of neighbor Cells vector */ + std::transform(_cells.begin(), _cells.end(), + std::back_inserter(cells), pair_second(_cells)); - if (cell->cellContainsCoords(coords)) { + /* Loop over all Cells */ + for (iter = cells.begin(); iter != cells.end(); ++iter) { + cell = (*iter); + + if (cell->containsCoords(coords)) { /* Set the Cell on this level */ coords->setCell(cell); /* MATERIAL type Cell - lowest level, terminate search for Cell */ - if (cell->getType() == MATERIAL) { - coords->setCell(cell); - return_cell = cell; - return return_cell; - } + if (cell->getType() == MATERIAL) + return cell; /* FILL type Cell - Cell contains a Universe at a lower level * Update coords to next level and continue search */ else if (cell->getType() == FILL) { - LocalCoords* next_coords; - - if (coords->getNext() == NULL) - next_coords = new LocalCoords(coords->getX(), coords->getY()); - else - next_coords = coords->getNext(); - - CellFill* fill = static_cast(cell); - Universe* univ = fill->getFill(); + LocalCoords* next_coords = + new LocalCoords(coords->getX(), coords->getY(), coords->getZ()); + next_coords->setPhi(coords->getPhi()); + + /* Apply translation to position in the next coords */ + if (cell->isTranslated()){ + double* translation = cell->getTranslation(); + double new_x = coords->getX() + translation[0]; + double new_y = coords->getY() + translation[1]; + double new_z = coords->getZ() + translation[2]; + next_coords->setX(new_x); + next_coords->setY(new_y); + next_coords->setZ(new_z); + } + + /* Apply rotation to position and direction in the next coords */ + if (cell->isRotated()){ + double x = coords->getX(); + double y = coords->getY(); + double z = coords->getZ(); + double* matrix = cell->getRotationMatrix(); + double new_x = matrix[0] * x + matrix[1] * y + matrix[2] * z; + double new_y = matrix[3] * x + matrix[4] * y + matrix[5] * z; + double new_z = matrix[6] * x + matrix[7] * y + matrix[8] * z; + next_coords->setX(new_x); + next_coords->setY(new_y); + next_coords->setZ(new_z); + next_coords->incrementPhi(cell->getPsi() * M_PI / 180.); + } + + Universe* univ = cell->getFillUniverse(); next_coords->setUniverse(univ); - coords->setCell(cell); coords->setNext(next_coords); next_coords->setPrev(coords); @@ -640,69 +695,54 @@ Cell* Universe::findCell(LocalCoords* coords) { } } - return return_cell; + return NULL; } /** - * @brief Finds the distance to the nearest surface. - * @details Loops over all the cells within the universe and computes - * the distance to each one following the direction of the track. - * Returns distance to nearest next cell's nearest surface. - * @param point a pointer to a starting point - * @param angle the azimuthal angle of the track - * @return the distance to the nearest surface + * @brief Subdivides all of the Material-filled Cells within this Universe + * into rings and angular sectors aligned with the z-axis. + * @param max_radius the maximum allowable radius used in the subdivisions */ -double Universe::minSurfaceDist(Point* point, double angle) { +void Universe::subdivideCells(double max_radius) { + + log_printf(DEBUG, "Subdividing Cells for Universe ID=%d " + "with max radius %f", _id, max_radius); - Point min_intersection; std::map::iterator iter; - double dist; - double min_dist = INFINITY; - /* Loop over all Cells in this Universe */ for (iter = _cells.begin(); iter != _cells.end(); ++iter) { - dist = iter->second->minSurfaceDist(point, angle, &min_intersection); - min_dist = std::min(dist, min_dist); - } - return min_dist; + /* Cells filled with Materials */ + if (iter->second->getType() == MATERIAL) { + Cell* cell = iter->second; + + if (cell->getNumRings() > 0 || cell->getNumSectors() > 0) + cell->subdivideCell(max_radius); + } + + /* Cells filled with Universes */ + else { + Universe* fill = iter->second->getFillUniverse(); + if (fill->getType() == SIMPLE) + fill->subdivideCells(max_radius); + else + static_cast(fill)->subdivideCells(max_radius); + } + } } /** - * @brief Subdivides all of the Cells within this Universe into rings - * and angular sectors. + * @brief Builds collections of neighboring Cells for all Cells in this + * Universe for optimized ray tracing. */ -void Universe::subdivideCells() { - - log_printf(DEBUG, "Subdividing Cells for Universe %d", _id); - - std::map::iterator iter1; - - while (iter1 != _cells.end()) { - - for (iter1 = _cells.begin(); iter1 != _cells.end(); ++iter1) { - - if (((*iter1).second)->getType() == MATERIAL) { - CellBasic* cell = static_cast((*iter1).second); - - if (cell->getNumRings() > 0 || cell->getNumSectors() > 0) { - std::vector newcells = cell->subdivideCell(); +void Universe::buildNeighbors() { - log_printf(DEBUG, "Cell %d in Universe %d has %d subcells", - cell->getId(), _id, newcells.size()); - - std::vector::iterator iter2; - for (iter2=newcells.begin(); iter2!=newcells.end(); ++iter2) - addCell((*iter2)); - - _cells.erase(iter1); - break; - } - } - } - } + /* Loop over all of the Universe's Cells and make recursive call */ + std::map::iterator iter; + for (iter = _cells.begin(); iter != _cells.end(); ++iter) + iter->second->buildNeighbors(); } @@ -758,11 +798,11 @@ Universe* Universe::clone() { for (iter1 = _cells.begin(); iter1 != _cells.end(); ++iter1) { /* If the Cell is filled with a Material, clone it */ - if ((*iter1).second->getType() == MATERIAL) { + if (iter1->second->getType() == MATERIAL) { /* Clone the Cell */ - CellBasic* parent = static_cast((*iter1).second); - CellBasic* cell_clone = parent->clone(); + Cell* parent = static_cast(iter1->second); + Cell* cell_clone = parent->clone(); /* Add Cell clone to the list */ clone->addCell(cell_clone); @@ -785,13 +825,15 @@ Universe* Universe::clone() { Lattice::Lattice(const int id, const char* name): Universe(id, name) { _type = LATTICE; - _offset.setCoords(0.0, 0.0); + _offset.setCoords(0.0, 0.0, 0.0); /* Default width and number of Lattice cells along each dimension */ - _num_y = 0; - _num_x = 0; + _num_x = -1; + _num_y = -1; + _num_z = -1; _width_x = 0; _width_y = 0; + _width_z = 0; } @@ -800,8 +842,12 @@ Lattice::Lattice(const int id, const char* name): Universe(id, name) { */ Lattice::~Lattice() { - for (int i=0; i < _num_x; i++) - _universes.at(i).clear(); + /* Clear the triple-nested vector of Universes */ + for (int k=0; k < _num_z; k++) { + for (int j=0; j < _num_y; j++) + _universes.at(k).at(j).clear(); + _universes.at(k).clear(); + } _universes.clear(); } @@ -817,10 +863,12 @@ Lattice::~Lattice() { * and up 2 cm. * @param x the offset in the x direction * @param y the offset in the y direction + * @param z the offset in the z direction */ -void Lattice::setOffset(double x, double y) { +void Lattice::setOffset(double x, double y, double z) { _offset.setX(x); _offset.setY(y); + _offset.setZ(z); } @@ -851,6 +899,15 @@ int Lattice::getNumY() const { } +/** + * @brief Return the number of Lattice cells along the z-axis + * @return the number of Lattice cells along z + */ +int Lattice::getNumZ() const { + return _num_z; +} + + /** * @brief Return the width of the Lattice along the x-axis. * @return the width of the Lattice cells along x @@ -869,6 +926,15 @@ double Lattice::getWidthY() const { } +/** + * @brief Return the width of the Lattice along the z-axis. + * @return the width of the Lattice cells along z + */ +double Lattice::getWidthZ() const { + return _width_z; +} + + /** * @brief Returns the minimum reachable x-coordinate in the Lattice. * @return the minimum reachable x-coordinate @@ -900,7 +966,7 @@ double Lattice::getMinY() { * @brief Returns the maximum reachable y-coordinate in the Lattice. * @return the maximum reachable y-coordinate */ -double Lattice::getMaxY(){ +double Lattice::getMaxY() { return _offset.getY() + (_num_y * _width_y / 2.); } @@ -910,7 +976,7 @@ double Lattice::getMaxY(){ * @return the minimum reachable z-coordinate */ double Lattice::getMinZ() { - return -std::numeric_limits::infinity(); + return _offset.getZ() - (_num_z * _width_z / 2.); } @@ -919,7 +985,7 @@ double Lattice::getMinZ() { * @return the maximum reachable z-coordinate */ double Lattice::getMaxZ() { - return std::numeric_limits::infinity(); + return _offset.getZ() + (_num_z * _width_z / 2.); } @@ -927,28 +993,30 @@ double Lattice::getMaxZ() { * @brief Returns a pointer to the Universe within a specific Lattice cell. * @param lat_x the x index to the Lattice cell * @param lat_y the y index to the Lattice cell + * @param lat_z the z index to the Lattice cell * @return pointer to a Universe filling the Lattice cell */ -Universe* Lattice::getUniverse(int lat_x, int lat_y) const { +Universe* Lattice::getUniverse(int lat_x, int lat_y, int lat_z) const { /* Checks that lattice indices are within the bounds of the lattice */ - if (lat_x > _num_x || lat_y > _num_y) + if (lat_x >= _num_x || lat_y >= _num_y || lat_z >= _num_z || + lat_x < 0 || lat_y < 0 || lat_z < 0) log_printf(ERROR, "Cannot retrieve Universe from Lattice ID = %d: Index" - "out of bounds: Tried to access Cell x = %d, y = %d but bounds" - "are x = %d, y = %d", _id, lat_x, lat_y, _num_x, _num_y); + "out of bounds: Tried to access Cell x = %d, y = %d, " + "z = %d but bounds are x = %d, y = %d, z = %d", + _id, lat_x, lat_y, lat_z, _num_x, _num_y, _num_z); - return _universes.at(lat_y).at(lat_x).second; + return _universes.at(lat_z).at(lat_y).at(lat_x).second; } /** - * @brief Return a 2D vector of the Universes in the Lattice. - * @return 2D vector of Universes + * @brief Return a 3D vector of the Universes in the Lattice. + * @return 3D vector of Universes */ -std::vector>> - Lattice::getUniverses() const { - - return _universes; +std::vector< std::vector< std::vector< std::pair > > >* + Lattice::getUniverses() { + return &_universes; } @@ -963,11 +1031,14 @@ std::map Lattice::getUniqueUniverses() { std::map unique_universes; Universe* universe; + int univ_id; - for (int i = _num_y-1; i > -1; i--) { - for (int j = 0; j < _num_x; j++) { - universe = _universes.at(i).at(j).second; - unique_universes[universe->getId()] = universe; + for (int k = _num_z-1; k > -1; k--) { + for (int j = _num_y-1; j > -1; j--) { + for (int i = 0; i < _num_x; i++) { + universe = _universes.at(k).at(j).at(i).second; + unique_universes[universe->getId()] = universe; + } } } @@ -988,7 +1059,7 @@ std::map Lattice::getAllCells() { std::map::iterator iter; std::map nested_cells; - for (iter = unique_universes.begin(); iter != unique_universes.end(); ++iter){ + for (iter = unique_universes.begin(); iter != unique_universes.end(); ++iter) { nested_cells = iter->second->getAllCells(); cells.insert(nested_cells.begin(), nested_cells.end()); } @@ -1018,7 +1089,7 @@ std::map Lattice::getAllUniverses() { std::map::iterator iter; std::map nested_universes; - for (iter = unique_universes.begin(); iter != unique_universes.end(); ++iter){ + for (iter = unique_universes.begin(); iter != unique_universes.end(); ++iter) { nested_universes = iter->second->getAllUniverses(); all_universes.insert(nested_universes.begin(), nested_universes.end()); } @@ -1045,73 +1116,167 @@ void Lattice::setNumY(int num_y) { } +/** + * @brief Set the number of Lattice cells along the z-axis. + * @param num_z the number of Lattice cells along z + */ +void Lattice::setNumZ(int num_z) { + _num_z = num_z; +} + + /** * @brief Set the width of each Lattice cell. * @param width_x the width along the x-axis in centimeters * @param width_y the width along the y-axis in centimeters + * @param width_z the width along the z-axis in centimeters */ -void Lattice::setWidth(double width_x, double width_y) { +void Lattice::setWidth(double width_x, double width_y, double width_z) { - if (width_x <= 0 || width_y <= 0) + if (width_x <= 0 || width_y <= 0 || width_z <= 0) log_printf(ERROR, "Unable to set the width of Lattice ID = %d " - "for x = %f and y = %f since they are not positive values", - _id, width_x, width_y); + "for x = %f, y = %f, and z = %f since they are not positive " + "values", _id, width_x, width_y, _width_z); _width_x = width_x; _width_y = width_y; + _width_z = width_z; } /** * @brief Sets the array of Universe pointers filling each Lattice cell. * @details This is a helper method for SWIG to allow users to assign Universes - * to a Lattice using a 2D Python list (list of lists). An example - * how this method can be called from Python is as follows: + * to a Lattice using a 3D Python list (list of lists of lists). An + * example how this method can be called from Python is as follows: * * @code * u1 = Universe(name='Universe 1') * u2 = Universe(name='Universe 2') * u3 = Universe(name='Universe 3') - * lattice.setLatticeCells([[u1, u2, u1, u2], - * [u2, u3, u2, u3], - * [u1, u2, u1, u2], - * [u2, u3, u2, u3]]) + * lattice.setUniverses([[[u1, u2, u1, u2], + * [u2, u3, u2, u3], + * [u1, u2, u1, u2], + * [u2, u3, u2, u3]], + * [[u1, u2, u1, u2], + * [u2, u3, u2, u3], + * [u1, u2, u1, u2], + * [u2, u3, u2, u3]]]) * @endcode * - * @param num_x the number of Lattice cells along x + * @param num_z the number of Lattice cells along z * @param num_y the number of Lattice cells along y + * @param num_x the number of Lattice cells along x * @param universes the array of Universes for each Lattice cell */ -void Lattice::setUniverses(int num_x, int num_y, Universe** universes) { +void Lattice::setUniverses(int num_z, int num_y, int num_x, + Universe** universes) { - /* Clear any Universes in the Lattice (from a previous run) */ - for (int i=0; i < _num_x; i++) + std::map unique_universes = getUniqueUniverses(); + std::map::iterator iter; + + /* Remove all Universes in the Lattice */ + for (iter = unique_universes.begin(); iter != unique_universes.end(); ++iter) + removeUniverse(iter->second); + + /* Clear all Universe maps in the Lattice (from a previous run) */ + for (int i=0; i < _num_y; i++) _universes.at(i).clear(); _universes.clear(); /* Set the Lattice dimensions */ - setNumX(num_y); + setNumX(num_x); setNumY(num_y); + setNumZ(num_z); Universe* universe; /* The Lattice cells are assumed input in row major order starting from the * upper left corner. This double loop reorders the Lattice cells from the - * to start from the lower left corner */ - for (int i = 0; i < _num_y; i++) { + * start from the lower left corner */ + for (int k = 0; k < _num_z; k++) { + _universes.push_back( + std::vector< std::vector< std::pair > >()); + for (int j = 0; j < _num_y; j++) { + + _universes.at(k).push_back(std::vector< std::pair >()); + + for (int i = 0; i < _num_x; i++) { + universe = universes + [(_num_z-1-k)*_num_x*_num_y + (_num_y-1-j)*_num_x + i]; + _universes.at(k).at(j).push_back(std::pair( + universe->getId(), universe)); + } + } + } +} + - _universes.push_back(std::vector< std::pair >()); +/** + * @brief Removes all references to a Universe from the Lattice. + * @param universe the Universe to remove + */ +void Lattice::removeUniverse(Universe* universe) { - for (int j = 0; j< _num_x; j++){ - universe = universes[(_num_y-1-i)*_num_x + j]; - _universes.at(i).push_back(std::pair - (universe->getId(), universe)); + Universe* null = NULL; + + /* Clear any Universes in the Lattice (from a previous run) */ + for (int k=0; k < _num_z; k++) { + for (int j=0; j < _num_y; j++) { + for (int i=0; i < _num_x; i++) { + if (universe->getId() == getUniverse(i,j,k)->getId()) + _universes.at(k).at(j).at(i) = std::pair(-1, null); + } } } } +/** + * @brief Subdivides all of the Material-filled Cells within this Lattice + * into rings and angular sectors aligned with the z-axis. + * @param max_radius the maximum allowable radius used in the subdivisions + */ +void Lattice::subdivideCells(double max_radius) { + + log_printf(DEBUG, "Subdividing Cells for Lattice ID=%d " + "with max radius %f", _id, max_radius); + + std::map::iterator iter; + std::map universes = getUniqueUniverses(); + + /* Compute the max radius as the distance from the center to a corner + * of a Lattice cell. */ + double radius = sqrt(_width_x*_width_x/4.0 + _width_y*_width_y/4.0); + + /* If the lattice pitch is smaller than max_radius parameter, over-ride it */ + if (radius < max_radius) + max_radius = radius; + + /* Subdivide all Cells */ + for (iter = universes.begin(); iter != universes.end(); ++iter) + iter->second->subdivideCells(max_radius); +} + + +/** + * @brief Builds collections of neighboring Cells for all Cells in each + * Universe in the Lattice for optimized ray tracing. + */ +void Lattice::buildNeighbors() { + + /* Get list of unique Universes in this Lattice */ + std::map universes = getUniqueUniverses(); + + /* Loop over each Universe and make recursive call */ + std::map::iterator iter; + for (iter = universes.begin(); iter != universes.end(); ++iter) + iter->second->buildNeighbors(); +} + + + /** * @brief Checks if a Point is within the bounds of a Lattice. * @param point a pointer to the Point of interest @@ -1124,18 +1289,25 @@ bool Lattice::withinBounds(Point* point) { double bound_x_min = _offset.getX() - _num_x/2.0 * _width_x; double bound_y_max = _offset.getY() + _num_y/2.0 * _width_y; double bound_y_min = _offset.getY() - _num_y/2.0 * _width_y; + double bound_z_max = _offset.getZ() + _num_z/2.0 * _width_z; + double bound_z_min = _offset.getZ() - _num_z/2.0 * _width_z; double x = point->getX(); double y = point->getY(); + double z = point->getZ(); /* If the Point is outside the x bounds */ if (x > bound_x_max || x < bound_x_min) return false; - /* If the Point is outside the y boounds */ + /* If the Point is outside the y bounds */ else if (y > bound_y_max || y < bound_y_min) return false; + /* If the Point is outside the z bounds */ + else if (z > bound_z_max || z < bound_z_min) + return false; + /* If the Point is within the bounds */ else return true; @@ -1155,39 +1327,51 @@ Cell* Lattice::findCell(LocalCoords* coords) { /* Set the LocalCoord to be a LAT type at this level */ coords->setType(LAT); - /* Compute the x and y indices for the Lattice cell this coord is in */ + /* Compute the x, y, and z indices for the Lattice cell this coord is in */ int lat_x = getLatX(coords->getPoint()); int lat_y = getLatY(coords->getPoint()); + int lat_z = getLatZ(coords->getPoint()); + double next_x, next_y, next_z; /* If the indices are outside the bound of the Lattice */ if (lat_x < 0 || lat_x >= _num_x || - lat_y < 0 || lat_y >= _num_y) { + lat_y < 0 || lat_y >= _num_y || + lat_z < 0 || lat_z >= _num_z) { return NULL; } /* Compute local position of Point in the next level Universe */ - double nextX = coords->getX() - - (-_width_x*_num_x/2.0 + _offset.getX() + (lat_x + 0.5) * _width_x) - + getOffset()->getX(); - double nextY = coords->getY() - - (-_width_y*_num_y/2.0 + _offset.getY() + (lat_y + 0.5) * _width_y) - + getOffset()->getY(); + next_x = coords->getX() - + (-_width_x*_num_x/2.0 + _offset.getX() + (lat_x + 0.5) * _width_x) + + getOffset()->getX(); + next_y = coords->getY() - + (-_width_y*_num_y/2.0 + _offset.getY() + (lat_y + 0.5) * _width_y) + + getOffset()->getY(); + + if (_width_z == std::numeric_limits::infinity()) + next_z = coords->getZ(); + else + next_z = coords->getZ() - + (-_width_z*_num_z/2.0 + _offset.getZ() + (lat_z + 0.5) * _width_z) + + getOffset()->getZ(); /* Create a new LocalCoords object for the next level Universe */ LocalCoords* next_coords; if (coords->getNext() == NULL) - next_coords = new LocalCoords(nextX, nextY); + next_coords = new LocalCoords(next_x, next_y, next_z); else next_coords = coords->getNext(); - Universe* univ = getUniverse(lat_x, lat_y); + Universe* univ = getUniverse(lat_x, lat_y, lat_z); next_coords->setUniverse(univ); + next_coords->setPhi(coords->getPhi()); /* Set Lattice indices */ coords->setLattice(this); coords->setLatticeX(lat_x); coords->setLatticeY(lat_y); + coords->setLatticeZ(lat_z); coords->setNext(next_coords); next_coords->setPrev(coords); @@ -1202,42 +1386,38 @@ Cell* Lattice::findCell(LocalCoords* coords) { * @details Knowing that a Lattice must be cartesian, this function computes * the distance to the nearest boundary between lattice cells * in the direction of the track. - * Returns distance to nearest Lattice cell boundary. - * @param point a pointer to a starting point - * @param angle the azimuthal angle of the track + * @param coords a pointer to a localcoords object * @return the distance to the nearest Lattice cell boundary */ -double Lattice::minSurfaceDist(Point* point, double angle) { +double Lattice::minSurfaceDist(LocalCoords* coords) { - double next_x, next_y; - double dist_x, dist_y; - double dist_row, dist_col; + /* Compute the x, y, and z indices for the Lattice cell this point is in */ + int lat_x = getLatX(coords->getPoint()); + int lat_y = getLatY(coords->getPoint()); + double phi = coords->getPhi(); - /* Compute the x and y indices for the Lattice cell this point is in */ - int lat_x = getLatX(point); - int lat_y = getLatY(point); + /* Create planes representing the boundaries of the lattice cell */ + XPlane xplane(0.0); + YPlane yplane(0.0); - /* find distance to next x plane crossing */ - if (angle < M_PI / 2.0) - next_x = (lat_x + 1) * _width_x - _width_x*_num_x/2.0 + _offset.getX(); + /* Get the min distance for X PLANE */ + if (phi < M_PI_2) + xplane.setX(((lat_x+1) * _width_x - _width_x*_num_x/2.0 + _offset.getX())); else - next_x = lat_x * _width_x - _width_x*_num_x/2.0 + _offset.getX(); + xplane.setX((lat_x * _width_x - _width_x*_num_x/2.0 + _offset.getX())); - /* get distance to the nearest cell in the current row */ - next_y = point->getY() + tan(angle) * (next_x - point->getX()); - dist_x = fabs(next_x - point->getX()); - dist_y = fabs(next_y - point->getY()); - dist_row = pow(pow(dist_x, 2) + pow(dist_y, 2), 0.5); + double dist_x = xplane.getMinDistance(coords); - /* find distance to next y plane crossing */ - next_y = (lat_y + 1) * _width_y - _width_y*_num_y/2.0 + _offset.getY(); - next_x = point->getX() + (next_y - point->getY()) / tan(angle); - dist_x = fabs(next_x - point->getX()); - dist_y = fabs(next_y - point->getY()); - dist_col = pow(pow(dist_x, 2) + pow(dist_y, 2), 0.5); + /* Get the min distance for Y PLANE */ + if (phi < M_PI) + yplane.setY(((lat_y+1) * _width_y - _width_y*_num_y/2.0 + _offset.getY())); + else + yplane.setY((lat_y * _width_y - _width_y*_num_y/2.0 + _offset.getY())); + + double dist_y = yplane.getMinDistance(coords); /* return shortest distance to next lattice cell */ - return std::min(dist_row, dist_col); + return std::min(dist_x, dist_y); } @@ -1249,7 +1429,7 @@ double Lattice::minSurfaceDist(Point* point, double angle) { int Lattice::getLatX(Point* point) { /* Compute the x indice for the Lattice cell this point is in */ - int lat_x = (int)floor((point->getX() + _width_x*_num_x/2.0 - + int lat_x = (int)floor((point->getX() + _width_x*_num_x/2.0 - _offset.getX()) / _width_x); /* get the distance to the left surface */ @@ -1285,9 +1465,9 @@ int Lattice::getLatY(Point* point) { /* Check if the Point is on the Lattice boundaries and if so adjust * y Lattice cell indice */ - if (fabs(dist_to_bottom) < ON_SURFACE_THRESH) + if (fabs(dist_to_bottom) < ON_SURFACE_THRESH) lat_y = 0; - else if (fabs(dist_to_bottom - _num_y*_width_y) < ON_SURFACE_THRESH) + else if (fabs(dist_to_bottom - _num_y*_width_y) < ON_SURFACE_THRESH) lat_y = _num_y - 1; else if (lat_y < 0 || lat_y > _num_y-1) log_printf(ERROR, "Trying to get lattice y index for point that is " @@ -1295,7 +1475,39 @@ int Lattice::getLatY(Point* point) { return lat_y; } - + + +/** + * @brief Finds the Lattice cell z index that a point lies in. + * @param point a pointer to a point being evaluated. + * @return the Lattice cell z index. + */ +int Lattice::getLatZ(Point* point) { + + /* Check to see if lattice is infinite in z direction */ + if (_width_z == std::numeric_limits::infinity()) + return 0; + + /* Compute the z indice for the Lattice cell this point is in */ + int lat_z = (int)floor((point->getZ() + _width_z*_num_z/2.0 - + _offset.getZ()) / _width_z); + + /* get the distance to the bottom surface */ + double dist_to_bottom = point->getZ() + _width_z*_num_z/2.0 - _offset.getZ(); + + /* Check if the Point is on the Lattice boundaries and if so adjust + * z Lattice cell indice */ + if (fabs(dist_to_bottom) < ON_SURFACE_THRESH) + lat_z = 0; + else if (fabs(dist_to_bottom - _num_z*_width_z) < ON_SURFACE_THRESH) + lat_z = _num_z - 1; + else if (lat_z < 0 || lat_z > _num_z-1) + log_printf(ERROR, "Trying to get lattice z index for point that is " + "outside lattice bounds: %f.", point->getZ()); + + return lat_z; +} + /** * @brief Converts a Lattice's attributes to a character array representation. @@ -1309,15 +1521,19 @@ std::string Lattice::toString() { << ", name = " << _name << ", # cells along x = " << _num_x << ", # cells along y = " << _num_y + << ", # cells along z = " << _num_z << ", x width = " << _width_x - << ", y width = " << _width_y; + << ", y width = " << _width_y + << ", z width = " << _width_z; string << "\n\t\tUniverse IDs within this Lattice: "; - for (int i = _num_y-1; i > -1; i--) { - for (int j = 0; j < _num_x; j++) - string << _universes.at(i).at(j).first << ", "; - string << "\n\t\t"; + for (int k = _num_z-1; k > -1; k--) { + for (int j = _num_y-1; j > -1; j--) { + for (int i = 0; i < _num_x; i++) + string << _universes.at(k).at(j).at(i).first << ", "; + string << "\n\t\t"; + } } return string.str(); @@ -1335,9 +1551,11 @@ void Lattice::printString() { /** * @brief Finds the Lattice cell index that a point lies in. - * @details Lattice cells are numbered starting with 0 in the lower left - * corner. Lattice cell IDs in all rows then increase monotonically - * from left to right. For example, the indices for a 4 x 4 lattice: + * @details Lattice cells are numbered starting with 0 x-min/y-min/z-min corner. + * Lattice cell IDs then increase monotonically from x-min to x-max, + * y-min to y-max, and z-min to z-max. Note that values increase first + * on the x-axis, followed by the y-axis, then on the z-axis. + * For example, the indices for a 4 x 4 x 1 lattice: * 12 13 14 15 * 8 9 10 11 * 4 5 6 7 @@ -1345,64 +1563,125 @@ void Lattice::printString() { * @param point a pointer to a point being evaluated. * @return the Lattice cell index. */ -int Lattice::getLatticeCell(Point* point){ - return (getLatY(point)*_num_x + getLatX(point)); +int Lattice::getLatticeCell(Point* point) { + return getLatZ(point)*_num_x*_num_y + getLatY(point)*_num_x + getLatX(point); +} + + +/** + * @brief Finds the distance from a point to a particular lattice cell surface. + * @param cell the cell index that the point is in. + * @param point a pointer to a point being evaluated. + * @param surface a surface id to get the distance to. + * @return the distance to the lattice cell surface of interest. + */ +double Lattice::getDistanceToSurface(int cell, Point* point, int surface) { + + /* Get coordinates of the point */ + double x = point->getX(); + double y = point->getY(); + + /* Check that the surface is valid */ + if (surface < 0 || surface >= NUM_SURFACES) + log_printf(ERROR, "Unable to get the distance from point (%f, %f) to " + "lattice surface %d since there are only %d surfaces", + x, y, surface, NUM_SURFACES); + + /* Get lattice indices of the cell */ + int lat_x = cell % _num_x; + int lat_y = cell / _num_x; + + double dist; + + /* Return the distance to the corresponding lattice cell surface */ + if (surface == SURFACE_X_MIN) { + dist = lat_x*_width_x - _width_x*_num_x/2.0 + _offset.getX(); + return fabs(x - dist); + } + else if (surface == SURFACE_X_MAX) { + dist = (lat_x + 1)*_width_x - _width_x*_num_x/2.0 + _offset.getX(); + return fabs(x - dist); + } + else if (surface == SURFACE_Y_MIN) { + dist = lat_y*_width_y - _width_y*_num_y/2.0 + _offset.getY(); + return fabs(y - dist); + } + else { + dist = (lat_y + 1)*_width_y - _width_y*_num_y/2.0 + _offset.getY(); + return fabs(y - dist); + } } /** * @brief Finds the Lattice cell surface that a point lies on. * If the point is not on a surface, -1 is returned. - * @details The surface indices for a lattice cell are 0 (left), - * 1, (bottom), 2 (right), 3 (top), 4 (bottom-left corner), - * 5 (bottom-right corner), 6 (top-right corner), and - * 7 (top-left corner). The index returned takes into account - * the cell index and returns 8*cell_index + surface_index. + * @details The surface indices are defined in constants.h as they + * need to be consistent with the surface constant definitions + * used in Cmfd. The index returned takes into account + * the cell index and returns NUM_SURFACES*cell_index + surface_index. * @param cell the cell index that the point is in. * @param point a pointer to a point being evaluated. * @return the Lattice surface index. */ int Lattice::getLatticeSurface(int cell, Point* point) { + int surface = -1; + /* Get coordinates of point and cell boundaries */ double x = point->getX(); double y = point->getY(); - int lat_x = cell % _num_x; - int lat_y = cell / _num_x; - double left = lat_x*_width_x - _width_x*_num_x/2.0 + _offset.getX(); - double right = (lat_x + 1)*_width_x - _width_x*_num_x/2.0 + _offset.getX(); - double bottom = lat_y*_width_y - _width_y*_num_y/2.0 + _offset.getY(); - double top = (lat_y+1)*_width_y - _width_y*_num_y/2.0 + _offset.getY(); - int surface = -1; - - /* Check if point is on left boundary */ - if (fabs(x - left) <= ON_SURFACE_THRESH){ - /* Check if point is on bottom boundary */ - if (fabs(y - bottom) <= ON_SURFACE_THRESH) - surface = cell*8 + 4; - /* Check if point is on top boundary */ - else if (fabs(y - top) <= ON_SURFACE_THRESH) - surface = cell*8 + 7; + double z = point->getZ(); + int lat_x = (cell % (_num_x*_num_y)) % _num_x; + int lat_y = (cell % (_num_x*_num_y)) / _num_x; + int lat_z = cell / (_num_x*_num_y); + + /* Create planes representing the boundaries of the lattice cell */ + XPlane xplane(0.0); + YPlane yplane(0.0); + + /* Bools indicating if point is on each surface */ + bool on_min_x, on_max_x, on_min_y, on_max_y; + + /* Check if point is on X_MIN boundary */ + xplane.setX((lat_x*_width_x - _width_x*_num_x/2.0 + _offset.getX())); + on_min_x = xplane.isPointOnSurface(point); + + /* Check if point is on X_MAX boundary */ + xplane.setX(((lat_x + 1)*_width_x - _width_x*_num_x/2.0 + _offset.getX())); + on_max_x = xplane.isPointOnSurface(point); + + /* Check if point is on Y_MIN boundary */ + yplane.setY((lat_y*_width_y - _width_y*_num_y/2.0 + _offset.getY())); + on_min_y = yplane.isPointOnSurface(point); + + /* Check if point is on Y_MAX boundary */ + yplane.setY(((lat_y + 1)*_width_y - _width_y*_num_y/2.0 + _offset.getY())); + on_max_y = yplane.isPointOnSurface(point); + + if (on_min_x) { + if (on_min_y) + surface = SURFACE_X_MIN_Y_MIN; + else if (on_max_y) + surface = SURFACE_X_MIN_Y_MAX; else - surface = cell*8; + surface = SURFACE_X_MIN; } - /* Check if point is on right boundary */ - else if (fabs(x - right) <= ON_SURFACE_THRESH){ - /* Check if point is on bottom boundary */ - if (fabs(y - bottom) <= ON_SURFACE_THRESH) - surface = cell*8 + 5; - /* Check if point is on top boundary */ - else if (fabs(y - top) <= ON_SURFACE_THRESH) - surface = cell*8 + 6; + else if (on_max_x) { + if (on_min_y) + surface = SURFACE_X_MAX_Y_MIN; + else if (on_max_y) + surface = SURFACE_X_MAX_Y_MAX; else - surface = cell*8 + 2; + surface = SURFACE_X_MAX; } - /* Check if point is on bottom boundary */ - else if (fabs(y - bottom) <= ON_SURFACE_THRESH) - surface = cell*8 + 1; - /* Check if point is on top boundary */ - else if (fabs(y - top) <= ON_SURFACE_THRESH) - surface = cell*8 + 3; + else if (on_min_y) + surface = SURFACE_Y_MIN; + else if (on_max_y) + surface = SURFACE_Y_MAX; + + if (surface != -1) + surface = NUM_SURFACES * cell + surface; return surface; } diff --git a/src/Universe.h b/src/Universe.h index 5d377040b..a53044f1d 100644 --- a/src/Universe.h +++ b/src/Universe.h @@ -9,32 +9,29 @@ #define UNIVERSE_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "constants.h" +#include "LocalCoords.h" +#include "boundary_type.h" #include #include #include -#include "LocalCoords.h" -#include "boundary_type.h" #endif -/** Error threshold for determining how close to the boundary of a Lattice cell - * a Point needs to be to be considered on it */ -#define ON_LATTICE_CELL_THRESH 1E-12 - -/** Distance a Point is moved to cross over a Surface into a new Cell during - * Track segmentation */ -#define TINY_MOVE 1E-10 /* Forward declarations to resolve circular dependencies */ class LocalCoords; class Cell; -class CellFill; -class CellBasic; class Surface; class Material; +struct surface_halfspace; int universe_id(); void reset_universe_id(); +void maximize_universe_id(int universe_id); /** @@ -53,11 +50,11 @@ enum universeType{ /** * @class Universe Universe.h "src/Universe.h" - * @brief A Universe represents an unbounded space in the 2D xy-plane. - * @details A Universe contains cell which are bounded subspaces in the 2D - * xy-plane and which together form the Universe. Universes allow - * for complex, repeating (i.e. lattices) geometries to be simply - * represented with as few data structures as possible. + * @brief A Universe represents an unbounded space in the 3D. + * @details A Universe contains cell which are bounded subspaces in 3D which + * together form the Universe. Universes allow for complex, repeating + * (i.e. lattices) geometries to be simply represented with as few data + * structures as possible. */ class Universe { @@ -78,7 +75,7 @@ class Universe { /** The type of Universe (ie, SIMPLE or LATTICE) */ universeType _type; - /** A collection of Cell IDs and Cell pointers */ + /** A collection of Cell IDs and Cell pointers in this Universe */ std::map _cells; /** A boolean representing whether or not this Universe contains a Material @@ -87,7 +84,7 @@ class Universe { public: - Universe(const int id=0, const char* name=""); + Universe(const int id=-1, const char* name=""); virtual ~Universe(); int getUid() const; int getId() const; @@ -104,13 +101,9 @@ class Universe { boundaryType getMaxXBoundaryType(); boundaryType getMinYBoundaryType(); boundaryType getMaxYBoundaryType(); - boundaryType getMinZBoundaryType(); - boundaryType getMaxZBoundaryType(); Cell* getCell(int cell_id); std::map getCells() const; - CellFill* getCellFill(int cell_id); - CellBasic* getCellBasic(int cell_id); std::map getAllCells(); std::map getAllMaterials(); std::map getAllUniverses(); @@ -123,10 +116,10 @@ class Universe { Cell* findCell(LocalCoords* coords); void setFissionability(bool fissionable); - double minSurfaceDist(Point* point, double angle); - void subdivideCells(); + void subdivideCells(double max_radius=INFINITY); + void buildNeighbors(); - std::string toString(); + virtual std::string toString(); void printString(); Universe* clone(); @@ -135,7 +128,7 @@ class Universe { /** * @class Lattice Universe.h "src/Universe.h" - * @brief Represents a repeating 2D Lattice of Universes. + * @brief Represents a repeating 3D Lattice of Universes. */ class Lattice: public Universe { @@ -147,29 +140,38 @@ class Lattice: public Universe { /** The number of Lattice cells along the y-axis */ int _num_y; + /** The number of Lattice cells along the z-axis */ + int _num_z; + /** The width of each Lattice cell (cm) along the x-axis */ double _width_x; /** The width of each Lattice cell (cm) along the y-axis */ double _width_y; + /** The width of each Lattice cell (cm) along the z-axis */ + double _width_z; + /** The coordinates of the offset for the Universe */ Point _offset; /** A container of Universes ? */ - std::vector< std::vector< std::pair > > _universes; + std::vector< std::vector< std::vector< std::pair > > > + _universes; public: - Lattice(const int id=0, const char* name=""); + Lattice(const int id=-1, const char* name=""); virtual ~Lattice(); - void setOffset(double x, double y); + void setOffset(double x, double y, double z); Point* getOffset(); int getNumX() const; int getNumY() const; + int getNumZ() const; double getWidthX() const; double getWidthY() const; + double getWidthZ() const; double getMinX(); double getMaxX(); double getMinY(); @@ -177,30 +179,67 @@ class Lattice: public Universe { double getMinZ(); double getMaxZ(); - Universe* getUniverse(int lat_x, int lat_y) const; - std::vector< std::vector< std::pair > > getUniverses() const; + Universe* getUniverse(int lat_x, int lat_y, int lat_z) const; + std::vector< std::vector< std::vector< std::pair > > >* + getUniverses(); std::map getUniqueUniverses(); std::map getAllCells(); std::map getAllUniverses(); void setNumX(int num_x); void setNumY(int num_y); - void setWidth(double width_x, double width_y); - void setUniverses(int num_x, int num_y, Universe** universes); + void setNumZ(int num_z); + void setWidth(double width_x, double width_y, + double width_z=std::numeric_limits::infinity()); + void setUniverses(int num_z, int num_y, int num_x, Universe** universes); + void removeUniverse(Universe* universe); + void subdivideCells(double max_radius=INFINITY); + void buildNeighbors(); bool withinBounds(Point* point); Cell* findCell(LocalCoords* coords); - double minSurfaceDist(Point* point, double angle); + double minSurfaceDist(LocalCoords* coords); int getLatX(Point* point); int getLatY(Point* point); + int getLatZ(Point* point); int getLatticeCell(Point* point); int getLatticeSurface(int cell, Point* point); + double getDistanceToSurface(int cell, Point* point, int surface); std::string toString(); void printString(); }; -#endif /* UNIVERSE_H_ */ + +/** + * @brief A helper struct for the Universe::findCell() method. + * @details This is used to insert a Universe's Cells to the back of a vector + * of neighbor Cells in Universe::findCell() routine. This works in + * symbiosis with the pair_second method template defined below. + */ +template +struct second_t { + typename tPair::second_type operator()(const tPair& p) const { + return p.second; + } +}; + + +/** + * @brief A helper routine for the Universe::findCell() method. + * @details This is used to insert a Universe's Cells to the back of a vector + * of neighbor Cells in Universe::findCell() routine. This works in + * symbiosis with the second_t struct template defined above. + * @param map a std::map iterator + * @return the second element in the iterator (e.g., map value) + */ +template +second_t pair_second(const tMap& map) { + return second_t(); +} + + +#endif /* UNIVERSE_H_ */ diff --git a/src/Vector.cpp b/src/Vector.cpp new file mode 100644 index 000000000..3574bb37b --- /dev/null +++ b/src/Vector.cpp @@ -0,0 +1,354 @@ +#include "Vector.h" + +/** + * @brief Constructor initializes Vector object as a floating point array + * and sets the vector dimensions. + * @detail The vector is ordered by cell (as opposed to by group) on the + * outside to be consistent with the Matrix object. Locks are used to + * make the vector object thread-safe against concurrent writes the + * same value. One lock locks out multiple rows of + * the vector at a time representing multiple groups in the same cell. + * @param cell_locks OpenMP locks for atomic cell operations. + * @param num_x The number of cells in the x direction. + * @param num_y The number of cells in the y direction. + * @param num_groups The number of energy groups in each cell. + */ +Vector::Vector(omp_lock_t* cell_locks, int num_x, int num_y, int num_groups) { + + setNumX(num_x); + setNumY(num_y); + setNumGroups(num_groups); + _num_rows = _num_x*_num_y*_num_groups; + + /* Initialize array and set all to 0.0 */ + _array = new FP_PRECISION[_num_rows]; + setAll(0.0); + + /* Set OpenMP locks for each Vector cell */ + if (cell_locks == NULL) + log_printf(ERROR, "Unable to create a Vector without an array of cell " + "locks"); + + _cell_locks = cell_locks; +} + + +/** + * @brief Destructor deletes the arrays used to represent the vector. + */ +Vector::~Vector() { + + if (_array != NULL) + delete [] _array; +} + + +/** + * @brief Increment a value in the vector. + * @detail This method takes a cell and group and floating + * point value. The cell and group are used to compute the + * row and column in the vector. If a value exists for the row, + * the value is incremented by val; otherwise, it is set to val. + * @param cell The cell location. + * @param group The group location. + * @param val The value used to increment the row location. + */ +void Vector::incrementValue(int cell, int group, FP_PRECISION val) { + + if (cell >= _num_x*_num_y || cell < 0) + log_printf(ERROR, "Unable to increment Vector value for cell %d" + " which is not between 0 and %d", cell, _num_x*_num_y-1); + else if (group >= _num_groups || group < 0) + log_printf(ERROR, "Unable to increment Vector value for group %d" + " which is not between 0 and %d", group, _num_groups-1); + + /* Atomically increment the Vector value from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell]); + + _array[cell*_num_groups + group] += val; + + /* Release Vector cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell]); +} + + +void Vector::setAll(FP_PRECISION val) { + std::fill_n(_array, _num_rows, val); +} + + +/** + * @brief Increment values in the vector. + * @detail This method takes a cell, first group, last group, and floating + * point value. The cell and groups are used to compute the + * rows in the vector. If values exist for the rows, + * the values are incremented by vals; otherwise, they are set. + * @param cell The cell location. + * @param group_first The first group location to increment. + * @param group_last The last group location to increment. + * @param vals The values used to increment the row locations. + */ +void Vector::incrementValues(int cell, int group_first, int group_last, + FP_PRECISION* vals) { + + if (cell >= _num_x*_num_y || cell < 0) + log_printf(ERROR, "Unable to increment Vector values for cell %d" + " which is not between 0 and %d", cell, _num_x*_num_y-1); + else if (group_first >= _num_groups || group_first < 0) + log_printf(ERROR, "Unable to increment Vector values for first group %d" + " which is not between 0 and %d", group_first, _num_groups-1); + else if (group_last >= _num_groups || group_last < 0) + log_printf(ERROR, "Unable to increment Vector values for last group %d" + " which is not between 0 and %d", group_last, _num_groups-1); + else if (group_first > group_last) + log_printf(ERROR, "Unable to increment Vector values with first group %d" + " greater than last group %d", group_first, group_last); + + /* Atomically increment the Vector values from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell]); + +#pragma omp simd + for (int g=group_first; g <= group_last; g++) + _array[cell*_num_groups + g] += vals[g-group_first]; + + /* Release Vector cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell]); +} + + +/** + * @brief Set a value in the vector. + * @detail This method takes a cell and group and floating + * point value. The cell and group are used to compute the + * row and column in the vector. The location of the corresponding + * row is set to val. + * @param cell The cell location. + * @param group The group location. + * @param val The value used to set the row location. + */ +void Vector::setValue(int cell, int group, FP_PRECISION val) { + + if (cell >= _num_x*_num_y || cell < 0) + log_printf(ERROR, "Unable to set Vector value for cell %d" + " which is not between 0 and %d", cell, _num_x*_num_y-1); + else if (group >= _num_groups || group < 0) + log_printf(ERROR, "Unable to set Vector value for group %d" + " which is not between 0 and %d", group, _num_groups-1); + + /* Atomically set the Vector value from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell]); + + _array[cell*_num_groups + group] = val; + + /* Release Vector cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell]); +} + + +/** + * @brief Set values in the vector. + * @detail This method takes a cell, first group, last group, and floating + * point value. The cell and groups are used to compute the + * rows in the vector. If a values exist for the rows, + * the values are overwritten. + * @param cell The cell location. + * @param group_first The first group location to set. + * @param group_last The last group location to set. + * @param vals The values used to set the row locations. + */ +void Vector::setValues(int cell, int group_first, int group_last, + FP_PRECISION* vals) { + + if (cell >= _num_x*_num_y || cell < 0) + log_printf(ERROR, "Unable to set Vector values for cell %d" + " which is not between 0 and %d", cell, _num_x*_num_y-1); + else if (group_first >= _num_groups || group_first < 0) + log_printf(ERROR, "Unable to set Vector values for first group %d" + " which is not between 0 and %d", group_first, _num_groups-1); + else if (group_last >= _num_groups || group_last < 0) + log_printf(ERROR, "Unable to set Vector values for last group %d" + " which is not between 0 and %d", group_last, _num_groups-1); + else if (group_first > group_last) + log_printf(ERROR, "Unable to set Vector values with first group %d" + " greater than last group %d", group_first, group_last); + + /* Atomically set the Vector values from the + * temporary array using mutual exclusion locks */ + omp_set_lock(&_cell_locks[cell]); + +#pragma omp simd + for (int g=group_first; g <= group_last; g++) + _array[cell*_num_groups + g] = vals[g-group_first]; + + /* Release Vector cell mutual exclusion lock */ + omp_unset_lock(&_cell_locks[cell]); +} + + +/** + * @brief Clear all values in the vector. + */ +void Vector::clear() { + setAll(0.0); +} + + +/** + * @brief Scales the vector by a given value. + * @param val The value to scale the vector by. + */ +void Vector::scaleByValue(FP_PRECISION val) { + +#pragma omp parallel for schedule(guided) + for (int i=0; i < _num_rows; i++) + _array[i] *= val; +} + + +/** + * @brief Print the vector object to the log file. + */ +void Vector::printString() { + + std::stringstream string; + string << std::setprecision(6); + + string << std::endl; + string << "Vector" << std::endl; + string << " Num rows: " << _num_rows << std::endl; + + for (int row=0; row < _num_rows; row++) + string << " ( " << row << "): " << _array[row] << std::endl; + + string << "End Vector" << std::endl; + + log_printf(NORMAL, string.str().c_str()); +} + + +/** + * @brief Copy the values from the current vector to an input vector. + * @param vector The vector to copy values to. + */ +void Vector::copyTo(Vector* vector) { + std::copy(_array, _array + _num_rows, vector->getArray()); +} + + +/** + * @brief Get a value at location described by a given cell and + * group index. + * @param cell The cell location index. + * @param group The group location index. + */ +FP_PRECISION Vector::getValue(int cell, int group) { + return _array[cell*_num_groups + group]; +} + + +/** + * @brief Get the array describing the vector. + * @return The array describing the vector. + */ +FP_PRECISION* Vector::getArray() { + return _array; +} + + +/** + * @brief Get the number of cells in the x dimension. + * @return The number of cells in the x dimension. + */ +int Vector::getNumX() { + return _num_x; +} + + +/** + * @brief Get the number of cells in the y dimension. + * @return The number of cells in the y dimension. + */ +int Vector::getNumY() { + return _num_y; +} + + +/** + * @brief Get the number of groups in each cell. + * @return The number of groups in each cell. + */ +int Vector::getNumGroups() { + return _num_groups; +} + + +/** + * @brief Get the number of rows in the vector. + * @return The number of rows in the vector. + */ +int Vector::getNumRows() { + return _num_rows; +} + + +/** + * @brief Get the sum of all the values in the vector. + * @return The sum of all the values in the vector. + */ +FP_PRECISION Vector::getSum() { + return pairwise_sum(_array, _num_rows); +} + + +/** + * @brief Set the number of cells in the x dimension. + * @param num_x The number of cells in the x dimension. + */ +void Vector::setNumX(int num_x) { + + if (num_x < 1) + log_printf(ERROR, "Unable to set Vector num x to non-positive value %d", + num_x); + + _num_x = num_x; +} + + +/** + * @brief Set the number of cells in the y dimension. + * @param num_y The number of cells in the y dimension. + */ +void Vector::setNumY(int num_y) { + + if (num_y < 1) + log_printf(ERROR, "Unable to set Vector num y to non-positive value %d", + num_y); + + _num_y = num_y; +} + + +/** + * @brief Set the number of groups in each cell. + * @param num_groups The number of groups in each cell. + */ +void Vector::setNumGroups(int num_groups) { + + if (num_groups < 1) + log_printf(ERROR, "Unable to set Vector num groups to non-positive value" + " %d", num_groups); + + _num_groups = num_groups; +} + + +/** + * @brief Return the array of cell locks for atomic cell operations. + * @return an array of cell locks + */ +omp_lock_t* Vector::getCellLocks() { + return _cell_locks; +} diff --git a/src/Vector.h b/src/Vector.h new file mode 100644 index 000000000..a98c074b9 --- /dev/null +++ b/src/Vector.h @@ -0,0 +1,77 @@ +/** + * @file Vector.h + * @brief A vector object + * @date May 5, 2015 + * @author Samuel Shaner, MIT, Course 22 (shaner@mit.edu) + */ + +#ifndef VECTOR_H_ +#define VECTOR_H_ + + +#ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "pairwise_sum.h" +#endif + + +class Vector { + +private: + + /** An array representing the vector */ + FP_PRECISION* _array; + int _num_rows; + int _num_x; + int _num_y; + int _num_groups; + + /** OpenMP mutual exclusion locks for atomic cell updates */ + omp_lock_t* _cell_locks; + + void setNumX(int num_x); + void setNumY(int num_y); + void setNumGroups(int num_groups); + +public: + Vector(omp_lock_t* cell_locks, int num_x=1, int num_y=1, int num_groups=1); + virtual ~Vector(); + + /* Worker functions */ + void incrementValue(int cell, int group, FP_PRECISION val); + void incrementValues(int cell, int group_start, int group_end, + FP_PRECISION* vals); + void clear(); + void scaleByValue(FP_PRECISION val); + void printString(); + void copyTo(Vector* vector); + + /* Getter functions */ + FP_PRECISION getValue(int cell, int group); + FP_PRECISION* getArray(); + int getNumX(); + int getNumY(); + int getNumGroups(); + int getNumRows(); + FP_PRECISION getSum(); + omp_lock_t* getCellLocks(); + + /* Setter functions */ + void setValue(int cell, int group, FP_PRECISION val); + void setValues(int cell, int group_start, int group_end, FP_PRECISION* vals); + void setAll(FP_PRECISION val); +}; + +#endif /* VECTOR_H_ */ diff --git a/src/VectorizedSolver.cpp b/src/VectorizedSolver.cpp index 74c89a579..7997cd148 100644 --- a/src/VectorizedSolver.cpp +++ b/src/VectorizedSolver.cpp @@ -2,30 +2,19 @@ /** - * @brief Constructor initializes empty arrays for source, flux, etc. - * @details The construcor retrieves the number of energy groups and FSRs - * and azimuthal angles from the Geometry and TrackGenerator if - * they were provided by the user, and uses this to initialize - * empty arrays for the FSRs, boundary angular fluxes, FSR scalar - * fluxes, FSR sources and FSR fission rates. The constructor - * initalizes the number of threads to a default of 1. - * @param geometry an optional pointer to the Geometry object + * @brief Constructor initializes NULL arrays for source, flux, etc. * @param track_generator an optional pointer to a TrackGenerator object */ -VectorizedSolver::VectorizedSolver(Geometry* geometry, - TrackGenerator* track_generator) : - CPUSolver(geometry, track_generator) { +VectorizedSolver::VectorizedSolver(TrackGenerator* track_generator) : + CPUSolver(track_generator) { if (_cmfd != NULL) - log_printf(ERROR, "The VectorizedSolver is not set up to use CMFD"); + log_printf(ERROR, "The VectorizedSolver is not yet configured for CMFD"); _delta_psi = NULL; _thread_taus = NULL; _thread_exponentials = NULL; - if (geometry != NULL) - setGeometry(geometry); - if (track_generator != NULL) setTrackGenerator(track_generator); @@ -44,29 +33,14 @@ VectorizedSolver::~VectorizedSolver() { _boundary_flux = NULL; } - if (_boundary_leakage != NULL) { - MM_FREE(_boundary_leakage); - _boundary_leakage = NULL; - } - - if (_scalar_flux != NULL) { + if (_scalar_flux != NULL && !_user_fluxes) { MM_FREE(_scalar_flux); _scalar_flux = NULL; } - if (_fission_sources != NULL) { - MM_FREE(_fission_sources); - _fission_sources = NULL; - } - - if (_scatter_sources != NULL) { - MM_FREE(_scatter_sources); - _scatter_sources = NULL; - } - - if (_old_fission_sources != NULL) { - MM_FREE(_old_fission_sources); - _old_fission_sources = NULL; + if (_old_scalar_flux != NULL) { + MM_FREE(_old_scalar_flux); + _old_scalar_flux = NULL; } if (_reduced_sources != NULL) { @@ -74,6 +48,11 @@ VectorizedSolver::~VectorizedSolver() { _reduced_sources = NULL; } + if (_fixed_sources != NULL) { + MM_FREE(_fixed_sources); + _fixed_sources = NULL; + } + if (_delta_psi != NULL) { MM_FREE(_delta_psi); _delta_psi = NULL; @@ -88,7 +67,6 @@ VectorizedSolver::~VectorizedSolver() { MM_FREE(_thread_exponentials); _thread_exponentials = NULL; } - } @@ -106,8 +84,7 @@ int VectorizedSolver::getNumVectorWidths() { /** - * @brief Sets the Geometry for the Solver and aligns all Material - * cross-section data for SIMD vector instructions. + * @brief Sets the Geometry for the Solver. * @param geometry a pointer to the Geometry */ void VectorizedSolver::setGeometry(Geometry* geometry) { @@ -120,25 +97,16 @@ void VectorizedSolver::setGeometry(Geometry* geometry) { /* Reset the number of energy groups by rounding up for the number * of vector widths needed to accomodate the energy groups */ _num_groups = _num_vector_lengths * VEC_LENGTH; - _polar_times_groups = _num_groups * _num_polar; - - std::map materials = geometry->getMaterials(); - std::map::iterator iter; - - /* Iterate over each Material and replace its cross-section with a new one - * array that is a multiple of VEC_LENGTH long */ - for (iter=materials.begin(); iter != materials.end(); ++iter) - (*iter).second->alignData(); } /** * @brief Allocates memory for the exponential linear interpolation table. */ -void VectorizedSolver::buildExpInterpTable() { +void VectorizedSolver::initializeExpEvaluator() { - CPUSolver::buildExpInterpTable(); + CPUSolver::initializeExpEvaluator(); /* Deallocates memory for the exponentials if it was allocated for a * previous simulation */ @@ -154,10 +122,26 @@ void VectorizedSolver::buildExpInterpTable() { } +/** + * @brief Aligns all Material cross-section data for SIMD vector instructions. + * @param mode the solution type (FORWARD or ADJOINT) + */ +void VectorizedSolver::initializeMaterials(solverMode mode) { + /* Build fission matrices */ + Solver::initializeMaterials(mode); + + std::map materials = _geometry->getAllMaterials(); + std::map::iterator m_iter; + + /* Iterate over each Material and replace its cross-section with a new one + * array that is a multiple of VEC_LENGTH long */ + for (m_iter = materials.begin(); m_iter != materials.end(); ++m_iter) + m_iter->second->alignData(); +} + /** - * @brief Allocates memory for Track boundary angular flux and leakage and - * FSR scalar flux arrays. + * @brief Allocates memory for Track boundary angular and FSR scalar fluxes. * @details Deletes memory for old flux arrays if they were allocated for a * previous simulation. */ @@ -167,12 +151,12 @@ void VectorizedSolver::initializeFluxArrays() { if (_boundary_flux != NULL) MM_FREE(_boundary_flux); - if (_boundary_leakage != NULL) - MM_FREE(_boundary_leakage); - - if (_scalar_flux != NULL) + if (_scalar_flux != NULL && !_user_fluxes) MM_FREE(_scalar_flux); + if (_old_scalar_flux != NULL) + MM_FREE(_old_scalar_flux); + if (_delta_psi != NULL) MM_FREE(_delta_psi); @@ -187,10 +171,10 @@ void VectorizedSolver::initializeFluxArrays() { size = 2 * _tot_num_tracks * _num_groups * _num_polar; size *= sizeof(FP_PRECISION); _boundary_flux = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - _boundary_leakage = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); size = _num_FSRs * _num_groups * sizeof(FP_PRECISION); _scalar_flux = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); + _old_scalar_flux = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); size = _num_threads * _num_groups * sizeof(FP_PRECISION); _delta_psi = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); @@ -199,8 +183,7 @@ void VectorizedSolver::initializeFluxArrays() { _thread_taus = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the VectorizedSolver's " - "fluxes. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for the fluxes"); } } @@ -213,43 +196,81 @@ void VectorizedSolver::initializeFluxArrays() { void VectorizedSolver::initializeSourceArrays() { /* Delete old sources arrays if they exist */ - if (_fission_sources != NULL) - MM_FREE(_fission_sources); - - if (_scatter_sources != NULL) - MM_FREE(_scatter_sources); - - if (_old_fission_sources != NULL) - MM_FREE(_old_fission_sources); - if (_reduced_sources != NULL) MM_FREE(_reduced_sources); + if (_fixed_sources != NULL) + MM_FREE(_fixed_sources); - if (_source_residuals != NULL) - MM_FREE(_source_residuals); - - int size; + int size = _num_FSRs * _num_groups * sizeof(FP_PRECISION); /* Allocate aligned memory for all source arrays */ try{ - size = _num_FSRs * _num_groups * sizeof(FP_PRECISION); - _fission_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); _reduced_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - - size = _num_threads * _num_groups * sizeof(FP_PRECISION); - _scatter_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - - size = _num_FSRs * sizeof(FP_PRECISION); - _old_fission_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - _source_residuals = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); + _fixed_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the VectorizedSolver's " - "FSR sources array. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for FSR sources"); + } + + /* Initialize fixed sources to zero */ + memset(_fixed_sources, 0.0, size); + + /* Populate fixed source array with any user-defined sources */ + initializeFixedSources(); +} + + +/** + * @brief Populates array of fixed sources assigned by FSR. + */ +void VectorizedSolver::initializeFixedSources() { + + Solver::initializeFixedSources(); + + int fsr_id, group; + std::pair fsr_group_key; + std::map< std::pair, FP_PRECISION >::iterator fsr_iter; + + /* Populate fixed source array with any user-defined sources */ + for (fsr_iter = _fix_src_FSR_map.begin(); + fsr_iter != _fix_src_FSR_map.end(); ++fsr_iter) { + + /* Get the FSR with an assigned fixed source */ + fsr_group_key = fsr_iter->first; + fsr_id = fsr_group_key.first; + group = fsr_group_key.second; + + if (group <= 0 || group > _num_groups) + log_printf(ERROR,"Unable to use fixed source for group %d in " + "a %d energy group problem", group, _num_groups); + + if (fsr_id < 0 || fsr_id >= _num_FSRs) + log_printf(ERROR,"Unable to use fixed source for FSR %d with only " + "%d FSRs in the geometry", fsr_id, _num_FSRs); + + _fixed_sources(fsr_id, group-1) = _fix_src_FSR_map[fsr_group_key]; } } +/** + * @brief Initializes the FSR volumes and Materials array. + */ +void VectorizedSolver::initializeFSRs() { + + CPUSolver::initializeFSRs(); + + /* Compute the number of SIMD vector widths needed to fit energy groups */ + _num_vector_lengths = (_num_groups / VEC_LENGTH) + 1; + + /* Reset the number of energy groups by rounding up for the number + * of vector widths needed to accomodate the energy groups */ + _num_groups = _num_vector_lengths * VEC_LENGTH; + _polar_times_groups = _num_groups * _num_polar; +} + + + /** * @brief Normalizes all FSR scalar fluxes and Track boundary angular * fluxes to the total fission source (times \f$ \nu \f$). @@ -261,9 +282,11 @@ void VectorizedSolver::normalizeFluxes() { FP_PRECISION tot_fission_source; FP_PRECISION norm_factor; + int size = _num_FSRs * _num_groups * sizeof(FP_PRECISION); + FP_PRECISION* fission_sources = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); + /* Compute total fission source for each FSR, energy group */ - #pragma omp parallel for private(volume, nu_sigma_f) \ - reduction(+:tot_fission_source) schedule(guided) +#pragma omp parallel for private(volume, nu_sigma_f) schedule(guided) for (int r=0; r < _num_FSRs; r++) { /* Get pointers to important data structures */ @@ -274,24 +297,27 @@ void VectorizedSolver::normalizeFluxes() { for (int v=0; v < _num_vector_lengths; v++) { /* Loop over each energy group within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - _fission_sources(r,e) = nu_sigma_f[e] * _scalar_flux(r,e); + fission_sources(r,e) = nu_sigma_f[e] * _scalar_flux(r,e); /* Loop over each energy group within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - _fission_sources(r,e) *= volume; + fission_sources(r,e) *= volume; } } /* Compute the total fission source */ - int size = _num_FSRs * _num_groups; - #ifdef SINGLE - tot_fission_source = cblas_sasum(size, _fission_sources, 1); - #else - tot_fission_source = cblas_dasum(size, _fission_sources, 1); - #endif + size = _num_FSRs * _num_groups; +#ifdef SINGLE + tot_fission_source = cblas_sasum(size, fission_sources, 1); +#else + tot_fission_source = cblas_dasum(size, fission_sources, 1); +#endif + + /* Deallocate memory for fission source array */ + MM_FREE(fission_sources); /* Compute the normalization factor */ norm_factor = 1.0 / tot_fission_source; @@ -300,141 +326,93 @@ void VectorizedSolver::normalizeFluxes() { tot_fission_source, norm_factor); /* Normalize the FSR scalar fluxes */ - #ifdef SINGLE +#ifdef SINGLE cblas_sscal(size, norm_factor, _scalar_flux, 1); - #else + cblas_sscal(size, norm_factor, _old_scalar_flux, 1); +#else cblas_dscal(size, norm_factor, _scalar_flux, 1); - #endif + cblas_dscal(size, norm_factor, _old_scalar_flux, 1); +#endif /* Normalize the Track angular boundary fluxes */ size = 2 * _tot_num_tracks * _num_polar * _num_groups; - #ifdef SINGLE +#ifdef SINGLE cblas_sscal(size, norm_factor, _boundary_flux, 1); - #else +#else cblas_dscal(size, norm_factor, _boundary_flux, 1); - #endif +#endif return; } /** - * @brief Computes the total source (fission and scattering) in each FSR. + * @brief Computes the total source (fission, scattering, fixed) in each FSR. * @details This method computes the total source in each FSR based on - * this iteration's current approximation to the scalar flux. A - * residual for the source with respect to the source compute on - * the previous iteration is computed and returned. The residual - * is determined as follows: - * \f$ res = \sqrt{\frac{\displaystyle\sum \displaystyle\sum - * \left(\frac{Q^i - Q^{i-1}{Q^i}\right)^2}{# FSRs}}} $\f - * - * @return the residual between this source and the previous source + * this iteration's current approximation to the scalar flux. */ -FP_PRECISION VectorizedSolver::computeFSRSources() { - - int tid; - FP_PRECISION scatter_source; - FP_PRECISION fission_source; - FP_PRECISION fsr_fission_source; - FP_PRECISION* nu_sigma_f; - FP_PRECISION* sigma_s; - FP_PRECISION* sigma_t; - FP_PRECISION* chi; - Material* material; - - FP_PRECISION source_residual = 0.0; - - FP_PRECISION inverse_k_eff = 1.0 / _k_eff; - - /* For all FSRs, find the source */ - #pragma omp parallel for private(material, nu_sigma_f, chi, \ - sigma_s, sigma_t, fission_source, scatter_source, fsr_fission_source) \ - schedule(guided) - for (int r=0; r < _num_FSRs; r++) { - - tid = omp_get_thread_num(); - material = _FSR_materials[r]; - nu_sigma_f = material->getNuSigmaF(); - chi = material->getChi(); - sigma_s = material->getSigmaS(); - sigma_t = material->getSigmaT(); - - /* Initialize the source residual to zero */ - _source_residuals[r] = 0.; - fsr_fission_source = 0.0; - - /* Compute fission source for each group */ - if (material->isFissionable()) { - for (int v=0; v < _num_vector_lengths; v++) { - - /* Compute fission source for each group */ - #pragma simd vectorlength(VEC_LENGTH) - for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - _fission_sources(r,e) = _scalar_flux(r,e) * nu_sigma_f[e]; - } - - #ifdef SINGLE - fission_source = cblas_sasum(_num_groups, &_fission_sources(r,0),1); - #else - fission_source = cblas_dasum(_num_groups, &_fission_sources(r,0),1); - #endif +void VectorizedSolver::computeFSRSources() { - fission_source *= inverse_k_eff; - } - - else - fission_source = 0.0; - - /* Compute total scattering source for group G */ - for (int G=0; G < _num_groups; G++) { - scatter_source = 0; - - for (int v=0; v < _num_vector_lengths; v++) { - - #pragma simd vectorlength(VEC_LENGTH) - for (int g=v*VEC_LENGTH; g < (v+1)*VEC_LENGTH; g++) - _scatter_sources(tid,g) = sigma_s[G*_num_groups+g] * - _scalar_flux(r,g); +#pragma omp parallel default(none) + { + int tid; + Material* material; + FP_PRECISION* sigma_t; + FP_PRECISION* sigma_s; + FP_PRECISION* fiss_mat; + FP_PRECISION scatter_source, fission_source; + + int size = _num_groups * sizeof(FP_PRECISION); + FP_PRECISION* fission_sources = + (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); + FP_PRECISION* scatter_sources = + (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); + + /* For all FSRs, find the source */ +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { + + tid = omp_get_thread_num(); + material = _FSR_materials[r]; + sigma_t = material->getSigmaT(); + sigma_s = material->getSigmaS(); + fiss_mat = material->getFissionMatrix(); + + /* Compute scatter + fission source for group G */ + for (int G=0; G < _num_groups; G++) { + for (int v=0; v < _num_vector_lengths; v++) { + +#pragma simd vectorlength(VEC_LENGTH) + for (int g=v*VEC_LENGTH; g < (v+1)*VEC_LENGTH; g++) { + scatter_sources[g] = sigma_s[G*_num_groups+g] * _scalar_flux(r,g); + fission_sources[g] = fiss_mat[G*_num_groups+g] * _scalar_flux(r,g); + } + } + +#ifdef SINGLE + scatter_source=cblas_sasum(_num_groups, scatter_sources, 1); + fission_source=cblas_sasum(_num_groups, fission_sources, 1); +#else + scatter_source=cblas_dasum(_num_groups, scatter_sources, 1); + fission_source=cblas_dasum(_num_groups, fission_sources, 1); +#endif + + fission_source /= _k_eff; + + /* Compute total (scatter+fission+fixed) reduced source */ + _reduced_sources(r,G) = _fixed_sources(r,G); + _reduced_sources(r,G) += scatter_source + fission_source; + _reduced_sources(r,G) *= ONE_OVER_FOUR_PI / sigma_t[G]; } - - #ifdef SINGLE - scatter_source=cblas_sasum(_num_groups,&_scatter_sources(tid,0),1); - #else - scatter_source=cblas_dasum(_num_groups,&_scatter_sources(tid,0),1); - #endif - - /* Set the total source for FSR r in group G */ - fsr_fission_source += fission_source * chi[G]; - - _reduced_sources(r,G) = (fission_source * chi[G] + scatter_source) - * ONE_OVER_FOUR_PI / sigma_t[G]; } - /* Compute the norm of residual of the source in the FSR */ - if (fsr_fission_source > 0.0) - _source_residuals[r] = pow((fsr_fission_source - _old_fission_sources[r]) - / fsr_fission_source, 2); - - /* Update the old source */ - _old_fission_sources[r] = fsr_fission_source; + MM_FREE(fission_sources); + MM_FREE(scatter_sources); } - - /* Sum up the residuals from each group and in each FSR */ - #ifdef SINGLE - source_residual = cblas_sasum(_num_FSRs,_source_residuals,1); - #else - source_residual = cblas_dasum(_num_FSRs,_source_residuals,1); - #endif - - source_residual = sqrt(source_residual \ - / (_num_fissionable_FSRs * _num_groups)); - - return source_residual; } - /** * @brief Add the source term contribution in the transport equation to * the FSR scalar flux @@ -446,7 +424,7 @@ void VectorizedSolver::addSourceToScalarFlux() { /* Add in source term and normalize flux to volume for each FSR */ /* Loop over FSRs, energy groups */ - #pragma omp parallel for private(volume, sigma_t) schedule(guided) +#pragma omp parallel for private(volume, sigma_t) schedule(guided) for (int r=0; r < _num_FSRs; r++) { volume = _FSR_volumes[r]; @@ -456,17 +434,17 @@ void VectorizedSolver::addSourceToScalarFlux() { for (int v=0; v < _num_vector_lengths; v++) { /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) _scalar_flux(r,e) *= 0.5; /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) _scalar_flux(r,e) = _scalar_flux(r,e) / (sigma_t[e] * volume); /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) _scalar_flux(r,e) += FOUR_PI * _reduced_sources(r,e); } @@ -477,26 +455,11 @@ void VectorizedSolver::addSourceToScalarFlux() { /** - * @brief Compute \f$ k_{eff} \f$ from the total, fission and scattering - * reaction rates and leakage. - * @details This method computes the current approximation to the - * multiplication factor on this iteration as follows: - * \f$ k_{eff} = \frac{\displaystyle\sum_{i \in I} - * \displaystyle\sum_{g \in G} \nu \Sigma^F_g \Phi V_{i}} - * {\displaystyle\sum_{i \in I} - * \displaystyle\sum_{g \in G} (\Sigma^T_g \Phi V_{i} - - * \Sigma^S_g \Phi V_{i} - L_{i,g})} \f$ + * @brief Compute \f$ k_{eff} \f$ from successive fission sources. */ void VectorizedSolver::computeKeff() { - int tid; - Material* material; - FP_PRECISION* sigma; - FP_PRECISION volume; - - FP_PRECISION total = 0.0; - FP_PRECISION fission = 0.0; - FP_PRECISION scatter = 0.0; + FP_PRECISION fission; int size = _num_FSRs * sizeof(FP_PRECISION); FP_PRECISION* FSR_rates = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); @@ -504,134 +467,56 @@ void VectorizedSolver::computeKeff() { size = _num_threads * _num_groups * sizeof(FP_PRECISION); FP_PRECISION* group_rates = (FP_PRECISION*)MM_MALLOC(size, VEC_ALIGNMENT); - /* Loop over all FSRs and compute the volume-weighted total rates */ - #pragma omp parallel for private(tid, volume, \ - material, sigma) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { - - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; - sigma = material->getSigmaT(); - - /* Loop over each energy group vector length */ - for (int v=0; v < _num_vector_lengths; v++) { - - /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) - for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); - } - - #ifdef SINGLE - FSR_rates[r] = cblas_sasum(_num_groups, &group_rates[tid], 1) * volume; - #else - FSR_rates[r] = cblas_dasum(_num_groups, &group_rates[tid], 1) * volume; - #endif - } - - /* Reduce total rates across FSRs, energy groups */ - #ifdef SINGLE - total = cblas_sasum(_num_FSRs, FSR_rates, 1); - #else - tototal = cblas_dasum(_num_FSRs, FSR_rates, 1); - #endif - - /* Loop over all FSRs and compute the volume-weighted fission rates */ - #pragma omp parallel for private(tid, volume, \ - material, sigma) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { - - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; - sigma = material->getNuSigmaF(); - - /* Loop over each energy group vector length */ - for (int v=0; v < _num_vector_lengths; v++) { - - /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) - for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); - } - - #ifdef SINGLE - FSR_rates[r] = cblas_sasum(_num_groups, &group_rates[tid], 1) * volume; - #else - FSR_rates[r] = cblas_dasum(_num_groups, &group_rates[tid], 1) * volume; - #endif - } - - /* Reduce fission rates across FSRs */ - #ifdef SINGLE - fission = cblas_sasum(_num_FSRs, FSR_rates, 1); - #else - fission = cblas_dasum(_num_FSRs, FSR_rates, 1); - #endif - - /* Loop over all FSRs and compute the volume-weighted scatter rates */ - #pragma omp parallel for private(tid, volume, \ - material, sigma) schedule(guided) - for (int r=0; r < _num_FSRs; r++) { +#pragma omp parallel + { - tid = omp_get_thread_num() * _num_groups; - volume = _FSR_volumes[r]; - material = _FSR_materials[r]; - sigma = material->getSigmaS(); + int tid = omp_get_thread_num() * _num_groups; + Material* material; + FP_PRECISION* sigma; + FP_PRECISION volume; - FSR_rates[r] = 0.; + /* Compute the new nu-fission rates in each FSR */ +#pragma omp for schedule(guided) + for (int r=0; r < _num_FSRs; r++) { - for (int G=0; G < _num_groups; G++) { + volume = _FSR_volumes[r]; + material = _FSR_materials[r]; + sigma = material->getNuSigmaF(); /* Loop over each energy group vector length */ for (int v=0; v < _num_vector_lengths; v++) { /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) - for (int g=v*VEC_LENGTH; g < (v+1)*VEC_LENGTH; g++) - group_rates[tid+g] = sigma[G*_num_groups+g] * _scalar_flux(r,g); +#pragma simd vectorlength(VEC_LENGTH) + for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) + group_rates[tid+e] = sigma[e] * _scalar_flux(r,e); } - #ifdef SINGLE - FSR_rates[r] += cblas_sasum(_num_groups, &group_rates[tid], 1) * volume; - #else - FSR_rates[r] += cblas_dasum(_num_groups, &group_rates[tid], 1) * volume; - #endif +#ifdef SINGLE + FSR_rates[r] = cblas_sasum(_num_groups, &group_rates[tid], 1) * volume; +#else + FSR_rates[r] = cblas_dasum(_num_groups, &group_rates[tid], 1) * volume; +#endif } } - /* Reduce scatter rates across FSRs */ - #ifdef SINGLE - scatter = cblas_sasum(_num_FSRs, FSR_rates, 1); - #else - scatter = cblas_dasum(_num_FSRs, FSR_rates, 1); - #endif - - /** Reduce leakage array across tracks, energy groups, polar angles */ - size = 2 * _tot_num_tracks * _polar_times_groups; - - #ifdef SINGLE - _leakage = cblas_sasum(size, _boundary_leakage, 1) * 0.5; - #else - _leakage = cblas_dasum(size, _boundary_leakage, 1) * 0.5; - #endif - - _k_eff = fission / (total - scatter + _leakage); + /* Reduce new fission rates across FSRs */ +#ifdef SINGLE + fission = cblas_sasum(_num_FSRs, FSR_rates, 1); +#else + fission = cblas_dasum(_num_FSRs, FSR_rates, 1); +#endif - log_printf(DEBUG, "tot = %f, fiss = %f, scatt = %f, leakage = %f," - "k_eff = %f", total, fission, scatter, _leakage, _k_eff); + _k_eff *= fission; MM_FREE(FSR_rates); MM_FREE(group_rates); - -return; } /** - * @brief Computes the contribution to the FSR scalar flux from a Track segment. + * @brief Computes the contribution to the FSR scalar flux from a segment. * @details This method integrates the angular flux for a Track segment across * energy groups and polar angles, and tallies it into the FSR scalar * flux, and updates the Track's angular flux. @@ -639,18 +524,14 @@ return; * @param azim_index a pointer to the azimuthal angle index for this segment * @param track_flux a pointer to the Track's angular flux * @param fsr_flux a pointer to the temporary FSR flux buffer - * @param fwd */ -void VectorizedSolver::scalarFluxTally(segment* curr_segment, +void VectorizedSolver::tallyScalarFlux(segment* curr_segment, int azim_index, FP_PRECISION* track_flux, - FP_PRECISION* fsr_flux, - bool fwd){ + FP_PRECISION* fsr_flux) { int tid = omp_get_thread_num(); int fsr_id = curr_segment->_region_id; - FP_PRECISION length = curr_segment->_length; - FP_PRECISION* sigma_t = curr_segment->_material->getSigmaT(); FP_PRECISION* delta_psi = &_delta_psi[tid*_num_groups]; FP_PRECISION* exponentials = &_thread_exponentials[tid*_polar_times_groups]; @@ -661,28 +542,28 @@ void VectorizedSolver::scalarFluxTally(segment* curr_segment, /* Tally the flux contribution from segment to FSR's scalar flux */ /* Loop over polar angles */ - for (int p=0; p < _num_polar; p++){ + for (int p=0; p < _num_polar; p++) { /* Loop over each energy group vector length */ for (int v=0; v < _num_vector_lengths; v++) { /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) delta_psi[e] = track_flux(p,e) - _reduced_sources(fsr_id,e); /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) delta_psi[e] *= exponentials(p,e); /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) fsr_flux[e] += delta_psi[e] * _polar_weights(azim_index,p); /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) track_flux(p,e) -= delta_psi[e]; } @@ -691,17 +572,15 @@ void VectorizedSolver::scalarFluxTally(segment* curr_segment, /* Atomically increment the FSR scalar flux from the temporary array */ omp_set_lock(&_FSR_locks[fsr_id]); { - #ifdef SINGLE +#ifdef SINGLE vsAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux, &_scalar_flux(fsr_id,0)); - #else +#else vdAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux, &_scalar_flux(fsr_id,0)); - #endif +#endif } omp_unset_lock(&_FSR_locks[fsr_id]); - - return; } @@ -719,18 +598,13 @@ void VectorizedSolver::computeExponentials(segment* curr_segment, FP_PRECISION* sigma_t = curr_segment->_material->getSigmaT(); /* Evaluate the exponentials using the linear interpolation table */ - if (_interpolate_exponential) { + if (_exp_evaluator->isUsingInterpolation()) { FP_PRECISION tau; - int index; for (int e=0; e < _num_groups; e++) { - for (int p=0; p < _num_polar; p++) { - tau = sigma_t[e] * length; - index = round_to_int(tau * _inverse_exp_table_spacing); - index *= _two_times_num_polar; - exponentials(p,e) = (1. - (_exp_table[index+2 * p] * tau + - _exp_table[index + 2 * p +1])); - } + tau = length * sigma_t[e]; + for (int p=0; p < _num_polar; p++) + exponentials(p,e) = _exp_evaluator->computeExponential(tau, p); } } @@ -738,8 +612,7 @@ void VectorizedSolver::computeExponentials(segment* curr_segment, else { int tid = omp_get_thread_num(); - - FP_PRECISION* sinthetas = _quad->getSinThetas(); + FP_PRECISION* sin_thetas = _polar_quad->getSinThetas(); FP_PRECISION* taus = &_thread_taus[tid*_polar_times_groups]; /* Initialize the tau argument for the exponentials */ @@ -747,29 +620,29 @@ void VectorizedSolver::computeExponentials(segment* curr_segment, for (int v=0; v < _num_vector_lengths; v++) { - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) taus(p,e) = -sigma_t[e] * length; - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - taus(p,e) /= sinthetas[p]; + taus(p,e) /= sin_thetas[p]; } } /* Evaluate the negative of the exponentials using Intel's MKL */ - #ifdef SINGLE +#ifdef SINGLE vsExp(_polar_times_groups, taus, exponentials); - #else +#else vdExp(_polar_times_groups, taus, exponentials); - #endif +#endif /* Compute one minus the exponentials */ for (int p=0; p < _num_polar; p++) { for (int v=0; v < _num_vector_lengths; v++) { - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) exponentials(p,e) = 1.0 - exponentials(p,e); } @@ -780,9 +653,10 @@ void VectorizedSolver::computeExponentials(segment* curr_segment, /** * @brief Updates the boundary flux for a Track given boundary conditions. - * @details For reflective boundary conditions, the outgoing boundary flux - * for the Track is given to the reflecting Track. For vacuum - * boundary conditions, the outgoing flux tallied as leakage. + * @details For reflective and periodic boundary conditions, the outgoing + * boundary flux for the Track is given to the corresponding reflecting + * or periodic Track. For vacuum boundary conditions, the outgoing flux + * is tallied as leakage. * @param track_id the ID number for the Track of interest * @param azim_index a pointer to the azimuthal angle index for this segment * @param direction the Track direction (forward - true, reverse - false) @@ -792,27 +666,21 @@ void VectorizedSolver::transferBoundaryFlux(int track_id, int azim_index, bool direction, FP_PRECISION* track_flux) { int start; - bool bc; - FP_PRECISION* track_leakage; + bool transfer_flux; int track_out_id; - /* Extract boundary conditions for this Track and the pointer to the - * outgoing reflective Track, and index into the leakage array */ - /* For the "forward" direction */ if (direction) { - start = _tracks[track_id]->isReflOut() * _polar_times_groups; - track_leakage = &_boundary_leakage(track_id,0); + start = _tracks[track_id]->isNextOut() * _polar_times_groups; + transfer_flux = _tracks[track_id]->getTransferFluxOut(); track_out_id = _tracks[track_id]->getTrackOut()->getUid(); - bc = _tracks[track_id]->getBCOut(); } /* For the "reverse" direction */ else { - start = _tracks[track_id]->isReflIn() * _polar_times_groups; - track_leakage = &_boundary_leakage(track_id,_polar_times_groups); + start = _tracks[track_id]->isNextIn() * _polar_times_groups; + transfer_flux = _tracks[track_id]->getTransferFluxIn(); track_out_id = _tracks[track_id]->getTrackIn()->getUid(); - bc = _tracks[track_id]->getBCIn(); } FP_PRECISION* track_out_flux = &_boundary_flux(track_out_id,0,0,start); @@ -824,19 +692,9 @@ void VectorizedSolver::transferBoundaryFlux(int track_id, int azim_index, for (int v=0; v < _num_vector_lengths; v++) { /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) - for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - track_out_flux(p,e) = track_flux(p,e) * bc; - - /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) - for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - track_leakage(p,e) = track_flux(p,e); - - /* Loop over energy groups within this vector */ - #pragma simd vectorlength(VEC_LENGTH) +#pragma simd vectorlength(VEC_LENGTH) for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) - track_leakage(p,e) *= _polar_weights(azim_index,p) * (!bc); + track_out_flux(p,e) = track_flux(p,e) * transfer_flux; } } } diff --git a/src/VectorizedSolver.h b/src/VectorizedSolver.h index b3f45f467..0679534d5 100644 --- a/src/VectorizedSolver.h +++ b/src/VectorizedSolver.h @@ -11,11 +11,11 @@ #ifdef __cplusplus #define _USE_MATH_DEFINES +#include "CPUSolver.h" #include #include #include #include -#include "CPUSolver.h" #endif /** Indexing scheme for the optical length (\f$ l\Sigma_t \f$) for a @@ -53,40 +53,31 @@ class VectorizedSolver : public CPUSolver { * each thread in each energy group and polar angle */ FP_PRECISION* _thread_exponentials; - void buildExpInterpTable(); - void initializeFluxArrays(); - void initializeSourceArrays(); - - void normalizeFluxes(); - FP_PRECISION computeFSRSources(); - void scalarFluxTally(segment* curr_segment, int azim_index, - FP_PRECISION* track_flux, - FP_PRECISION* fsr_flux, bool fwd); + void tallyScalarFlux(segment* curr_segment, int azim_index, + FP_PRECISION* track_flux, FP_PRECISION* fsr_flux); void transferBoundaryFlux(int track_id, int azim_index, bool direction, FP_PRECISION* track_flux); - void addSourceToScalarFlux(); - void computeKeff(); - - - /** - * @brief Computes an array of the exponentials in the transport equation, - * \f$ exp(-\frac{\Sigma_t * l}{sin(\theta)}) \f$, for each - * energy group and polar angle for a given segment. - * @param curr_segment pointer to the segment of interest - * @param exponentials the array to store the exponential values - */ - virtual void computeExponentials(segment* curr_segment, - FP_PRECISION* exponentials); + void computeExponentials(segment* curr_segment, FP_PRECISION* exponentials); public: - VectorizedSolver(Geometry* geometry=NULL, - TrackGenerator* track_generator=NULL); - + VectorizedSolver(TrackGenerator* track_generator=NULL); virtual ~VectorizedSolver(); int getNumVectorWidths(); void setGeometry(Geometry* geometry); + + void initializeExpEvaluator(); + void initializeMaterials(solverMode mode=ADJOINT); + void initializeFluxArrays(); + void initializeSourceArrays(); + void initializeFixedSources(); + void initializeFSRs(); + + void normalizeFluxes(); + void computeFSRSources(); + void addSourceToScalarFlux(); + void computeKeff(); }; diff --git a/src/accel/DeviceMaterial.h b/src/accel/DeviceMaterial.h index 660bac719..8e4308364 100644 --- a/src/accel/DeviceMaterial.h +++ b/src/accel/DeviceMaterial.h @@ -27,9 +27,6 @@ struct dev_material { /** An array of the total cross-sections for each energy group */ FP_PRECISION* _sigma_t; - /** An array of the absorption cross-sections for each energy group */ - FP_PRECISION* _sigma_a; - /** A 2D array of the scattering cross-section matrix. The first index is * row number and second index is column number */ FP_PRECISION* _sigma_f; @@ -41,8 +38,10 @@ struct dev_material { /** An array of the chi \f$ \chi \f$ values for each energy group */ FP_PRECISION* _chi; - /** An array of the group-to-group scattering cross-sections. The first - * index is row number; second index is column number */ + /** A 2D array of the fission matrix from/into each group */ + FP_PRECISION* _fiss_matrix; + + /** A 2D array of the scattering cross-section matrix from/into each group */ FP_PRECISION* _sigma_s; /** @@ -50,11 +49,11 @@ struct dev_material { */ dev_material() { _sigma_t = NULL; - _sigma_a = NULL; _sigma_s = NULL; _sigma_f = NULL; _nu_sigma_f = NULL; _chi = NULL; + _fiss_matrix = NULL; } /** @@ -63,8 +62,6 @@ struct dev_material { ~dev_material() { if (_sigma_t != NULL) delete [] _sigma_t; - if (_sigma_a != NULL) - delete [] _sigma_a; if (_sigma_s != NULL) delete [] _sigma_s; if (_sigma_f != NULL) @@ -73,6 +70,8 @@ struct dev_material { delete [] _nu_sigma_f; if (_chi != NULL) delete [] _chi; + if (_fiss_matrix != NULL) + delete [] _fiss_matrix; } }; diff --git a/src/accel/DeviceTrack.h b/src/accel/DeviceTrack.h index beec94e44..0be564da9 100644 --- a/src/accel/DeviceTrack.h +++ b/src/accel/DeviceTrack.h @@ -54,34 +54,33 @@ struct dev_track { /** The number of segments making up this Track */ int _num_segments; - /** Index of the Track which reflects out of this Track along its "forward" - * direction for reflective boundary conditions. */ + /** Index of the next Track when traveling along this Track in the "forward" + * direction. */ int _track_in; - /** Index of the Track which reflects out of this Track along its "reverse" - * direction for reflective boundary conditions. */ + /** Index of the next Track when traveling along this Track in the "reverse" + * direction. */ int _track_out; - /** The first index into the global 2D ragged array of Tracks for the Track - * that reflects out of this Track along its "forward" direction for - * reflective boundary conditions. */ - bool _refl_in; + /** A boolean to indicate whether to give the flux to the "forward" (false) + * or "reverse" (true) direction of the next Track going in the "forward" + * direction. */ + bool _next_in; - /** A boolean to indicate whether to give the flux to the "forward" - * (false) or "reverse" (true) direction of the Track reflecting out of - * this one along its "forward" direction for reflective boundary - * conditions. */ - bool _refl_out; + /** A boolean to indicate whether to give the flux to the "forward" (false) + * or "reverse" (true) direction of the next Track going in the "reverse" + * direction. */ + bool _next_out; /** A boolean to indicate whether the outgoing angular flux along this - * Track's "forward" direction should be zeroed out for vacuum boundary - * conditions. */ - bool _bc_in; + * Track's "forward" direction should be transferred to the outgoing + * Track. */ + bool _transfer_flux_in; /** A boolean to indicate whether the outgoing angular flux along this - * Track's "reverse" direction should be zeroed out for vacuum boundary - * conditions. */ - bool _bc_out; + * Track's "reverse" direction should be transferred to the incoming + * Track. */ + bool _transfer_flux_out; }; diff --git a/src/accel/cuda/GPUExpEvaluator.cu b/src/accel/cuda/GPUExpEvaluator.cu new file mode 100644 index 000000000..6f3068176 --- /dev/null +++ b/src/accel/cuda/GPUExpEvaluator.cu @@ -0,0 +1,101 @@ +#include "GPUExpEvaluator.h" + + +/** A boolean whether to use linear interpolation to compute exponentials */ +__constant__ bool interpolate[1]; + +/** The maximum allowable optical length represented in the table */ +__constant__ FP_PRECISION max_optical_length[1]; + +/** The inverse spacing for the exponential linear interpolation table */ +__constant__ FP_PRECISION inverse_exp_table_spacing[1]; + +/** An array for the sines of the polar angle in the polar Quadrature set */ +extern __constant__ FP_PRECISION sin_thetas[MAX_POLAR_ANGLES_GPU]; + +/** Twice the number of polar angles */ +extern __constant__ int two_times_num_polar[1]; + + +/** + * @brief Given a pointer to an ExpEvaluator on the host and a + * GPUExpEvaluator on the GPU, copy all of the properties from +* the ExpEvaluator object on the host to the GPU. + * @details This routine is called by the GPUSolver::initializeExpEvaluator() + * private class method and is not intended to be called directly. + * @param eavluator_h pointer to a ExpEvaluator on the host + * @param evaluator_d pointer to a GPUExpEvaluator on the GPU + */ +void clone_exp_evaluator(ExpEvaluator* evaluator_h, + GPUExpEvaluator* evaluator_d) { + + /* Copy a boolean indicating whether or not to use the linear interpolation + * table or the exp intrinsic function to constant memory on the device */ + bool interpolate_exp = evaluator_h->isUsingInterpolation(); + cudaMemcpyToSymbol(interpolate, (void*)&interpolate_exp, + sizeof(bool), 0, cudaMemcpyHostToDevice); + + if (evaluator_h->isUsingInterpolation()) { + + /* Copy inverse table spacing to constant memory on the device */ + FP_PRECISION inverse_spacing_h = 1.0 / evaluator_h->getTableSpacing(); + cudaMemcpyToSymbol(inverse_exp_table_spacing, (void*)&inverse_spacing_h, + sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); + + /* Copy the number of table entries to constant memory on the device */ + FP_PRECISION max_optical_length_h = evaluator_h->getMaxOpticalLength(); + cudaMemcpyToSymbol(max_optical_length, (void*)&max_optical_length_h, + sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); + + /* Allocate memory for the interpolation table on the device */ + int exp_table_size_h = evaluator_h->getTableSize(); + FP_PRECISION* exp_table_h = evaluator_h->getExpTable(); + + FP_PRECISION* exp_table_d; + cudaMalloc((void**)&exp_table_d, exp_table_size_h * sizeof(FP_PRECISION)); + cudaMemcpy((void*)exp_table_d, (void*)exp_table_h, + exp_table_size_h * sizeof(FP_PRECISION), + cudaMemcpyHostToDevice); + cudaMemcpy((void*)&evaluator_d->_exp_table, (void*)&exp_table_d, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); + } + + return; +} + + +/** + * @brief Computes the exponential term for a optical length and polar angle. + * @details This method computes \f$ 1 - exp(-\tau/sin(\theta_p)) \f$ + * for some optical path length and polar angle. This method + * uses either a linear interpolation table (default) or the + * exponential intrinsic exp(...) function. + * @param tau the optical path length (e.g., sigma_t times length) + * @param polar the polar angle index + * @return the evaluated exponential + */ +__device__ FP_PRECISION GPUExpEvaluator::computeExponential(FP_PRECISION tau, + int polar) { + + FP_PRECISION exponential; + + /* Evaluate the exponential using the linear interpolation table */ + if (*interpolate) { + tau = min(tau, (*max_optical_length)); + int index = floor(tau * (*inverse_exp_table_spacing)); + index *= (*two_times_num_polar); + exponential = (1. - (_exp_table[index + 2 * polar] * tau + + _exp_table[index + 2 * polar +1])); + } + + /* Evalute the exponential using the intrinsic exp(...) function */ + else { + #ifdef SINGLE + exponential = 1.0 - __expf(- tau / sin_thetas[polar]); + #else + exponential = 1.0 - exp(- tau / sin_thetas[polar]); + #endif + } + + return exponential; +} diff --git a/src/accel/cuda/GPUExpEvaluator.h b/src/accel/cuda/GPUExpEvaluator.h new file mode 100644 index 000000000..10465bfdf --- /dev/null +++ b/src/accel/cuda/GPUExpEvaluator.h @@ -0,0 +1,45 @@ +/** + * @file GPUExpEvaluator.h + * @brief The GPUExpEvaluator class. + * @details This class is based on the ExpEvaluator class for execution + * on NVIDIA GPUs. + * @date April 11, 2015. + * @author William Boyd, MIT, Course 22 (wboyd@mit.edu) + */ + +#ifndef GPUEXPEVALUATOR_H_ +#define GPUEXPEVALUATOR_H_ + +#ifdef __cplusplus +#define _USE_MATH_DEFINES +#include +#include "../../ExpEvaluator.h" +#endif + + +/** + * @class GPUExpEvaluator GPUExpEvaluator.h "src/accel/cuda/ExpEvaluator.h" + * @brief This is a class for evaluating exponentials on GPUs. + * @details The ExpEvaluator includes different algorithms to evaluate + * exponentials with varying degrees of accuracy and speed. This + * is a helper class for the Solver and its subclasses and it not + * intended to be initialized as a standalone object. + */ +class GPUExpEvaluator { + +private: + +public: + + /** The exponential linear interpolation table */ + FP_PRECISION* _exp_table; + + __device__ FP_PRECISION computeExponential(FP_PRECISION tau, int polar); +}; + + +void clone_exp_evaluator(ExpEvaluator* evaluator_h, + GPUExpEvaluator* evaluator_d); + + +#endif /* EXPEVALUATOR_H_ */ diff --git a/src/accel/cuda/GPUQuery.h b/src/accel/cuda/GPUQuery.h index 6ddaa80e5..20dcf7a61 100644 --- a/src/accel/cuda/GPUQuery.h +++ b/src/accel/cuda/GPUQuery.h @@ -11,6 +11,9 @@ #define GPUQUERY_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif #include "../../log.h" #endif diff --git a/src/accel/cuda/GPUSolver.cu b/src/accel/cuda/GPUSolver.cu index 9921ed81a..f0727404b 100644 --- a/src/accel/cuda/GPUSolver.cu +++ b/src/accel/cuda/GPUSolver.cu @@ -19,56 +19,165 @@ __constant__ int two_times_num_polar[1]; __constant__ int polar_times_groups[1]; /** An array for the sines of the polar angle in the polar Quadrature set */ -__constant__ FP_PRECISION sinthetas[MAX_POLAR_ANGLES]; +__constant__ FP_PRECISION sin_thetas[MAX_POLAR_ANGLES_GPU]; /** An array of the weights for the polar angles from the Quadrature set */ -__constant__ FP_PRECISION polar_weights[MAX_POLAR_ANGLES*MAX_AZIM_ANGLES]; - -/** A pointer to an array with the number of tracks per azimuthal angle */ -__constant__ int num_tracks[MAX_AZIM_ANGLES/2]; +__constant__ FP_PRECISION polar_weights[MAX_POLAR_ANGLES_GPU*MAX_AZIM_ANGLES_GPU]; /** The total number of Tracks */ __constant__ int tot_num_tracks[1]; -/** A boolean indicating whether or not to use linear interpolation - * to comptue the exponential in the transport equation */ -__constant__ bool interpolate_exponential[1]; +/** An GPUExpEvaluator object to compute exponentials */ +__constant__ GPUExpEvaluator exp_evaluator; -/** The maximum index of the exponential linear interpolation table */ -__constant__ int exp_table_max_index[1]; -/** The spacing for the exponential linear interpolation table */ -__constant__ FP_PRECISION exp_table_spacing[1]; +/** + * @brief A struct used to check if a value on the GPU is equal to INF. + * @details This is used as a predicate in Thrust routines. + */ +struct isinf_test { + /** + * @brief Checks if a double precision value is INF. + * @param a the value to check + * @return true if equal to INF, false otherwise + */ + __host__ __device__ bool operator()(double a) { + return isinf(a); + } -/** The inverse spacing for the exponential linear interpolation table */ -__constant__ FP_PRECISION inverse_exp_table_spacing[1]; + /** + * @brief Checks if a single precision value is INF. + * @param a the value to check + * @return true if equal to INF, false otherwise + */ + __host__ __device__ bool operator()(float a) { + return isinf(a); + } +}; +/** + * @brief A struct used to check if a value on the GPU is equal to NaN. + * @details This is used as a predicate in Thrust routines. + */ +struct isnan_test { + /** + * @brief Checks if a double precision value is NaN. + * @param a the value to check + * @return true if equal to NaN, false otherwise + */ + __host__ __device__ bool operator()(double a) { + return isnan(a); + } + + /** + * @brief Checks if a single precision value is NaN. + * @param a the value to check + * @return true if equal to NaN, false otherwise + */ + __host__ __device__ bool operator()(float a) { + return isnan(a); + } +}; + /** - * @brief Fast method to round a single precision floating point value - * to an integer on the GPU. - * @param x float floating point value to round - * @return the rounded down integer value + * @brief A functor to multiply all elements in a Thrust vector by a constant. + * @param constant the constant to multiply the vector */ -__device__ int round_to_int(float x) { - return __float2int_rd(x); -} +template< typename T > +struct multiplyByConstant { + +public: + /* The constant to multiply by */ + const T constant; + + /** + * @brief Constructor for the functor. + * @param constant to multiply each element in a Thrust vector + */ + multiplyByConstant(T constant) : constant(constant) {} + + /** + * @brief Multiply an element in a Thrust vector. + * @param VecElem the element to multiply + */ + __host__ __device__ void operator()(T& VecElem) const { + VecElem = VecElem * constant; + } +}; /** - * @brief Fast method to round a double precision floating point value - * to an integer on the GPU. - * @param x double floating point value to round - * @return the rounded down integer value + * @class This provides a templated interface for a strided iterator over + * a Thrust device_vector on a GPU. + * @details This code is taken from the Thrust examples site on 1/20/2015: + * https://github.com/thrust/thrust/blob/master/examples/strided_range.cu */ -__device__ int round_to_int(double x) { - return __double2int_rd(x); -} +template +class strided_range { + +public: + + typedef typename thrust::iterator_difference::type difference_type; + + struct stride_functor : public thrust::unary_function { + + difference_type stride; + + stride_functor(difference_type stride) : stride(stride) { } + + __host__ __device__ difference_type operator()(const difference_type& i) const { + return stride * i; + } + }; + + typedef typename thrust::counting_iterator CountingIterator; + typedef typename thrust::transform_iterator + TransformIterator; + typedef typename thrust::permutation_iterator + PermutationIterator; + typedef PermutationIterator iterator; + + /** + * @brief The strided iterator constructor. + */ + strided_range(Iterator first, Iterator last, difference_type stride) + : first(first), last(last), stride(stride) { } + + /** + * @brief Get the first element in the iterator. + * @return the first element in the iterator + */ + iterator begin(void) const { + return PermutationIterator(first, + TransformIterator(CountingIterator(0), stride_functor(stride))); + } + + /** + * @brief Get the last element in the iterator. + * @return the last element in the iterator + */ + iterator end(void) const { + return begin() + ((last - first) + (stride - 1)) / stride; + } + +protected: + + /** The first element in the underlying device_vector as set by the constructor */ + Iterator first; + + /** The last element in the underlying device_vector as set by the constructor */ + Iterator last; + + /** The stride to use when iterating over the underlying device_vector */ + difference_type stride; + +}; /** - * @brief Compute the total fission source from all FSRs on the GPU. + * @brief Compute the total fission source from all FSRs. * @param FSR_volumes an array of FSR volumes * @param FSR_materials an array of FSR Material indices * @param materials an array of dev_materials on the device @@ -88,8 +197,7 @@ __global__ void computeFissionSourcesOnDevice(FP_PRECISION* FSR_volumes, dev_material* curr_material; FP_PRECISION* nu_sigma_f; - FP_PRECISION volume; - FP_PRECISION source; + FP_PRECISION volume, source; /* Initialize fission source to zero */ shared_fission_source[threadIdx.x] = 0; @@ -115,223 +223,181 @@ __global__ void computeFissionSourcesOnDevice(FP_PRECISION* FSR_volumes, /* Copy this thread's fission source to global memory */ tid = threadIdx.x + blockIdx.x * blockDim.x; fission_sources[tid] = shared_fission_source[threadIdx.x]; - - return; } /** - * @brief Normalizes all FSR scalar fluxes and Track boundary angular - * fluxes to the total fission source (times \f$ \nu \f$). - * @param scalar_flux an array of the FSR scalar fluxes - * @param boundary_flux an array of the Track boundary fluxes - * @param norm_factor the normalization factor + * @brief Computes the total source (fission, scattering, fixed) in each FSR. + * @details This method computes the total source in each region based on + * this iteration's current approximation to the scalar flux. + * @param FSR_materials an array of FSR Material indices + * @param materials an array of dev_material pointers + * @param scalar_flux an array of FSR scalar fluxes + * @param fixed_sources an array of fixed (user-defined) sources + * @param reduced_sources an array of FSR sources / total xs + * @param inverse_k_eff the inverse of keff */ -__global__ void normalizeFluxesOnDevice(FP_PRECISION* scalar_flux, - FP_PRECISION* boundary_flux, - FP_PRECISION norm_factor) { +__global__ void computeFSRSourcesOnDevice(int* FSR_materials, + dev_material* materials, + FP_PRECISION* scalar_flux, + FP_PRECISION* fixed_sources, + FP_PRECISION* reduced_sources, + FP_PRECISION inverse_k_eff) { int tid = threadIdx.x + blockIdx.x * blockDim.x; - /* Normalize scalar fluxes for each FSR */ - while(tid < *num_FSRs) { + FP_PRECISION fission_source; + FP_PRECISION scatter_source; - for (int e=0; e < *num_groups; e++) - scalar_flux(tid,e) *= norm_factor; + dev_material* curr_material; + FP_PRECISION* sigma_t; + FP_PRECISION* sigma_s; + FP_PRECISION* fiss_mat; - tid += blockDim.x * gridDim.x; - } + /* Iterate over all FSRs */ + while (tid < *num_FSRs) { - tid = threadIdx.x + blockIdx.x * blockDim.x; + curr_material = &materials[FSR_materials[tid]]; - /* Normalize angular boundary fluxes for each Track */ - while(tid < *tot_num_tracks) { + sigma_t = curr_material->_sigma_t; + sigma_s = curr_material->_sigma_s; + fiss_mat = curr_material->_fiss_matrix; - for (int pe2=0; pe2 < 2*(*polar_times_groups); pe2++) - boundary_flux(tid,pe2) *= norm_factor; + /* Compute scatter + fission source for group g */ + for (int g=0; g < *num_groups; g++) { + scatter_source = 0; + fission_source = 0; + for (int g_prime=0; g_prime < *num_groups; g_prime++) { + scatter_source += sigma_s[g*(*num_groups)+g_prime] * scalar_flux(tid,g_prime); + fission_source += fiss_mat[g*(*num_groups)+g_prime] * scalar_flux(tid,g_prime); + } + + fission_source *= inverse_k_eff; + + /* Compute total (scatter+fission+fixed) reduced source */ + reduced_sources(tid,g) = fixed_sources(tid,g); + reduced_sources(tid,g) += scatter_source + fission_source; + reduced_sources(tid,g) *= ONE_OVER_FOUR_PI; + reduced_sources(tid,g) = __fdividef(reduced_sources(tid,g), sigma_t[g]); + } + + /* Increment the thread id */ tid += blockDim.x * gridDim.x; } - - return; } /** - * @brief Computes the total source (fission and scattering) in each FSR - * on the GPU. - * @details This method computes the total source in each region based on - * this iteration's current approximation to the scalar flux. A - * residual for the source with respect to the source compute on - * the previous iteration is computed and returned. The residual - * is determined as follows: - * \f$ res = \sqrt{\frac{\displaystyle\sum \displaystyle\sum - * \left(\frac{Q^i - Q^{i-1}{Q^i}\right)^2}{# FSRs}}} $\f - * + * @brief Computes the total fission source in each FSR in each energy group + * @details This method is a helper routine for the openmoc.krylov submodule. + * This routine computes the total fission source in each FSR. If the + * divide_sigma_t parameter is true then the fission source will be + * divided by the total cross-section in each FSR. * @param FSR_materials an array of FSR Material indices * @param materials an array of dev_material pointers + * @param divide_sigma_t a boolean indicating whether to divide by the total xs * @param scalar_flux an array of FSR scalar fluxes - * @param old_fission_sources an array of current FSR sources from previous iteration - * @param reduced_sources an array of FSR sources / total xs - * @param inverse_k_eff the inverse of keff - * @param source_residuals an array of the FSR source residuals - * @return the residual between this source and the previous source + * @param reduced_sources an array of FSR fission sources */ -__global__ void computeFSRSourcesOnDevice(int* FSR_materials, - dev_material* materials, - FP_PRECISION* scalar_flux, - FP_PRECISION* old_fission_sources, - FP_PRECISION* reduced_sources, - FP_PRECISION inverse_k_eff, - FP_PRECISION* source_residuals) { +__global__ void computeFSRFissionSourcesOnDevice(int* FSR_materials, + dev_material* materials, + bool divide_sigma_t, + FP_PRECISION* scalar_flux, + FP_PRECISION* reduced_sources) { int tid = threadIdx.x + blockIdx.x * blockDim.x; - /* Reset the residual for the old and new fission sources to zero */ - source_residuals[threadIdx.x + blockIdx.x * blockDim.x] = 0.0; - FP_PRECISION fission_source; - FP_PRECISION scatter_source; - FP_PRECISION fsr_fission_source; dev_material* curr_material; - - FP_PRECISION* nu_sigma_f; - FP_PRECISION* sigma_s; FP_PRECISION* sigma_t; - FP_PRECISION* chi; + FP_PRECISION* fiss_mat; /* Iterate over all FSRs */ while (tid < *num_FSRs) { curr_material = &materials[FSR_materials[tid]]; - nu_sigma_f = curr_material->_nu_sigma_f; - sigma_s = curr_material->_sigma_s; sigma_t = curr_material->_sigma_t; - chi = curr_material->_chi; + fiss_mat = curr_material->_fiss_matrix; - /* Initialize the fission source to zero for this FSR */ - fission_source = 0; - fsr_fission_source = 0.0; + /* Compute fission source for group g */ + for (int g=0; g < *num_groups; g++) { + fission_source = 0; - /* Compute total fission source for current region */ - for (int e=0; e < *num_groups; e++) - fission_source += scalar_flux(tid,e) * nu_sigma_f[e]; - - /* Compute total scattering source for this FSR in group G */ - for (int G=0; G < *num_groups; G++) { - - scatter_source = 0; + for (int g_prime=0; g_prime < *num_groups; g_prime++) + fission_source += fiss_mat[g*(*num_groups)+g_prime] * scalar_flux(tid,g_prime); - for (int g=0; g < *num_groups; g++) - scatter_source += sigma_s[G*(*num_groups)+g] * scalar_flux(tid,g); - - /* Set the fission source for FSR r in group G */ - fsr_fission_source += fission_source * chi[G] * inverse_k_eff; - - reduced_sources(tid,G) = __fdividef((inverse_k_eff * fission_source - * chi[G] + scatter_source) * ONE_OVER_FOUR_PI, sigma_t[G]); + /* Set the reduced fission source for FSR tid in group g */ + reduced_sources(tid,g) = fission_source; + reduced_sources(tid,g) *= ONE_OVER_FOUR_PI; + if (divide_sigma_t) + reduced_sources(tid,g) = __fdividef(reduced_sources(tid,g), sigma_t[g]); } - /* Compute the norm of residuals of the sources for convergence */ - if (fabs(fsr_fission_source) > 1E-10) - source_residuals[threadIdx.x + blockIdx.x * blockDim.x] += - pow((fsr_fission_source - old_fission_sources[tid]) - / fsr_fission_source, 2); - - - /* Update the old fission source */ - old_fission_sources[tid] = fsr_fission_source; - /* Increment the thread id */ tid += blockDim.x * gridDim.x; } - - return; } /** - * @brief Compute the total fission source from all FSRs and energy groups - * on the GPU. - * @param FSR_volumes an array of the FSR volumes - * @param FSR_materials an array of the FSR Material indices - * @param materials an array of the dev_material pointers + * @brief Computes the total scattering source in each FSR and energy group. + * @details This method is a helper routine for the openmoc.krylov submodule. + * This routine computes the total scatter source in each FSR. If the + * divide_sigma_t parameter is true then the scatter source will be + * divided by the total cross-section in each FSR. + * @param FSR_materials an array of FSR Material indices + * @param materials an array of dev_material pointers + * @param divide_sigma_t a boolean indicating whether to divide by the total xs * @param scalar_flux an array of FSR scalar fluxes - * @param total array of FSR total reaction rates - * @param fission an array of FSR fission rates - * @param scatter an array of FSR scattering rates + * @param reduced_sources an array of FSR scatter sources */ -__global__ void computeKeffReactionRates(FP_PRECISION* FSR_volumes, - int* FSR_materials, - dev_material* materials, - FP_PRECISION* scalar_flux, - FP_PRECISION* total, - FP_PRECISION* fission, - FP_PRECISION* scatter) { +__global__ void computeFSRScatterSourcesOnDevice(int* FSR_materials, + dev_material* materials, + bool divide_sigma_t, + FP_PRECISION* scalar_flux, + FP_PRECISION* reduced_sources) { int tid = threadIdx.x + blockIdx.x * blockDim.x; + FP_PRECISION scatter_source; + dev_material* curr_material; - FP_PRECISION* sigma_t; - FP_PRECISION* nu_sigma_f; FP_PRECISION* sigma_s; - FP_PRECISION volume; - - FP_PRECISION tot = 0.; - FP_PRECISION fiss = 0.; - FP_PRECISION scatt = 0.; + FP_PRECISION* sigma_t; /* Iterate over all FSRs */ while (tid < *num_FSRs) { curr_material = &materials[FSR_materials[tid]]; - sigma_t = curr_material->_sigma_t; - nu_sigma_f = curr_material->_nu_sigma_f; - sigma_s = curr_material->_sigma_s; - volume = FSR_volumes[tid]; - FP_PRECISION curr_tot = 0.; - FP_PRECISION curr_fiss = 0.; - FP_PRECISION curr_scatt = 0.; + sigma_s = curr_material->_sigma_s; + sigma_t = curr_material->_sigma_t; - /* Iterate over all energy groups and update total and fission - * rates for this thread block */ - for (int e=0; e < *num_groups; e++) { - curr_tot += sigma_t[e] * scalar_flux(tid,e); - curr_fiss += nu_sigma_f[e] * scalar_flux(tid,e); - } + /* Compute total scattering source for this FSR in group g */ + for (int g=0; g < *num_groups; g++) { + scatter_source = 0; - tot += curr_tot * volume; - fiss += curr_fiss * volume; + for (int g_prime=0; g_prime < *num_groups; g_prime++) + scatter_source += sigma_s[g*(*num_groups)+g_prime] * scalar_flux(tid,g_prime); - /* Iterate over all energy groups and update scattering - * rates for this thread block */ - for (int G=0; G < *num_groups; G++) { - for (int g=0; g < *num_groups; g++) - curr_scatt += sigma_s[G*(*num_groups)+g] * scalar_flux(tid,g); + /* Set the reduced scatter source for FSR tid in group g */ + reduced_sources(tid,g) = scatter_source; + reduced_sources(tid,g) *= ONE_OVER_FOUR_PI; + if (divide_sigma_t) + reduced_sources(tid,g) = __fdividef(reduced_sources(tid,g), sigma_t[g]); } - scatt += curr_scatt * volume; - - /* Increment thread id */ + /* Increment the thread id */ tid += blockDim.x * gridDim.x; } - - /* Copy this thread's total and scatter rates to global memory */ - tid = threadIdx.x + blockIdx.x * blockDim.x; - total[tid] = tot; - fission[tid] = fiss; - scatter[tid] = scatt; - - return; } /** - * @brief Perform an atomic addition in double precision to an array address - * on the GPU. + * @brief Perform an atomic addition in double precision to an array address. * @details This method is straight out of CUDA C Developers Guide (cc 2013). * @param address the array memory address * @param val the value to add to the array @@ -353,52 +419,8 @@ __device__ double atomicAdd(double* address, double val) { /** - * @brief Computes the exponential term in the transport equation for a - * Track segment on the GPU. - * @details This method computes \f$ 1 - exp(-l\Sigma^T_g/sin(\theta_p)) \f$ - * for a segment with total group cross-section and for - * some polar angle. - * @param sigma_t the total group cross-section at this energy - * @param length the length of the line segment projected in the xy-plane - * @param _exp_table the exponential linear interpolation table - * @param p the polar angle index - * @return the evaluated exponential - */ -__device__ FP_PRECISION computeExponential(FP_PRECISION sigma_t, - FP_PRECISION length, - FP_PRECISION* _exp_table, - int p) { - - FP_PRECISION exponential; - FP_PRECISION tau = sigma_t * length; - - /* Evaluate the exponential using the linear interpolation table */ - if (*interpolate_exponential) { - int index; - - index = round_to_int(tau * (*inverse_exp_table_spacing)); - index *= (*two_times_num_polar); - exponential = (1. - (_exp_table[index+2 * p] * tau + - _exp_table[index + 2 * p +1])); - } - - /* Evalute the exponential using the intrinsic exp(...) function */ - else { - FP_PRECISION sintheta = sinthetas[p]; - #ifdef SINGLE - exponential = 1.0 - __expf(- tau / sintheta); - #else - exponential = 1.0 - exp(- tau / sintheta); - #endif - } - - return exponential; -} - - -/** - * @brief Computes the contribution to the FSR scalar flux from a Track segment - * in a single energy group on the GPU. + * @brief Computes the contribution to the FSR scalar flux from a Track + * segment in a single energy group. * @details This method integrates the angular flux for a Track segment across * energy groups and polar angles, and tallies it into the FSR scalar * flux, and updates the Track's angular flux. @@ -409,23 +431,21 @@ __device__ FP_PRECISION computeExponential(FP_PRECISION sigma_t, * @param track_flux a pointer to the Track's angular flux * @param reduced_sources the array of FSR sources / total xs * @param polar_weights the array of polar Quadrature weights - * @param _exp_table the exponential interpolation table * @param scalar_flux the array of FSR scalar fluxes */ -__device__ void scalarFluxTally(dev_segment* curr_segment, +__device__ void tallyScalarFlux(dev_segment* curr_segment, int azim_index, int energy_group, dev_material* materials, FP_PRECISION* track_flux, FP_PRECISION* reduced_sources, FP_PRECISION* polar_weights, - FP_PRECISION* _exp_table, FP_PRECISION* scalar_flux) { int fsr_id = curr_segment->_region_uid; FP_PRECISION length = curr_segment->_length; dev_material* curr_material = &materials[curr_segment->_material_index]; - FP_PRECISION *sigma_t = curr_material->_sigma_t; + FP_PRECISION* sigma_t = curr_material->_sigma_t; /* The change in angular flux long this Track segment in this FSR */ FP_PRECISION delta_psi; @@ -434,14 +454,12 @@ __device__ void scalarFluxTally(dev_segment* curr_segment, /* Zero the FSR scalar flux contribution from this segment and energy group */ FP_PRECISION fsr_flux = 0.0; - /* Compute the exponential interpolation table index */ - /* Loop over polar angles */ for (int p=0; p < *num_polar; p++) { - exponential = computeExponential(sigma_t[energy_group], - length, _exp_table, p); - delta_psi = (track_flux[p] - reduced_sources(fsr_id,energy_group)) * - exponential; + exponential = + exp_evaluator.computeExponential(sigma_t[energy_group] * length, p); + delta_psi = (track_flux[p] - reduced_sources(fsr_id,energy_group)); + delta_psi *= exponential; fsr_flux += delta_psi * polar_weights(azim_index,p); track_flux[p] -= delta_psi; } @@ -452,17 +470,16 @@ __device__ void scalarFluxTally(dev_segment* curr_segment, /** - * @brief Updates the boundary flux for a Track given boundary conditions - * on the GPU. - * @details For reflective boundary conditions, the outgoing boundary flux - * for the Track is given to the reflecting track. For vacuum - * boundary conditions, the outgoing flux tallied as leakage. - * Note: Only one energy group is transferred by this routine. + * @brief Updates the boundary flux for a Track given boundary conditions. + * @details For reflective and periodic boundary conditions, the outgoing + * boundary flux for the Track is given to the corresponding reflecting + * or periodic Track. For vacuum boundary conditions, the outgoing flux + * is tallied as leakage. Note: Only one energy group is transferred + * by this routine. * @param curr_track a pointer to the Track of interest * @param azim_index a pointer to the azimuthal angle index for this segment * @param track_flux an array of the outgoing Track flux * @param boundary_flux an array of all angular fluxes - * @param leakage an array of leakages for each CUDA thread * @param polar_weights an array of polar Quadrature weights * @param energy_angle_index the energy group index * @param direction the Track direction (forward - true, reverse - false) @@ -471,56 +488,47 @@ __device__ void transferBoundaryFlux(dev_track* curr_track, int azim_index, FP_PRECISION* track_flux, FP_PRECISION* boundary_flux, - FP_PRECISION* leakage, FP_PRECISION* polar_weights, int energy_angle_index, bool direction) { int start = energy_angle_index; - bool bc; + bool transfer_flux; int track_out_id; - /* Extract boundary conditions for this Track and the pointer to the - * outgoing reflective Track, and index into the leakage array */ - /* For the "forward" direction */ if (direction) { - bc = curr_track->_bc_out; + transfer_flux = curr_track->_transfer_flux_out; track_out_id = curr_track->_track_out; - start += curr_track->_refl_out * (*polar_times_groups); + start += curr_track->_next_out * (*polar_times_groups); } /* For the "reverse" direction */ else { - bc = curr_track->_bc_in; + transfer_flux = curr_track->_transfer_flux_in; track_out_id = curr_track->_track_in; - start += curr_track->_refl_in * (*polar_times_groups); + start += curr_track->_next_in * (*polar_times_groups); } FP_PRECISION* track_out_flux = &boundary_flux(track_out_id,start); /* Put Track's flux in the shared memory temporary flux array */ - for (int p=0; p < *num_polar; p++) { - track_out_flux[p] = track_flux[p] * bc; - leakage[0] += track_flux[p] * polar_weights(azim_index,p) * (!bc); - } + for (int p=0; p < *num_polar; p++) + track_out_flux[p] = track_flux[p] * transfer_flux; } /** * @brief This method performs one transport sweep of one halfspace of all - * azimuthal angles, tracks, segments, polar angles and energy groups - * on the GPU. + * azimuthal angles, tracks, segments, polar angles and energy groups. * @details The method integrates the flux along each track and updates the * boundary fluxes for the corresponding output Track, while updating * the scalar flux in each FSR. * @param scalar_flux an array of FSR scalar fluxes * @param boundary_flux an array of Track boundary fluxes * @param reduced_sources an array of FSR sources / total xs - * @param leakage an array of angular flux leakaages * @param materials an array of dev_material pointers * @param tracks an array of Tracks - * @param _exp_table an array for the exponential interpolation table * @param tid_offset the Track offset for azimuthal angle halfspace * @param tid_max the upper bound on the Track IDs for this azimuthal * angle halfspace @@ -528,10 +536,8 @@ __device__ void transferBoundaryFlux(dev_track* curr_track, __global__ void transportSweepOnDevice(FP_PRECISION* scalar_flux, FP_PRECISION* boundary_flux, FP_PRECISION* reduced_sources, - FP_PRECISION* leakage, dev_material* materials, dev_track* tracks, - FP_PRECISION* _exp_table, int tid_offset, int tid_max) { @@ -575,14 +581,12 @@ __global__ void transportSweepOnDevice(FP_PRECISION* scalar_flux, /* Loop over each Track segment in forward direction */ for (int i=0; i < num_segments; i++) { curr_segment = &curr_track->_segments[i]; - scalarFluxTally(curr_segment, azim_index, energy_group, materials, - track_flux, reduced_sources, polar_weights, - _exp_table, scalar_flux); + tallyScalarFlux(curr_segment, azim_index, energy_group, materials, + track_flux, reduced_sources, polar_weights, scalar_flux); } /* Transfer boundary angular flux to outgoing Track */ transferBoundaryFlux(curr_track, azim_index, track_flux, boundary_flux, - &leakage[threadIdx.x + blockIdx.x * blockDim.x], polar_weights, energy_angle_index, true); /* Loop over each Track segment in reverse direction */ @@ -590,14 +594,12 @@ __global__ void transportSweepOnDevice(FP_PRECISION* scalar_flux, for (int i=num_segments-1; i > -1; i--) { curr_segment = &curr_track->_segments[i]; - scalarFluxTally(curr_segment, azim_index, energy_group, materials, - track_flux, reduced_sources, polar_weights, - _exp_table, scalar_flux); - } + tallyScalarFlux(curr_segment, azim_index, energy_group, materials, + track_flux, reduced_sources, polar_weights, scalar_flux); + } /* Transfer boundary angular flux to outgoing Track */ transferBoundaryFlux(curr_track, azim_index, track_flux, boundary_flux, - &leakage[threadIdx.x + blockIdx.x * blockDim.x], polar_weights, energy_angle_index, false); /* Update the indices for this thread to the next Track, energy group */ @@ -606,8 +608,6 @@ __global__ void transportSweepOnDevice(FP_PRECISION* scalar_flux, energy_group = tid % (*num_groups); energy_angle_index = energy_group * (*num_polar); } - - return; } @@ -642,71 +642,74 @@ __global__ void addSourceToScalarFluxOnDevice(FP_PRECISION* scalar_flux, /* Iterate over all energy groups */ for (int i=0; i < *num_groups; i++) { scalar_flux(tid,i) *= 0.5; - scalar_flux(tid,i) = FOUR_PI * reduced_sources(tid,i) + - __fdividef(scalar_flux(tid,i), (sigma_t[i] * volume)); + scalar_flux(tid,i) = __fdividef(scalar_flux(tid,i), + (sigma_t[i] * volume)); + scalar_flux(tid,i) += FOUR_PI * reduced_sources(tid,i); } /* Increment thread id */ tid += blockDim.x * gridDim.x; } - - return; } /** - * @brief Computes the volume-weighted, energy integrated fission rate in - * each FSR and stores them in an array indexed by FSR ID on the GPU. - * @details This is a helper method for the - * GPUSolver::computeFSRFissionRates(...) method. - * @param fission_rates an array to store the fission rates - * @param fission_rates an array in which to store the FSR fission rates - * @param FSR_materials an array of FSR material indices - * @param materials an array of dev_material pointers + * @brief Compute the total volume-intergrated fission source from + * all FSRs and energy groups. + * @param FSR_volumes an array of the FSR volumes + * @param FSR_materials an array of the FSR Material indices + * @param materials an array of the dev_material pointers * @param scalar_flux an array of FSR scalar fluxes + * @param fission an array of FSR nu-fission rates */ -__global__ void computeFSRFissionRatesOnDevice(double* fission_rates, +__global__ void computeFSRFissionRatesOnDevice(FP_PRECISION* FSR_volumes, int* FSR_materials, dev_material* materials, - FP_PRECISION* scalar_flux) { + FP_PRECISION* scalar_flux, + FP_PRECISION* fission) { int tid = threadIdx.x + blockIdx.x * blockDim.x; + dev_material* curr_material; - FP_PRECISION* sigma_f; + FP_PRECISION* nu_sigma_f; + FP_PRECISION volume; - /* Loop over all FSRs and compute the volume-weighted fission rate */ + FP_PRECISION fiss = 0.; + + /* Iterate over all FSRs */ while (tid < *num_FSRs) { curr_material = &materials[FSR_materials[tid]]; sigma_f = curr_material->_sigma_f; + volume = FSR_volumes[tid]; - /* Initialize the fission rate for this FSR to zero */ - fission_rates[tid] = 0.0; + FP_PRECISION curr_fiss = 0.; - for (int i=0; i < *num_groups; i++) - fission_rates[tid] += sigma_f[i] * scalar_flux(tid,i); + /* Compute fission rates rates for this thread block */ + for (int e=0; e < *num_groups; e++) + curr_fiss += sigma_f[e] * scalar_flux(tid,e); + + fiss += curr_fiss * volume; /* Increment thread id */ tid += blockDim.x * gridDim.x; } - return; + /* Copy this thread's fission to global memory */ + tid = threadIdx.x + blockIdx.x * blockDim.x; + fission[tid] = fiss; } /** * @brief Constructor initializes arrays for dev_tracks and dev_materials.. - * @details The constructor retrieves the number of energy groups and FSRs - * and azimuthal angles from the Geometry and TrackGenerator if - * passed in as parameters by the user. The constructor initalizes - * the number of CUDA threads and thread blocks each to a default - * of 64. - * @param geometry an optional pointer to the Geometry + * @details The constructor initalizes the number of CUDA threads and thread + * blocks each to a default of 64. * @param track_generator an optional pointer to the TrackjGenerator */ -GPUSolver::GPUSolver(Geometry* geometry, TrackGenerator* track_generator) : +GPUSolver::GPUSolver(TrackGenerator* track_generator) : - Solver(geometry, track_generator) { + Solver(track_generator) { /* The default number of thread blocks and threads per thread block */ _B = 64; @@ -716,14 +719,6 @@ GPUSolver::GPUSolver(Geometry* geometry, TrackGenerator* track_generator) : _dev_tracks = NULL; _FSR_materials = NULL; - _total = NULL; - _fission = NULL; - _scatter = NULL; - _leakage = NULL; - - if (geometry != NULL) - setGeometry(geometry); - if (track_generator != NULL) setTrackGenerator(track_generator); } @@ -755,60 +750,12 @@ GPUSolver::~GPUSolver() { _dev_tracks = NULL; } - if (_boundary_flux != NULL) { - cudaFree(_boundary_flux); - _boundary_flux = NULL; - } - - if (_scalar_flux != NULL) { - cudaFree(_scalar_flux); - _scalar_flux = NULL; - } - - if (_old_fission_sources != NULL) { - cudaFree(_old_fission_sources); - _old_fission_sources = NULL; - } - - if (_reduced_sources != NULL) { - cudaFree(_reduced_sources); - _reduced_sources = NULL; - } - - if (_fission_sources != NULL) { - _fission_sources_vec.clear(); - _fission_sources = NULL; - } - - if (_total != NULL) { - _total_vec.clear(); - _total = NULL; - } - - if (_fission != NULL) { - _fission_vec.clear(); - _fission = NULL; - } - - if (_scatter != NULL) { - _scatter_vec.clear(); - _scatter = NULL; - } - - if (_source_residuals != NULL) { - _source_residuals_vec.clear(); - _source_residuals = NULL; - } - - if (_leakage != NULL) { - _leakage_vec.clear(); - _leakage = NULL; - } - - if (_exp_table != NULL) { - cudaFree(_exp_table); - _exp_table = NULL; - } + /* Clear Thrust vectors's memory on the device */ + _boundary_flux.clear(); + _scalar_flux.clear(); + _old_scalar_flux.clear(); + _fixed_sources.clear(); + _reduced_sources.clear(); } @@ -831,125 +778,70 @@ int GPUSolver::getNumThreadsPerBlock() { /** - * @brief Returns the FSR scalar flux for some energy group. + * @brief Returns the source for some energy group for a flat source region + * @details This is a helper routine used by the openmoc.process module. * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest + * @param group the energy group of interest + * @return the flat source region source */ -FP_PRECISION GPUSolver::getFSRScalarFlux(int fsr_id, int energy_group) { +FP_PRECISION GPUSolver::getFSRSource(int fsr_id, int group) { - /* Error checking */ if (fsr_id >= _num_FSRs) - log_printf(ERROR, "Unable to return a scalar flux for FSR id = %d in energy" - " group %d since the solver only contains FSR with IDs greater " - "than or equal to %d", fsr_id, energy_group, _num_FSRs-1); - - if (fsr_id < 0) - log_printf(ERROR, "Unable to return a scalar flux for FSR id = %d in energy" - " group %d since FSRs do not have negative IDs", - fsr_id, energy_group); - - if (energy_group-1 >= _num_groups) - log_printf(ERROR, "Unable to return a scalar flux for FSR id = %d in energy" - " group %d since the solver only has %d energy groups", - fsr_id, energy_group, _num_groups); - - if (energy_group <= 0) - log_printf(ERROR, "Unable to return a scalar flux for FSR id = %d in energy" - " group %d since energy groups are greater than 1", - fsr_id, energy_group); - - /* Copy the scalar flux for this FSR and energy group from the device */ - FP_PRECISION fsr_scalar_flux; - int flux_index = fsr_id * _num_groups + (energy_group - 1); - cudaMemcpy((void*)&fsr_scalar_flux, (void*)&_scalar_flux[flux_index], - sizeof(FP_PRECISION), cudaMemcpyDeviceToHost); - - return fsr_scalar_flux; -} - - -/** - * @brief Return the scalar flux array indexed by FSR IDs and energy groups. - * which contains the corresponding fluxes for each flat source region. - * @return an array of FSR scalar fluxes - */ -FP_PRECISION* GPUSolver::getFSRScalarFluxes() { + log_printf(ERROR, "Unable to return a source for FSR ID = %d " + "since the max FSR ID = %d", fsr_id, _num_FSRs-1); - if (_scalar_flux == NULL) - log_printf(ERROR, "Unable to returns the GPUSolver's scalar flux " - "array since it has not yet been allocated in memory"); - - /* Copy the scalar flux for all FSRs from the device to the host */ - FP_PRECISION* fsr_scalar_fluxes = new FP_PRECISION[_num_FSRs * _num_groups]; - cudaMemcpy((void*)fsr_scalar_fluxes, (void*)_scalar_flux, - _num_FSRs * _num_groups * sizeof(FP_PRECISION), - cudaMemcpyDeviceToHost); - - return fsr_scalar_fluxes; -} - - -/** - * @brief Returns the FSR source for some energy group. - * @param fsr_id the ID for the FSR of interest - * @param energy_group the energy group of interest - */ -FP_PRECISION GPUSolver::getFSRSource(int fsr_id, int energy_group) { - - /* Error checking */ - if (fsr_id >= _num_FSRs) - log_printf(ERROR, "Unable to return a source for FSR id = %d in energy" - " group %d since the solver only contains FSR with IDs greater than " - "or equal to %d", fsr_id, energy_group, _num_FSRs-1); + else if (fsr_id < 0) + log_printf(ERROR, "Unable to return a source for FSR ID = %d " + "since FSRs do not have negative IDs", fsr_id); - if (fsr_id < 0) - log_printf(ERROR, "Unable to return a source for FSR id = %d in energy" - " group %d since FSRs do not have negative IDs", - fsr_id, energy_group); + else if (group-1 >= _num_groups) + log_printf(ERROR, "Unable to return a source in group %d " + "since there are only %d groups", group, _num_groups); - if (energy_group-1 >= _num_groups) - log_printf(ERROR, "Unable to return a source for FSR id = %d in energy" - " group %d since the solver only has %d energy groups", - fsr_id, energy_group, _num_groups); + else if (group <= 0) + log_printf(ERROR, "Unable to return a source in group %d " + "since groups must be greater or equal to 1", group); - if (energy_group <= 0) - log_printf(ERROR, "Unable to return a source for FSR id = %d in energy" - " group %d since energy groups are greater than 1", - fsr_id, energy_group); + else if (_scalar_flux.size() == 0) + log_printf(ERROR, "Unable to return a source " + "since it has not yet been computed"); /* Get host material */ Material* host_material = _geometry->findFSRMaterial(fsr_id); /* Get cross sections and scalar flux */ - FP_PRECISION* nu_sigma_f = host_material->getNuSigmaF(); FP_PRECISION* sigma_s = host_material->getSigmaS(); - FP_PRECISION* chi = host_material->getChi(); + FP_PRECISION* fiss_mat = host_material->getFissionMatrix(); + FP_PRECISION* fsr_scalar_fluxes = new FP_PRECISION[_num_groups]; - cudaMemcpy((void*)fsr_scalar_fluxes, (void*)&_scalar_flux[fsr_id*_num_groups], + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + cudaMemcpy((void*)fsr_scalar_fluxes, (void*)&scalar_flux[fsr_id*_num_groups], _num_groups * sizeof(FP_PRECISION), cudaMemcpyDeviceToHost); - /* Initialize variables */ FP_PRECISION fission_source = 0.0; FP_PRECISION scatter_source = 0.0; FP_PRECISION total_source; - /* Compute total fission source for current region */ - for (int e=0; e < _num_groups; e++){ - fission_source += fsr_scalar_fluxes[e] * nu_sigma_f[e]; + /* Compute total scattering and fission sources for this FSR */ + for (int g=0; g < _num_groups; g++) { + scatter_source += sigma_s[(group-1)*(_num_groups)+g] + * fsr_scalar_fluxes[g]; + fission_source += fiss_mat[(group-1)*(_num_groups)+g] + * fsr_scalar_fluxes[g]; } fission_source /= _k_eff; - /* Compute total scattering source for this FSR */ - for (int g=0; g < _num_groups; g++){ - scatter_source += sigma_s[(energy_group-1)*(_num_groups)+g] - * fsr_scalar_fluxes[g]; - } - /* Compute the total source */ - total_source = (fission_source * chi[energy_group-1] + scatter_source) * - ONE_OVER_FOUR_PI; + total_source = fission_source + scatter_source; + + /* Add in fixed source (if specified by user) */ + total_source += _fixed_sources(fsr_id,group-1); + + /* Normalize to solid angle for isotropic approximation */ + total_source *= ONE_OVER_FOUR_PI; delete [] fsr_scalar_fluxes; @@ -957,6 +849,73 @@ FP_PRECISION GPUSolver::getFSRSource(int fsr_id, int energy_group) { } +/** + * @brief Returns the scalar flux for some FSR and energy group. + * @param fsr_id the ID for the FSR of interest + * @param group the energy group of interest + * @return the FSR scalar flux + */ +FP_PRECISION GPUSolver::getFlux(int fsr_id, int group) { + + if (fsr_id >= _num_FSRs) + log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " + "since the max FSR ID = %d", fsr_id, _num_FSRs-1); + + else if (fsr_id < 0) + log_printf(ERROR, "Unable to return a scalar flux for FSR ID = %d " + "since FSRs do not have negative IDs", fsr_id); + + else if (group-1 >= _num_groups) + log_printf(ERROR, "Unable to return a scalar flux in group %d " + "since there are only %d groups", group, _num_groups); + + else if (group <= 0) + log_printf(ERROR, "Unable to return a scalar flux in group %d " + "since groups must be greater or equal to 1", group); + + if (_scalar_flux.size() == 0) + log_printf(ERROR, "Unable to return a scalar flux " + "since it has not yet been computed"); + + return _scalar_flux(fsr_id,group-1); +} + + +/** + * @brief Fills an array with the scalar fluxes on the GPU. + * @details This class method is a helper routine called by the OpenMOC + * Python "openmoc.krylov" module for Krylov subspace methods. + * Although this method appears to require two arguments, in + * reality it only requires one due to SWIG and would be called + * from within Python as follows: + * + * @code + * num_fluxes = num_groups * num_FSRs + * fluxes = solver.getFluxes(num_fluxes) + * @endcode + * + * @param fluxes an array of FSR scalar fluxes in each energy group + * @param num_fluxes the total number of FSR flux values + */ +void GPUSolver::getFluxes(FP_PRECISION* out_fluxes, int num_fluxes) { + + if (num_fluxes != _num_groups * _num_FSRs) + log_printf(ERROR, "Unable to get FSR scalar fluxes since there are " + "%d groups and %d FSRs which does not match the requested " + "%d flux values", _num_groups, _num_FSRs, num_fluxes); + + else if (_scalar_flux.size() == 0) + log_printf(ERROR, "Unable to get FSR scalar fluxes since they " + "have not yet been allocated on the device"); + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + + /* Copy the fluxes from the GPU to the input array */ + cudaMemcpy((void*)out_fluxes, (void*)scalar_flux, + num_fluxes * sizeof(FP_PRECISION), cudaMemcpyDeviceToHost); +} + /** * @brief Sets the number of thread blocks (>0) for CUDA kernels. @@ -987,43 +946,41 @@ void GPUSolver::setNumThreadsPerBlock(int num_threads) { /** - * @brief Sets the Geometry pointer for the GPUSolver. - * @details The Geometry must already have initialized FSR offset maps - * and segmentized the TrackGenerator's tracks. Each of these - * should be initiated in Python prior to assigning a Geometry - * to the GPUSolver: - * - * @code - * geometry.initializeFlatSourceRegions() - * track_generator.generateTracks() - * @endcode - * - * @param geometry a pointer to a Geometry + * @brief Sets the Geometry for the Solver. + * @details This is a private setter method for the Solver and is not + * intended to be called by the user. + * @param geometry a pointer to a Geometry object */ void GPUSolver::setGeometry(Geometry* geometry) { Solver::setGeometry(geometry); - initializeMaterials(); + std::map host_materials=_geometry->getAllMaterials(); + std::map::iterator iter; + int material_index = 0; - /* Copy the number of energy groups to constant memory on the GPU */ - cudaMemcpyToSymbol(num_groups, (void*)&_num_groups, sizeof(int), 0, - cudaMemcpyHostToDevice); + /* Iterate through all Materials and clone them as dev_material structs + * on the device */ + for (iter=host_materials.begin(); iter != host_materials.end(); ++iter) { + _material_IDs_to_indices[iter->second->getId()] = material_index; + material_index++; + } } /** - * @brief Sets the TrackGenerator with characteristic tracks for the GPUSolver. + * @brief Sets the Solver's TrackGenerator with characteristic Tracks. * @details The TrackGenerator must already have generated Tracks and have * used ray tracing to segmentize them across the Geometry. This * should be initated in Python prior to assigning the TrackGenerator - * to the GPUSolver: + * to the Solver: * * @code * track_generator.generateTracks() + * solver.setTrackGenerator(track_generator) * @endcode * - * @param track_generator a pointer to a TrackGenerator + * @param track_generator a pointer to a TrackGenerator object */ void GPUSolver::setTrackGenerator(TrackGenerator* track_generator) { Solver::setTrackGenerator(track_generator); @@ -1032,24 +989,65 @@ void GPUSolver::setTrackGenerator(TrackGenerator* track_generator) { /** - * @brief Creates a polar Quadrature object for the GPUSolver on the GPU. + * @brief Set the flux array for use in transport sweep source calculations. + * @detail This is a helper method for the checkpoint restart capabilities, + * as well as the IRAMSolver in the openmoc.krylov submodule. This + * routine may be used as follows from within Python: + * + * @code + * num_FSRs = solver.getGeometry.getNumFSRs() + * num_groups = solver.getGeometry.getNumEnergyGroups() + * fluxes = numpy.random.rand(num_FSRs * num_groups, dtype=np.float) + * solver.setFluxes(fluxes) + * @endcode + * + * NOTE: This routine stores a pointer to the fluxes for the Solver + * to use during transport sweeps and other calculations. Hence, the + * flux array pointer is shared between NumPy and the Solver. + * + * @param in_fluxes an array with the fluxes to use + * @param num_fluxes the number of flux values (# groups x # FSRs) + */ +void GPUSolver::setFluxes(FP_PRECISION* in_fluxes, int num_fluxes) { + if (num_fluxes != _num_groups * _num_FSRs) + log_printf(ERROR, "Unable to set an array with %d flux values for %d " + " groups and %d FSRs", num_fluxes, _num_groups, _num_FSRs); + + /* Allocate array if flux arrays have not yet been initialized */ + if (_scalar_flux.size() == 0) + initializeFluxArrays(); + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + + /* Copy the input fluxes onto the GPU */ + cudaMemcpy((void*)scalar_flux, (void*)in_fluxes, + num_fluxes * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); + _user_fluxes = true; +} + + +/** + * @brief Creates a polar quadrature object for the GPUSolver on the GPU. */ void GPUSolver::initializePolarQuadrature() { log_printf(INFO, "Initializing polar quadrature on the GPU..."); - /* Deletes the old Quadrature if one existed */ - if (_quad != NULL) - delete _quad; + Solver::initializePolarQuadrature(); - _quad = new Quadrature(_quadrature_type, _num_polar); - _polar_times_groups = _num_groups * _num_polar; + if (_num_polar > MAX_POLAR_ANGLES_GPU) + log_printf(ERROR, "Unable to initialize a polar quadrature with %d " + "angles for the GPUSolver which is limited to %d polar " + "angles. Update the MAX_POLAR_ANGLES_GPU macro in constants.h " + "and recompile.", _num_polar, MAX_POLAR_ANGLES_GPU); /* Copy the number of polar angles to constant memory on the GPU */ cudaMemcpyToSymbol(num_polar, (void*)&_num_polar, sizeof(int), 0, cudaMemcpyHostToDevice); /* Copy twice the number of polar angles to constant memory on the GPU */ + _two_times_num_polar = 2 * _num_polar; cudaMemcpyToSymbol(two_times_num_polar, (void*)&_two_times_num_polar, sizeof(int), 0, cudaMemcpyHostToDevice); @@ -1058,24 +1056,37 @@ void GPUSolver::initializePolarQuadrature() { cudaMemcpyToSymbol(polar_times_groups, (void*)&_polar_times_groups, sizeof(int), 0, cudaMemcpyHostToDevice); - /* Compute polar times azimuthal angle weights */ - if (_polar_weights != NULL) - delete [] _polar_weights; + /* Copy the polar weights to constant memory on the GPU */ + cudaMemcpyToSymbol(polar_weights, (void*)_polar_weights, + _num_polar * _num_azim * sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); + + /* Copy the sines of the polar angles which is needed if the user + * requested the use of the exp intrinsic to evaluate exponentials */ + cudaMemcpyToSymbol(sin_thetas, (void*)_polar_quad->getSinThetas(), + _num_polar * sizeof(FP_PRECISION), 0, + cudaMemcpyHostToDevice); +} - _polar_weights = - (FP_PRECISION*)malloc(_num_polar * _num_azim * sizeof(FP_PRECISION)); - FP_PRECISION* multiples = _quad->getMultiples(); - FP_PRECISION* azim_weights = _track_generator->getAzimWeights(); +/** + * @brief Initializes new GPUExpEvaluator object to compute exponentials. + */ +void GPUSolver::initializeExpEvaluator() { - for (int i=0; i < _num_azim; i++) { - for (int j=0; j < _num_polar; j++) - _polar_weights[i*_num_polar+j] = azim_weights[i]*multiples[j]*FOUR_PI; - } + Solver::initializeExpEvaluator(); - /* Copy the polar weights to constant memory on the GPU */ - cudaMemcpyToSymbol(polar_weights, (void*)_polar_weights, - _num_polar * _num_azim * sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); + log_printf(INFO, "Initializing the exponential evaluator on the GPU..."); + + /* Allocate memory for a GPUExpEvaluator on the device */ + GPUExpEvaluator* dev_exp_evaluator; + cudaMalloc((void**)&dev_exp_evaluator, sizeof(GPUExpEvaluator)); + + /* Clone ExpEvaluator from the host into GPUExpEvaluator on the device */ + clone_exp_evaluator(_exp_evaluator, dev_exp_evaluator); + + /* Copy the GPUExpEvaluator into constant memory on the GPU */ + cudaMemcpyToSymbol(exp_evaluator, (void*)dev_exp_evaluator, + sizeof(GPUExpEvaluator), 0, cudaMemcpyDeviceToDevice); } @@ -1087,71 +1098,43 @@ void GPUSolver::initializePolarQuadrature() { */ void GPUSolver::initializeFSRs() { - log_printf(INFO, "Initializing FSRs on the GPU..."); + log_printf(NORMAL, "Initializing FSRs on the GPU..."); /* Delete old FSRs array if it exists */ - if (_FSR_volumes != NULL) + if (_FSR_volumes != NULL) { cudaFree(_FSR_volumes); + _FSR_volumes = NULL; + } - if (_FSR_materials != NULL) + if (_FSR_materials != NULL) { cudaFree(_FSR_materials); + _FSR_materials = NULL; + } + + Solver::initializeFSRs(); /* Allocate memory for all FSR volumes and dev_materials on the device */ try{ + /* Store pointers to arrays of FSR data created on the host by the + * the parent class Solver::initializeFSRs() routine */ + FP_PRECISION* host_FSR_volumes = _FSR_volumes; + int* host_FSR_materials = _FSR_materials; + /* Allocate memory on device for FSR volumes and Material indices */ cudaMalloc((void**)&_FSR_volumes, _num_FSRs * sizeof(FP_PRECISION)); cudaMalloc((void**)&_FSR_materials, _num_FSRs * sizeof(int)); - /* Create a temporary FSR array to populate and then copy to device */ - FP_PRECISION* temp_FSR_volumes = new FP_PRECISION[_num_FSRs]; - - /* Create a temporary FSR to material indices array to populate and then - * copy to device */ + /* Create a temporary FSR to material indices array */ int* FSRs_to_material_indices = new int[_num_FSRs]; - /* Initialize num fissionable FSRs counter */ - _num_fissionable_FSRs = 0; - /* Populate FSR Material indices array */ - for (int i = 0; i < _num_FSRs; i++){ + for (int i = 0; i < _num_FSRs; i++) FSRs_to_material_indices[i] = _material_IDs_to_indices[_geometry-> findFSRMaterial(i)->getId()]; - if (_geometry->findFSRMaterial(i)->isFissionable()) - _num_fissionable_FSRs++; - } - - /* Initialize each FSRs volume to 0 to avoid NaNs */ - memset(temp_FSR_volumes, FP_PRECISION(0.), _num_FSRs*sizeof(FP_PRECISION)); - - Track* track; - int num_segments; - segment* curr_segment; - segment* segments; - FP_PRECISION volume; - - FP_PRECISION* azim_weights = _track_generator->getAzimWeights(); - /* Set each FSR's volume by accumulating the total length of all Tracks - * inside the FSR. Iterate over azimuthal angle, Track, Track segment*/ - for (int i=0; i < _num_azim; i++) { - for (int j=0; j < _num_tracks[i]; j++) { - - track = &_track_generator->getTracks()[i][j]; - num_segments = track->getNumSegments(); - segments = track->getSegments(); - - /* Iterate over the Track's segments to update FSR volumes */ - for (int s = 0; s < num_segments; s++) { - curr_segment = &segments[s]; - volume = curr_segment->_length * azim_weights[i]; - temp_FSR_volumes[curr_segment->_region_id] += volume; - } - } - } - - /* Copy the temporary array of FSRs to the device */ - cudaMemcpy((void*)_FSR_volumes, (void*)temp_FSR_volumes, + /* Copy the arrays of FSR data to the device */ + cudaMemcpy((void*)_FSR_volumes, (void*)host_FSR_volumes, _num_FSRs * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); cudaMemcpy((void*)_FSR_materials, (void*)FSRs_to_material_indices, _num_FSRs * sizeof(int), cudaMemcpyHostToDevice); @@ -1160,34 +1143,39 @@ void GPUSolver::initializeFSRs() { cudaMemcpyToSymbol(num_FSRs, (void*)&_num_FSRs, sizeof(int), 0, cudaMemcpyHostToDevice); - /* Free the temporary array of FSR volumes on the host */ - free(temp_FSR_volumes); + /* Free the array of FSRs data allocated by the Solver parent class */ + free(host_FSR_volumes); + free(host_FSR_materials); /* Free the temporary array of FSRs to material indices on the host */ free(FSRs_to_material_indices); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's FSRs " - "on the device. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for FSRs on GPU"); } - - initializeThrustVectors(); } /** - * @brief Allocates data on the GPU for all Materials data. + * @brief Allocates all Materials data on the GPU. * @details This method loops over the materials in the host_materials map. - * Since cuda does not support std::map data types on the device (GPU), + * Since CUDA does not support std::map data types on the device, * the materials map must be converted to an array and a map created * that maps a material ID to an indice in the new materials array. In * initializeTracks, this map is used to convert the Material ID * associated with every segment to an index in the materials array. + * @param mode the solution type (FORWARD or ADJOINT) */ -void GPUSolver::initializeMaterials() { +void GPUSolver::initializeMaterials(solverMode mode) { + + Solver::initializeMaterials(mode); log_printf(INFO, "Initializing materials on the GPU..."); + /* Copy the number of energy groups to constant memory on the GPU */ + cudaMemcpyToSymbol(num_groups, (void*)&_num_groups, sizeof(int), 0, + cudaMemcpyHostToDevice); + /* Delete old materials array if it exists */ if (_materials != NULL) cudaFree(_materials); @@ -1198,25 +1186,23 @@ void GPUSolver::initializeMaterials() { std::map host_materials=_geometry->getAllMaterials(); std::map::iterator iter; int material_index = 0; - + /* Iterate through all Materials and clone them as dev_material structs * on the device */ cudaMalloc((void**)&_materials, _num_materials * sizeof(dev_material)); - for (iter=host_materials.begin(); iter != host_materials.end(); ++iter){ - clone_material_on_gpu(iter->second, &_materials[material_index]); - _material_IDs_to_indices[iter->second->getId()] = material_index; + for (iter=host_materials.begin(); iter != host_materials.end(); ++iter) { + clone_material(iter->second, &_materials[material_index]); material_index++; } } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's " - "dev_materials. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for Materials on GPU"); } } /** - * @brief Allocates memory on the GPU for all Tracks in the simulation. + * @brief Allocates memory for all Tracks on the GPU */ void GPUSolver::initializeTracks() { @@ -1237,25 +1223,18 @@ void GPUSolver::initializeTracks() { for (int i=0; i < _tot_num_tracks; i++) { - clone_track_on_gpu(_tracks[i], &_dev_tracks[i], _material_IDs_to_indices); + clone_track(_tracks[i], &_dev_tracks[i], _material_IDs_to_indices); - /* Make Track reflective */ - index = computeScalarTrackIndex(_tracks[i]->getTrackInI(), - _tracks[i]->getTrackInJ()); + /* Get indices to next tracks along "forward" and "reverse" directions */ + index = _tracks[i]->getTrackIn()->getUid(); cudaMemcpy((void*)&_dev_tracks[i]._track_in, (void*)&index, sizeof(int), cudaMemcpyHostToDevice); - index = computeScalarTrackIndex(_tracks[i]->getTrackOutI(), - _tracks[i]->getTrackOutJ()); + index = _tracks[i]->getTrackOut()->getUid(); cudaMemcpy((void*)&_dev_tracks[i]._track_out, (void*)&index, sizeof(int), cudaMemcpyHostToDevice); } - /* Copy the array of number of Tracks for each azimuthal angle into - * constant memory on GPU */ - cudaMemcpyToSymbol(num_tracks, (void*)_num_tracks, - _num_azim * sizeof(int), 0, cudaMemcpyHostToDevice); - /* Copy the total number of Tracks into constant memory on GPU */ cudaMemcpyToSymbol(tot_num_tracks, (void*)&_tot_num_tracks, sizeof(int), 0, cudaMemcpyHostToDevice); @@ -1263,264 +1242,105 @@ void GPUSolver::initializeTracks() { /* Copy the number of azimuthal angles into constant memory on GPU */ cudaMemcpyToSymbol(num_azim, (void*)&_num_azim, sizeof(int), 0, cudaMemcpyHostToDevice); - - /* Copy the array of number of Tracks for each azimuthal angles into - * constant memory on GPU */ - cudaMemcpyToSymbol(num_tracks, (void*)_num_tracks, - _num_azim * sizeof(int), 0, cudaMemcpyHostToDevice); - - /* Copy the total number of Tracks into constant memory on GPU */ - cudaMemcpyToSymbol(tot_num_tracks, (void*)&_tot_num_tracks, - sizeof(int), 0, cudaMemcpyHostToDevice); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's " - "dev_tracks on the device. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for Tracks on GPU"); } } /** - * @brief Allocates memory for Track boundary angular fluxes and leakages - * and FSR scalar fluxes on the GPU. - * @details Deletes memory for old flux arrays if they were allocated for a + * @brief Allocates memory for Track boundary angular and FSR scalar fluxes. + * @details Deletes memory for old flux vectors if they were allocated for a * previous simulation. */ void GPUSolver::initializeFluxArrays() { - log_printf(INFO, "Initializing flux arrays on the GPU..."); + log_printf(INFO, "Initializing flux vectors on the GPU..."); - /* Delete old flux arrays if they exist */ - if (_boundary_flux != NULL) - cudaFree(_boundary_flux); - - if (_scalar_flux != NULL) - cudaFree(_scalar_flux); + /* Clear Thrust vectors' memory if previously allocated */ + _boundary_flux.clear(); + _scalar_flux.clear(); + _old_scalar_flux.clear(); /* Allocate memory for all flux arrays on the device */ try{ - cudaMalloc((void**)&_boundary_flux, - 2*_tot_num_tracks * _polar_times_groups*sizeof(FP_PRECISION)); - cudaMalloc((void**)&_scalar_flux, - _num_FSRs * _num_groups * sizeof(FP_PRECISION)); + int size = 2 * _tot_num_tracks * _polar_times_groups; + _boundary_flux.resize(size); + + size = _num_FSRs * _num_groups; + _scalar_flux.resize(size); + _old_scalar_flux.resize(size); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's fluxes " - "on the device. Backtrace:%s", e.what()); + log_printf(ERROR, "Could not allocate memory for fluxes on GPU"); } } /** - * @brief Allocates memory for FSR source arrays on the GPU. - * @details Deletes memory for old source arrays if they were allocated for a - * previous simulation. + * @brief Allocates memory for FSR source vectors on the GPU. + * @details Deletes memory for old source vectors if they were allocated + * for a previous simulation. */ void GPUSolver::initializeSourceArrays() { - log_printf(INFO, "Initializing source arrays on the GPU..."); + log_printf(INFO, "Initializing source vectors on the GPU..."); - /* Delete old sources arrays if they exist */ - if (_old_fission_sources != NULL) - cudaFree(_old_fission_sources); + /* Clear Thrust vectors' memory if previously allocated */ + _reduced_sources.clear(); + _fixed_sources.clear(); - if (_reduced_sources != NULL) - cudaFree(_reduced_sources); + int size = _num_FSRs * _num_groups; /* Allocate memory for all source arrays on the device */ try{ - - cudaMalloc((void**)&_old_fission_sources, - _num_FSRs * sizeof(FP_PRECISION)); - - cudaMalloc((void**)&_reduced_sources, - _num_FSRs * _num_groups * sizeof(FP_PRECISION)); + _reduced_sources.resize(size); + _fixed_sources.resize(size); } catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's FSR " - "sources array on the device. Backtrace:%s", e.what()); - } -} - - -/** - * @brief Initialize Thrust vectors for the fission and absorption rates, - * source residuals, leakage and fission sources. - */ -void GPUSolver::initializeThrustVectors() { - - log_printf(INFO, "Initializing Thrust vectors on the GPU..."); - - /* Delete old vectors if they exist */ - if (_fission_sources != NULL) { - _fission_sources = NULL; - _fission_sources_vec.clear(); - } - - if (_total != NULL) { - _total = NULL; - _total_vec.clear(); - } - - if (_fission != NULL) { - _fission = NULL; - _fission_vec.clear(); - } - - if (_scatter != NULL) { - _scatter = NULL; - _scatter_vec.clear(); + log_printf(ERROR, "Could not allocate memory for sources on GPU"); } - if (_source_residuals != NULL) { - _source_residuals = NULL; - _source_residuals_vec.clear(); - } + /* Initialize fixed sources to zero */ + thrust::fill(_fixed_sources.begin(), _fixed_sources.end(), 0.0); - if (_leakage != NULL) { - _leakage = NULL; - _leakage_vec.clear(); - } - - /* Allocate memory for fission, absorption and source vectors on device */ - try{ - /* Allocate fission source array on device */ - _fission_sources_vec.resize(_B * _T); - _fission_sources = thrust::raw_pointer_cast(&_fission_sources_vec[0]); - - /* Allocate total reaction rate array on device */ - _total_vec.resize(_B * _T); - _total = thrust::raw_pointer_cast(&_total_vec[0]); - - /* Allocate fission reaction rate array on device */ - _fission_vec.resize(_B * _T); - _fission = thrust::raw_pointer_cast(&_fission_vec[0]); - - /* Allocate scattering reaction rate array on device */ - _scatter_vec.resize(_B * _T); - _scatter = thrust::raw_pointer_cast(&_scatter_vec[0]); - - /* Allocate source residual array on device */ - _source_residuals_vec.resize(_B * _T); - _source_residuals = thrust::raw_pointer_cast(&_source_residuals_vec[0]); - - /* Allocate leakage array on device */ - _leakage_vec.resize(_B * _T); - _leakage = thrust::raw_pointer_cast(&_leakage_vec[0]); - } - catch(std::exception &e) { - log_printf(ERROR, "Could not allocate memory for the GPUSolver's " - "Thrust vectors. Backtrace:%s", e.what()); - } + /* Fill fixed sources with those assigned by Cell, Material or FSR */ + initializeFixedSources(); } /** - * @brief This method computes the index for the Track j at azimuthal angle i. - * @details This method is necessary since the array of dev_tracks on the device - * is a 1D array which needs a one-to-one mapping from the 2D jagged - * array of Tracks on the host. - * @param i azimuthal angle number - * @param j the jth track at angle i - * @return an index into the device track array + * @brief Populates array of fixed sources assigned by FSR. */ -int GPUSolver::computeScalarTrackIndex(int i, int j) { +void GPUSolver::initializeFixedSources() { - int index =0; - int p = 0; + Solver::initializeFixedSources(); - /* Iterate over each azimuthal angle and increment index by the number of - * Tracks at each angle */ - while (p < i) { - index += _num_tracks[p]; - p++; - } + int fsr_id, group; + std::pair fsr_group_key; + std::map< std::pair, FP_PRECISION >::iterator fsr_iter; - /* Update index for this Track since it is the jth Track at angle i */ - index += j; + /* Populate fixed source array with any user-defined sources */ + for (fsr_iter = _fix_src_FSR_map.begin(); + fsr_iter != _fix_src_FSR_map.end(); ++fsr_iter) { - return index; -} + /* Get the FSR with an assigned fixed source */ + fsr_group_key = fsr_iter->first; + fsr_id = fsr_group_key.first; + group = fsr_group_key.second; + if (group <= 0 || group > _num_groups) + log_printf(ERROR,"Unable to use fixed source for group %d in " + "a %d energy group problem", group, _num_groups); -/** - * @brief Builds a linear interpolation table to compute exponentials for - * each segment of each Track for each polar angle on the GPU. - */ -void GPUSolver::buildExpInterpTable(){ - - log_printf(INFO, "Building exponential interpolation table on device..."); - - /* Copy a boolean indicating whether or not to use the linear interpolation - * table or the exp intrinsic function */ - cudaMemcpyToSymbol(interpolate_exponential,(void*)&_interpolate_exponential, - sizeof(bool), 0, cudaMemcpyHostToDevice); - - /* Copy the sines of the polar angles which is needed if the user - * requested the use of the exp intrinsic to evaluate exponentials */ - cudaMemcpyToSymbol(sinthetas, (void*)_quad->getSinThetas(), - _num_polar * sizeof(FP_PRECISION), 0, - cudaMemcpyHostToDevice); + if (fsr_id < 0 || fsr_id >= _num_FSRs) + log_printf(ERROR,"Unable to use fixed source for FSR %d with only " + "%d FSRs in the geometry", fsr_id, _num_FSRs); - /* Find largest optical path length track segment */ - FP_PRECISION tau = _track_generator->getMaxOpticalLength(); - - /* Expand tau slightly to accomodate track segments which have a - * length very nearly equal to the maximum value */ - tau *= 1.01; - - /* Set size of interpolation table */ - int num_array_values = - tau * sqrt(1. / (8. * _source_convergence_thresh * 1e-2)); - _exp_table_spacing = tau / num_array_values; - _inverse_exp_table_spacing = 1.0 / _exp_table_spacing; - _exp_table_size = _two_times_num_polar * num_array_values; - _exp_table_max_index = _exp_table_size - _two_times_num_polar - 1; - - /* Allocate array for the table */ - if (_exp_table != NULL) - delete [] _exp_table; - - FP_PRECISION* exp_table = new FP_PRECISION[_exp_table_size]; - - FP_PRECISION expon; - FP_PRECISION intercept; - FP_PRECISION slope; - - /* Create exponential interpolation table */ - for (int i = 0; i < num_array_values; i ++){ - for (int p = 0; p < _num_polar; p++){ - expon = exp(- (i * _exp_table_spacing) / _quad->getSinTheta(p)); - slope = - expon / _quad->getSinTheta(p); - intercept = expon * (1 + (i * _exp_table_spacing)/_quad->getSinTheta(p)); - exp_table[_two_times_num_polar * i + 2 * p] = slope; - exp_table[_two_times_num_polar * i + 2 * p + 1] = intercept; - } + _fixed_sources(fsr_id, group-1) = _fix_src_FSR_map[fsr_group_key]; } - - /* Allocate memory for the interpolation table on the device */ - cudaMalloc((void**)&_exp_table, _exp_table_size * sizeof(FP_PRECISION)); - - /* Copy exponential interpolation table to the device */ - cudaMemcpy((void*)_exp_table, (void*)exp_table, - _exp_table_size * sizeof(FP_PRECISION), - cudaMemcpyHostToDevice); - - /* Copy table size and spacing to constant memory on the device */ - cudaMemcpyToSymbol(exp_table_spacing, (void*)&_exp_table_spacing, - sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); - - cudaMemcpyToSymbol(inverse_exp_table_spacing, - (void*)&_inverse_exp_table_spacing, - sizeof(FP_PRECISION), 0, cudaMemcpyHostToDevice); - - cudaMemcpyToSymbol(exp_table_max_index, (void*)&_exp_table_max_index, - sizeof(int), 0, cudaMemcpyHostToDevice); - - free(exp_table); - - return; } @@ -1529,38 +1349,25 @@ void GPUSolver::buildExpInterpTable(){ * angle in the "forward" and "reverse" directions. */ void GPUSolver::zeroTrackFluxes() { - int size = 2 * _tot_num_tracks * _num_polar * _num_groups; - size *= sizeof(FP_PRECISION); - cudaMemset(_boundary_flux, 0.0, size); - return; + thrust::fill(_boundary_flux.begin(), _boundary_flux.end(), 0.0); } /** - * @brief Set the FSR scalar flux for each energy group to some value. + * @brief Set the scalar flux for each FSR and energy group to some value. * @param value the value to assign to each FSR scalar flux */ void GPUSolver::flattenFSRFluxes(FP_PRECISION value) { - - int size = _num_FSRs * _num_groups * sizeof(FP_PRECISION); - - cudaMemset(_scalar_flux, value, size); - - return; + thrust::fill(_scalar_flux.begin(), _scalar_flux.end(), value); } /** - * @brief Set the FSR source for each energy group to some value. - * @param value the value to assign to each FSR source + * @brief Stores the FSR scalar fluxes in the old scalar flux array. */ -void GPUSolver::flattenFSRSources(FP_PRECISION value) { - - int size = _num_FSRs * sizeof(FP_PRECISION); - - cudaMemset(_old_fission_sources, value, size); - - return; +void GPUSolver::storeFSRFluxes() { + thrust::copy(_scalar_flux.begin(), _scalar_flux.end(), + _old_scalar_flux.begin()); } @@ -1570,47 +1377,96 @@ void GPUSolver::flattenFSRSources(FP_PRECISION value) { */ void GPUSolver::normalizeFluxes() { + /** Create Thrust vector of fission sources in each FSR */ + thrust::device_vector fission_sources_vec; + fission_sources_vec.resize(_B * _T); + FP_PRECISION* fission_sources = + thrust::raw_pointer_cast(&fission_sources_vec[0]); + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + int shared_mem = sizeof(FP_PRECISION) * _T; computeFissionSourcesOnDevice<<<_B, _T, shared_mem>>>(_FSR_volumes, _FSR_materials, _materials, - _scalar_flux, - _fission_sources); - - FP_PRECISION norm_factor = 1.0 / thrust::reduce(_fission_sources_vec.begin(), - _fission_sources_vec.end()); - normalizeFluxesOnDevice<<<_B, _T>>>(_scalar_flux, _boundary_flux,norm_factor); + scalar_flux, + fission_sources); + + FP_PRECISION norm_factor = 1.0 / thrust::reduce(fission_sources_vec.begin(), + fission_sources_vec.end()); + + /* Multiply all scalar and angular fluxes by the normalization constant */ + thrust::transform(_scalar_flux.begin(), _scalar_flux.end(), + thrust::constant_iterator(norm_factor), + _scalar_flux.begin(), thrust::multiplies()); + thrust::transform(_old_scalar_flux.begin(), _old_scalar_flux.end(), + thrust::constant_iterator(norm_factor), + _old_scalar_flux.begin(), + thrust::multiplies()); + thrust::transform(_boundary_flux.begin(), _boundary_flux.end(), + thrust::constant_iterator(norm_factor), + _boundary_flux.begin(), thrust::multiplies()); + + /* Clear Thrust vector of FSR fission sources */ + fission_sources_vec.clear(); } /** - * @brief Computes the total source (fission and scattering) in each FSR. + * @brief Computes the total source (fission, scattering, fixed) in each FSR. * @details This method computes the total source in each FSR based on - * this iteration's current approximation to the scalar flux. A - * residual for the source with respect to the source compute on - * the previous iteration is computed and returned. The residual - * is determined as follows: - * /f$ res = \sqrt{\frac{\displaystyle\sum \displaystyle\sum - * \left(\frac{Q^i - Q^{i-1}{Q^i}\right)^2}{\# FSRs}}} /f$ - * - * @return the residual between this source and the previous source + * this iteration's current approximation to the scalar flux. */ -FP_PRECISION GPUSolver::computeFSRSources() { +void GPUSolver::computeFSRSources() { + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* fixed_sources = + thrust::raw_pointer_cast(&_fixed_sources[0]); + FP_PRECISION* reduced_sources = + thrust::raw_pointer_cast(&_reduced_sources[0]); computeFSRSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, - _scalar_flux, _old_fission_sources, - _reduced_sources, 1.0 / _k_eff, - _source_residuals); + scalar_flux, fixed_sources, + reduced_sources, 1.0 / _k_eff); +} - FP_PRECISION residual = thrust::reduce(_source_residuals_vec.begin(), - _source_residuals_vec.end()); - residual = sqrt(residual / (_num_groups * _num_fissionable_FSRs)); - return residual; +/** + * @brief Computes the fission source in each FSR. + * @details This method computes the fission source in each FSR based on + * this iteration's current approximation to the scalar flux. + */ +void GPUSolver::computeFSRFissionSources() { + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* reduced_sources = + thrust::raw_pointer_cast(&_reduced_sources[0]); + + computeFSRFissionSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, true, + scalar_flux, reduced_sources); } +/** + * @brief Computes the scatter source in each FSR. + * @details This method computes the scatter source in each FSR based on + * this iteration's current approximation to the scalar flux. + */ +void GPUSolver::computeFSRScatterSources() { + + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* reduced_sources = + thrust::raw_pointer_cast(&_reduced_sources[0]); + + computeFSRScatterSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, true, + scalar_flux, reduced_sources); +} + /** * @brief This method performs one transport sweep of all azimuthal angles, @@ -1622,36 +1478,36 @@ FP_PRECISION GPUSolver::computeFSRSources() { void GPUSolver::transportSweep() { int shared_mem = _T * _two_times_num_polar * sizeof(FP_PRECISION); - int tid_offset, tid_max; + int tid_offset = 0; + int tid_max = 0; log_printf(DEBUG, "Transport sweep on device with %d blocks and %d threads", _B, _T); - /* Initialize leakage to zero */ - thrust::fill(_leakage_vec.begin(), _leakage_vec.end(), 0.0); + /* Get device pointer to the Thrust vectors */ + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* boundary_flux = + thrust::raw_pointer_cast(&_boundary_flux[0]); + FP_PRECISION* reduced_sources = + thrust::raw_pointer_cast(&_reduced_sources[0]); /* Initialize flux in each FSR to zero */ flattenFSRFluxes(0.0); - /* Sweep the first halfspace of azimuthal angle space */ - tid_offset = 0; - tid_max = (_tot_num_tracks / 2); - - transportSweepOnDevice<<<_B, _T, shared_mem>>>(_scalar_flux, _boundary_flux, - _reduced_sources, _leakage, - _materials, _dev_tracks, - _exp_table, - tid_offset, tid_max); - - /* Sweep the second halfspace of azimuthal angle space */ - tid_offset = tid_max * _num_groups; - tid_max = _tot_num_tracks; - - transportSweepOnDevice<<<_B, _T, shared_mem>>>(_scalar_flux, _boundary_flux, - _reduced_sources, _leakage, - _materials, _dev_tracks, - _exp_table, - tid_offset, tid_max); + /* Loop over the parallel track groups and perform transport sweep on tracks + * in that group */ + for (int g=0; g < _num_parallel_track_groups; g++) { + tid_offset = tid_max * _num_groups; + tid_max += _track_generator->getNumTracksByParallelGroup(g); + + transportSweepOnDevice<<<_B, _T, shared_mem>>>(scalar_flux, boundary_flux, + reduced_sources, + _materials, _dev_tracks, + tid_offset, tid_max); + + cudaDeviceSynchronize(); + } } @@ -1660,16 +1516,19 @@ void GPUSolver::transportSweep() { * the FSR scalar flux. */ void GPUSolver::addSourceToScalarFlux() { + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* reduced_sources = + thrust::raw_pointer_cast(&_reduced_sources[0]); - addSourceToScalarFluxOnDevice<<<_B,_T>>>(_scalar_flux, _reduced_sources, + addSourceToScalarFluxOnDevice<<<_B,_T>>>(scalar_flux, reduced_sources, _FSR_volumes, _FSR_materials, _materials); } /** - * @brief Compute \f$ k_{eff} \f$ from the total, fission and scattering - * reaction rates and leakage. + * @brief Compute \f$ k_{eff} \f$ from successive fission sources. * @details This method computes the current approximation to the * multiplication factor on this iteration as follows: * \f$ k_{eff} = \frac{\displaystyle\sum_{i \in I} @@ -1680,53 +1539,286 @@ void GPUSolver::addSourceToScalarFlux() { */ void GPUSolver::computeKeff() { - FP_PRECISION total; FP_PRECISION fission; - FP_PRECISION scatter; - FP_PRECISION leakage; + + thrust::device_vector fission_vec; + fission_vec.resize(_B * _T); + + FP_PRECISION* fiss_ptr = thrust::raw_pointer_cast(&fission_vec[0]); + FP_PRECISION* flux = thrust::raw_pointer_cast(&_scalar_flux[0]); /* Compute the total, fission and scattering reaction rates on device. * This kernel stores partial rates in a Thrust vector with as many * entries as CUDAthreads executed by the kernel */ - computeKeffReactionRates<<<_B, _T>>>(_FSR_volumes, _FSR_materials, - _materials, _scalar_flux, - _total, _fission, _scatter); + computeFSRFissionRatesOnDevice<<<_B, _T>>>(_FSR_volumes, _FSR_materials, + _materials, flux, fiss_ptr); + + /* Compute the total fission source */ + fission = thrust::reduce(fission_vec.begin(), fission_vec.end()); - cudaDeviceSynchronize(); + _k_eff *= fission; - /* Compute the total reaction rate by reducing the partial total - * rates compiled in the Thrust vector */ - total = thrust::reduce(_total_vec.begin(), _total_vec.end()); + fission_vec.clear(); +} - /* Compute the fission rate by reducing the partial fission - * rates compiled in the Thrust vector */ - fission = thrust::reduce(_fission_vec.begin(), _fission_vec.end()); - cudaMemcpy((void*)&fission, (void*)_fission, - _B * _T * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); +/** + * @brief Computes the residual between source/flux iterations. + * @param res_type the type of residuals to compute + * (SCALAR_FLUX, FISSION_SOURCE, TOTAL_SOURCE) + * @return the average residual in each flat source region + */ +double GPUSolver::computeResidual(residualType res_type) { + + int norm; + double residual; + isinf_test inf_test; + isnan_test nan_test; + + /* Allocate Thrust vector for residuals in each FSR */ + thrust::device_vector residuals(_num_FSRs); + + if (res_type == SCALAR_FLUX) { + + norm = _num_FSRs; + + /* Allocate Thrust vector for residuals */ + thrust::device_vector fp_residuals(_num_FSRs * _num_groups); + thrust::device_vector FSR_fp_residuals(_num_FSRs); + + /* Compute the relative flux change in each FSR and group */ + thrust::transform(_scalar_flux.begin(), _scalar_flux.end(), + _old_scalar_flux.begin(), fp_residuals.begin(), + thrust::minus()); + thrust::transform(fp_residuals.begin(), fp_residuals.end(), + _old_scalar_flux.begin(), fp_residuals.begin(), + thrust::divides()); + + /* Replace INF and NaN values (from divide by zero) with 0. */ + thrust::replace_if(fp_residuals.begin(), fp_residuals.end(), inf_test, 0); + thrust::replace_if(fp_residuals.begin(), fp_residuals.end(), nan_test, 0); + + /* Square the residuals */ + thrust::transform(fp_residuals.begin(), fp_residuals.end(), + fp_residuals.begin(), fp_residuals.begin(), + thrust::multiplies()); + + typedef thrust::device_vector::iterator Iterator; + + /* Reduce flux residuals across energy groups within each FSR */ + for (int e=0; e < _num_groups; e++) { + strided_range strider(fp_residuals.begin() + e, + fp_residuals.end(), _num_groups); + thrust::transform(FSR_fp_residuals.begin(), FSR_fp_residuals.end(), + strider.begin(), FSR_fp_residuals.begin(), + thrust::plus()); + } - /* Compute the scattering rate by reducing the partial fission - * rates compiled in the Thrust vector */ - scatter = thrust::reduce(_scatter_vec.begin(), _scatter_vec.end()); + /* Copy the FP_PRECISION residual to the double precision residual */ + thrust::copy(FSR_fp_residuals.begin(), + FSR_fp_residuals.end(), residuals.begin()); - /* Compute the total leakage by reducing the partial leakage - * rates compiled in the Thrust vector */ - leakage = 0.5 * thrust::reduce(_leakage_vec.begin(), _leakage_vec.end()); + /* Sum up the residuals */ + residual = thrust::reduce(residuals.begin(), residuals.end()); + /* Deallocate memory for Thrust vectors */ + fp_residuals.clear(); + FSR_fp_residuals.clear(); + residuals.clear(); - /* Compute the new keff from the total, fission, scatter and leakage */ - _k_eff = fission / (total - scatter + leakage); + /* Normalize the residual */ + residual = sqrt(residual / norm); - log_printf(DEBUG, "tot = %f, fiss = %f, scatt = %f, leak = %f," - " keff = %f", total, fission, scatter, leakage, _k_eff); + return residual; + } + + else if (res_type == FISSION_SOURCE) { + + if (_num_fissionable_FSRs == 0) + log_printf(ERROR, "The Solver is unable to compute a " + "FISSION_SOURCE residual without fissionable FSRs"); + + norm = _num_fissionable_FSRs; + + /* Allocate Thrust vectors for fission sources in each FSR, group */ + thrust::device_vector new_fission_sources_vec(_num_FSRs * _num_groups); + thrust::device_vector old_fission_sources_vec(_num_FSRs * _num_groups); + + /* Allocate Thrust vectors for energy-integrated fission sources in each FSR */ + thrust::device_vector FSR_old_fiss_src(_num_FSRs); + thrust::device_vector FSR_new_fiss_src(_num_FSRs); + + /* Cast Thrust vectors as array pointers */ + FP_PRECISION* old_fission_sources = + thrust::raw_pointer_cast(&old_fission_sources_vec[0]); + FP_PRECISION* new_fission_sources = + thrust::raw_pointer_cast(&new_fission_sources_vec[0]); + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* old_scalar_flux = + thrust::raw_pointer_cast(&_old_scalar_flux[0]); + + /* Compute the old and new nu-fission sources in each FSR, group */ + computeFSRFissionSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + old_scalar_flux, old_fission_sources); + computeFSRFissionSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + scalar_flux, new_fission_sources); + + typedef thrust::device_vector::iterator Iterator; + + /* Reduce nu-fission sources across energy groups within each FSR */ + for (int e=0; e < _num_groups; e++) { + strided_range old_strider(old_fission_sources_vec.begin() + e, + old_fission_sources_vec.end(), _num_groups); + strided_range new_strider(new_fission_sources_vec.begin() + e, + new_fission_sources_vec.end(), _num_groups); + thrust::transform(FSR_old_fiss_src.begin(), FSR_old_fiss_src.end(), + old_strider.begin(), FSR_old_fiss_src.begin(), + thrust::plus()); + thrust::transform(FSR_new_fiss_src.begin(), FSR_new_fiss_src.end(), + new_strider.begin(), FSR_new_fiss_src.begin(), + thrust::plus()); + } + + /* Compute the relative nu-fission source change in each FSR */ + thrust::transform(FSR_new_fiss_src.begin(), FSR_new_fiss_src.end(), + FSR_old_fiss_src.begin(), residuals.begin(), + thrust::minus()); + thrust::transform(residuals.begin(), residuals.end(), + FSR_old_fiss_src.begin(), residuals.begin(), + thrust::divides()); + + /* Deallocate memory for Thrust vectors */ + old_fission_sources_vec.clear(); + new_fission_sources_vec.clear(); + FSR_old_fiss_src.clear(); + FSR_new_fiss_src.clear(); + } + + else if (res_type == TOTAL_SOURCE) { + + norm = _num_FSRs; + + /* Allocate Thrust vectors for fission/scatter sources in each FSR, group */ + thrust::device_vector new_sources_vec(_num_FSRs * _num_groups); + thrust::device_vector old_sources_vec(_num_FSRs * _num_groups); + thrust::fill(new_sources_vec.begin(), new_sources_vec.end(), 0.0); + thrust::fill(old_sources_vec.begin(), old_sources_vec.end(), 0.0); + + /* Allocate Thrust vectors for energy-integrated fission/scatter sources in each FSR */ + thrust::device_vector FSR_old_src(_num_FSRs); + thrust::device_vector FSR_new_src(_num_FSRs); + thrust::fill(FSR_old_src.begin(), FSR_old_src.end(), 0.); + thrust::fill(FSR_new_src.begin(), FSR_new_src.end(), 0.); + + /* Cast Thrust vectors as array pointers */ + FP_PRECISION* old_sources = + thrust::raw_pointer_cast(&old_sources_vec[0]); + FP_PRECISION* new_sources = + thrust::raw_pointer_cast(&new_sources_vec[0]); + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); + FP_PRECISION* old_scalar_flux = + thrust::raw_pointer_cast(&_old_scalar_flux[0]); + + /* Compute nu-fission source */ + + /* Compute the old and new nu-fission sources in each FSR, group */ + computeFSRFissionSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + old_scalar_flux, old_sources); + computeFSRFissionSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + scalar_flux, new_sources); + + typedef thrust::device_vector::iterator Iterator; + + /* Reduce nu-fission sources across energy groups within each FSR */ + for (int e=0; e < _num_groups; e++) { + strided_range old_strider(old_sources_vec.begin() + e, + old_sources_vec.end(), _num_groups); + strided_range new_strider(new_sources_vec.begin() + e, + new_sources_vec.end(), _num_groups); + thrust::transform(FSR_old_src.begin(), FSR_old_src.end(), + old_strider.begin(), FSR_old_src.begin(), + thrust::plus()); + thrust::transform(FSR_new_src.begin(), FSR_new_src.end(), + new_strider.begin(), FSR_new_src.begin(), + thrust::plus()); + } + + /* Multiply fission sources by inverse keff */ + thrust::for_each(FSR_new_src.begin(), FSR_new_src.end(), + multiplyByConstant(1. / _k_eff)); + thrust::for_each(FSR_old_src.begin(), FSR_old_src.end(), + multiplyByConstant(1. / _k_eff)); + + /* Compute scatter source */ + + /* Reset sources Thrust vectors to zero */ + thrust::fill(new_sources_vec.begin(), new_sources_vec.end(), 0.0); + thrust::fill(old_sources_vec.begin(), old_sources_vec.end(), 0.0); + + /* Compute the old and new scattering sources in each FSR, group */ + computeFSRScatterSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + old_scalar_flux, old_sources); + computeFSRScatterSourcesOnDevice<<<_B, _T>>>(_FSR_materials, _materials, false, + scalar_flux, new_sources); + + /* Reduce scatter sources across energy groups within each FSR */ + for (int e=0; e < _num_groups; e++) { + strided_range old_strider(old_sources_vec.begin() + e, + old_sources_vec.end(), _num_groups); + strided_range new_strider(new_sources_vec.begin() + e, + new_sources_vec.end(), _num_groups); + thrust::transform(FSR_old_src.begin(), FSR_old_src.end(), + old_strider.begin(), FSR_old_src.begin(), + thrust::plus()); + thrust::transform(FSR_new_src.begin(), FSR_new_src.end(), + new_strider.begin(), FSR_new_src.begin(), + thrust::plus()); + } + + /* Compute the relative total source change in each FSR */ + thrust::transform(FSR_new_src.begin(), FSR_new_src.end(), + FSR_old_src.begin(), residuals.begin(), + thrust::minus()); + thrust::transform(residuals.begin(), residuals.end(), + FSR_old_src.begin(), residuals.begin(), + thrust::divides()); + + /* Deallocate memory for Thrust vectors */ + old_sources_vec.clear(); + new_sources_vec.clear(); + FSR_old_src.clear(); + FSR_new_src.clear(); + } + + /* Replace INF and NaN values (from divide by zero) with 0. */ + thrust::replace_if(residuals.begin(), residuals.end(), inf_test, 0); + thrust::replace_if(residuals.begin(), residuals.end(), nan_test, 0); + + /* Square the residuals */ + thrust::transform(residuals.begin(), residuals.end(), + residuals.begin(), residuals.begin(), + thrust::multiplies()); + + /* Sum up the residuals */ + residual = thrust::reduce(residuals.begin(), residuals.end()); + + /* Deallocate memory for residuals vector */ + residuals.clear(); + + /* Normalize the residual */ + residual = sqrt(residual / norm); + + return residual; } /** - * @brief Computes the volume-weighted, energy integrated fission rate in + * @brief Computes the volume-averaged, energy-integrated nu-fission rate in * each FSR and stores them in an array indexed by FSR ID. * @details This is a helper method for SWIG to allow users to retrieve - * FSR fission rates as a NumPy array. An example of how this method + * FSR nu-fission rates as a NumPy array. An example of how this method * can be called from Python is as follows: * * @code @@ -1734,30 +1826,36 @@ void GPUSolver::computeKeff() { * fission_rates = solver.computeFSRFissionRates(num_FSRs) * @endcode * - * @param fission_rates an array to store the fission rates (implicitly passed - * in as a NumPy array from Python) + * @param fission_rates an array to store the nu-fission rates (implicitly + * passed in as a NumPy array from Python) * @param num_FSRs the number of FSRs passed in from Python */ void GPUSolver::computeFSRFissionRates(double* fission_rates, int num_FSRs) { log_printf(INFO, "Computing FSR fission rates..."); - /* Allocate memory for the FSR fission rates on the device */ - double* dev_fission_rates; - cudaMalloc((void**)&dev_fission_rates, _num_FSRs * sizeof(double)); + /* Allocate memory for the FSR nu-fission rates on the device and host */ + FP_PRECISION* dev_fission_rates; + cudaMalloc((void**)&dev_fission_rates, _num_FSRs * sizeof(FP_PRECISION)); + FP_PRECISION* host_fission_rates = new FP_PRECISION[_num_FSRs]; - /* Compute the FSR fission rates on the device */ - computeFSRFissionRatesOnDevice<<<_B,_T>>>(dev_fission_rates, - _FSR_materials, - _materials, - _scalar_flux); + FP_PRECISION* scalar_flux = + thrust::raw_pointer_cast(&_scalar_flux[0]); - /* Copy the fission rate array from the device to the host */ - cudaMemcpy((void*)fission_rates, (void*)dev_fission_rates, - _num_FSRs * sizeof(double), cudaMemcpyDeviceToHost); + /* Compute the FSR nu-fission rates on the device */ + computeFSRFissionRatesOnDevice<<<_B, _T>>>(_FSR_volumes, _FSR_materials, + _materials, scalar_flux, + dev_fission_rates); + + /* Copy the nu-fission rate array from the device to the host */ + cudaMemcpy((void*)host_fission_rates, (void*)dev_fission_rates, + _num_FSRs * sizeof(FP_PRECISION), cudaMemcpyDeviceToHost); + + /* Populate the double precision NumPy array for the output */ + for (int i=0; i < _num_FSRs; i++) + fission_rates[i] = host_fission_rates[i]; /* Deallocate the memory assigned to store the fission rates on the device */ cudaFree(dev_fission_rates); - - return; + delete [] host_fission_rates; } diff --git a/src/accel/cuda/GPUSolver.h b/src/accel/cuda/GPUSolver.h index 6cd479667..9dd74cfd6 100644 --- a/src/accel/cuda/GPUSolver.h +++ b/src/accel/cuda/GPUSolver.h @@ -9,22 +9,45 @@ #define GPUSOLVER_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "../../constants.h" #include "../../Solver.h" #endif -#include +#define PySys_WriteStdout printf + +#include +#include + #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include "clone.h" +#include "GPUExpEvaluator.h" /** Indexing macro for the scalar flux in each FSR and energy group */ #define scalar_flux(tid,e) (scalar_flux[(tid)*(*num_groups) + (e)]) +/** Indexing macro for the old scalar flux in each FSR and energy group */ +#define old_scalar_flux(tid,e) (old_scalar_flux[(tid)*(*num_groups) + (e)]) + /** Indexing macro for the total source divided by the total cross-section, * \f$ \frac{Q}{\Sigma_t} \f$, in each FSR and energy group */ #define reduced_sources(tid,e) (reduced_sources[(tid)*(*num_groups) + (e)]) +/** Indexing scheme for fixed sources for each FSR and energy group */ +#define fixed_sources(r,e) (fixed_sources[(r)*(*num_groups) + (e)]) + /** Indexing macro for the azimuthal and polar weights */ #define polar_weights(i,p) (polar_weights[(i)*(*num_polar) + (p)]) @@ -32,18 +55,6 @@ * group for a given Track */ #define boundary_flux(t,pe2) (boundary_flux[2*(t)*(*polar_times_groups)+(pe2)]) -/** The value of 4pi: \f$ 4\pi \f$ */ -#define FOUR_PI 12.5663706143 - -/** The values of 1 divided by 4pi: \f$ \frac{1}{4\pi} \f$ */ -#define ONE_OVER_FOUR_PI 0.0795774715 - -/** The maximum number of polar angles to reserve constant memory on GPU */ -#define MAX_POLAR_ANGLES 3 - -/** The maximum number of azimuthal angles to reserve constant memory on GPU */ -#define MAX_AZIM_ANGLES 256 - /** * @class GPUSolver GPUSolver.h "openmoc/src/dev/gpu/GPUSolver.h" @@ -62,6 +73,9 @@ class GPUSolver : public Solver { /** The number of threads per thread block */ int _T; + /** Twice the number of polar angles */ + int _two_times_num_polar; + /** The FSR Material pointers index by FSR ID */ int* _FSR_materials; @@ -71,116 +85,66 @@ class GPUSolver : public Solver { /** A pointer to the array of Tracks on the device */ dev_track* _dev_tracks; - /** An array of the cumulative number of Tracks for each azimuthal angle */ - int* _track_index_offsets; + /** Thrust vector of angular fluxes for each track */ + thrust::device_vector _boundary_flux; - /** A pointer to the Thrust vector of total reaction rates in each FSR */ - FP_PRECISION* _total; + /** Thrust vector of FSR scalar fluxes */ + thrust::device_vector _scalar_flux; - /** A pointer to the Thrust vector of fission rates in each FSR */ - FP_PRECISION* _fission; + /** Thrust vector of old FSR scalar fluxes */ + thrust::device_vector _old_scalar_flux; - /** A pointer to the Thrust vector of scatter rates in each FSR */ - FP_PRECISION* _scatter; + /** Thrust vector of fixed sources in each FSR */ + thrust::device_vector _fixed_sources; - /** A pointer to the Thrust vector of leakages for each Track */ - FP_PRECISION* _leakage; + /** Thrust vector of source / sigma_t in each FSR */ + thrust::device_vector _reduced_sources; - /** Thrust vector of fission sources in each FSR */ - thrust::device_vector _fission_sources_vec; - - /** Thrust vector of total reaction rates in each FSR */ - thrust::device_vector _total_vec; + /** Map of Material IDs to indices in _materials array */ + std::map _material_IDs_to_indices; - /** Thrust vector of fission rates in each FSR */ - thrust::device_vector _fission_vec; +public: - /** Thrust vector of scatter rates in each FSR */ - thrust::device_vector _scatter_vec; + GPUSolver(TrackGenerator* track_generator=NULL); + virtual ~GPUSolver(); - /** Thrust vector of source residuals in each FSR */ - thrust::device_vector _source_residuals_vec; + int getNumThreadBlocks(); - /** Thrust vector of leakages for each track */ - thrust::device_vector _leakage_vec; + /** + * @brief Returns the number of threads per block to execute on the GPU. + * @return the number of threads per block + */ + int getNumThreadsPerBlock(); + FP_PRECISION getFSRSource(int fsr_id, int group); + FP_PRECISION getFlux(int fsr_id, int group); + void getFluxes(FP_PRECISION* out_fluxes, int num_fluxes); - /** Map of Material IDs to indices in _materials array */ - std::map _material_IDs_to_indices; + void setNumThreadBlocks(int num_blocks); + void setNumThreadsPerBlock(int num_threads); + void setGeometry(Geometry* geometry); + void setTrackGenerator(TrackGenerator* track_generator); + void setFluxes(FP_PRECISION* in_fluxes, int num_fluxes); void initializePolarQuadrature(); + void initializeExpEvaluator(); + void initializeMaterials(solverMode mode=ADJOINT); void initializeFSRs(); - void initializeMaterials(); void initializeTracks(); void initializeFluxArrays(); void initializeSourceArrays(); - void initializeThrustVectors(); - void buildExpInterpTable(); + void initializeFixedSources(); void zeroTrackFluxes(); void flattenFSRFluxes(FP_PRECISION value); - void flattenFSRSources(FP_PRECISION value); + void storeFSRFluxes(); void normalizeFluxes(); - FP_PRECISION computeFSRSources(); + void computeFSRSources(); + void computeFSRFissionSources(); + void computeFSRScatterSources(); + void transportSweep(); void addSourceToScalarFlux(); void computeKeff(); - void transportSweep(); - -public: - - /** - * @brief Constructor initializes arrays for dev_tracks and dev_materials.. - * @details The constructor retrieves the number of energy groups and FSRs - * and azimuthal angles from the Geometry and TrackGenerator if - * passed in as parameters by the user. The constructor initalizes - * the number of CUDA threads and thread blocks each to a default - * of 64. - * @param geometry an optional pointer to the Geometry - * @param track_generator an optional pointer to the TrackjGenerator - */ - GPUSolver(Geometry* geometry=NULL, TrackGenerator* track_generator=NULL); - virtual ~GPUSolver(); - - /** - * @brief Sets the number of thread blocks (>0) for CUDA kernels. - * @return num_blocks the number of thread blocks - */ - int getNumThreadBlocks(); - -/** - * @brief Returns the number of threads per block to execute on the GPU. - * @return the number of threads per block - */ - int getNumThreadsPerBlock(); - - FP_PRECISION getFSRScalarFlux(int fsr_id, int energy_group); - FP_PRECISION* getFSRScalarFluxes(); - FP_PRECISION getFSRSource(int fsr_id, int energy_group); - - /** - * @brief Sets the number of thread blocks (>0) for CUDA kernels. - * @param num_blocks the number of thread blocks - */ - void setNumThreadBlocks(int num_blocks); - - /** - * @brief Sets the number of threads per block (>0) for CUDA kernels. - * @param num_threads the number of threads per block - */ - void setNumThreadsPerBlock(int num_threads); - - void setGeometry(Geometry* geometry); - void setTrackGenerator(TrackGenerator* track_generator); - - /** - * @brief This method computes the index for Track j at azimuthal angle i. - * @details This method is necessary since the array of dev_tracks on - * the device is a 1D array which needs a one-to-one mapping - * from the 2D jagged array of Tracks on the host. - * @param i azimuthal angle number - * @param j the jth track at angle i - * @return an index into the device track array - */ - int computeScalarTrackIndex(int i, int j); + double computeResidual(residualType res_type); void computeFSRFissionRates(double* fission_rates, int num_FSRs); }; diff --git a/src/accel/cuda/clone.cu b/src/accel/cuda/clone.cu index f9d1a2c68..922dd2b85 100644 --- a/src/accel/cuda/clone.cu +++ b/src/accel/cuda/clone.cu @@ -10,7 +10,7 @@ * @param material_h pointer to a Material on the host * @param material_d pointer to a dev_material on the GPU */ -void clone_material_on_gpu(Material* material_h, dev_material* material_d) { +void clone_material(Material* material_h, dev_material* material_d) { /* Copy over the Material's ID */ int id = material_h->getId(); @@ -20,48 +20,50 @@ void clone_material_on_gpu(Material* material_h, dev_material* material_d) { cudaMemcpyHostToDevice); /* Allocate memory on the device for each dev_material data array */ - double* sigma_t; - double* sigma_a; - double* sigma_s; - double* sigma_f; - double* nu_sigma_f; - double* chi; + FP_PRECISION* sigma_t; + FP_PRECISION* sigma_s; + FP_PRECISION* sigma_f; + FP_PRECISION* nu_sigma_f; + FP_PRECISION* chi; + FP_PRECISION* fiss_matrix; /* Allocate memory on device for dev_material data arrays */ - cudaMalloc((void**)&sigma_t, num_groups * sizeof(double)); - cudaMalloc((void**)&sigma_a, num_groups * sizeof(double)); - cudaMalloc((void**)&sigma_s, num_groups * num_groups * sizeof(double)); - cudaMalloc((void**)&sigma_f, num_groups * sizeof(double)); - cudaMalloc((void**)&nu_sigma_f, num_groups * sizeof(double)); - cudaMalloc((void**)&chi, num_groups * sizeof(double)); + cudaMalloc((void**)&sigma_t, num_groups * sizeof(FP_PRECISION)); + cudaMalloc((void**)&sigma_s, num_groups * num_groups * sizeof(FP_PRECISION)); + cudaMalloc((void**)&sigma_f, num_groups * sizeof(FP_PRECISION)); + cudaMalloc((void**)&nu_sigma_f, num_groups * sizeof(FP_PRECISION)); + cudaMalloc((void**)&chi, num_groups * sizeof(FP_PRECISION)); + cudaMalloc((void**)&fiss_matrix, num_groups * num_groups * sizeof(FP_PRECISION)); /* Copy Material data from host to arrays on the device */ cudaMemcpy((void*)sigma_t, (void*)material_h->getSigmaT(), - num_groups * sizeof(double), cudaMemcpyHostToDevice); - cudaMemcpy((void*)sigma_a, (void*)material_h->getSigmaA(), - num_groups * sizeof(double), cudaMemcpyHostToDevice); + num_groups * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); cudaMemcpy((void*)sigma_s, (void*)material_h->getSigmaS(), - num_groups * num_groups * sizeof(double), cudaMemcpyHostToDevice); + num_groups * num_groups * sizeof(FP_PRECISION), + cudaMemcpyHostToDevice); cudaMemcpy((void*)sigma_f, (void*)material_h->getSigmaF(), - num_groups * sizeof(double), cudaMemcpyHostToDevice); + num_groups * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); cudaMemcpy((void*)nu_sigma_f, (void*)material_h->getNuSigmaF(), - num_groups * sizeof(double), cudaMemcpyHostToDevice); + num_groups * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); cudaMemcpy((void*)chi, (void*)material_h->getChi(), - num_groups * sizeof(double), cudaMemcpyHostToDevice); + num_groups * sizeof(FP_PRECISION), cudaMemcpyHostToDevice); + cudaMemcpy((void*)fiss_matrix, (void*)material_h->getFissionMatrix(), + num_groups * num_groups * sizeof(FP_PRECISION), + cudaMemcpyHostToDevice); /* Copy Material data pointers to dev_material on GPU */ - cudaMemcpy((void*)&material_d->_sigma_t, (void*)&sigma_t, sizeof(double*), - cudaMemcpyHostToDevice); - cudaMemcpy((void*)&material_d->_sigma_a, (void*)&sigma_a, sizeof(double*), - cudaMemcpyHostToDevice); - cudaMemcpy((void*)&material_d->_sigma_s, (void*)&sigma_s, sizeof(double*), - cudaMemcpyHostToDevice); - cudaMemcpy((void*)&material_d->_sigma_f, (void*)&sigma_f, sizeof(double*), - cudaMemcpyHostToDevice); + cudaMemcpy((void*)&material_d->_sigma_t, (void*)&sigma_t, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); + cudaMemcpy((void*)&material_d->_sigma_s, (void*)&sigma_s, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); + cudaMemcpy((void*)&material_d->_sigma_f, (void*)&sigma_f, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); cudaMemcpy((void*)&material_d->_nu_sigma_f, (void*)&nu_sigma_f, - sizeof(double*), cudaMemcpyHostToDevice); - cudaMemcpy((void*)&material_d->_chi, (void*)&chi, sizeof(double*), - cudaMemcpyHostToDevice); + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); + cudaMemcpy((void*)&material_d->_chi, (void*)&chi, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); + cudaMemcpy((void*)&material_d->_fiss_matrix, (void*)&fiss_matrix, + sizeof(FP_PRECISION*), cudaMemcpyHostToDevice); return; } @@ -69,19 +71,19 @@ void clone_material_on_gpu(Material* material_h, dev_material* material_d) { /** * @brief Given a pointer to a Track on the host, a dev_track on - * the GPU, and the map of material IDs to indices in the - * _materials array, copy all of the class attributes and - * segments from the Track object on the host to the GPU. + * the GPU, and the map of material IDs to indices in the + * _materials array, copy all of the class attributes and + * segments from the Track object on the host to the GPU. * @details This routine is called by the GPUSolver::initializeTracks() * private class method and is not intended to be called - * directly. + * directly. * @param track_h pointer to a Track on the host * @param track_d pointer to a dev_track on the GPU * @param material_IDs_to_indices map of material IDs to indices * in the _materials array. */ -void clone_track_on_gpu(Track* track_h, dev_track* track_d, - std::map &material_IDs_to_indices) { +void clone_track(Track* track_h, dev_track* track_d, + std::map &material_IDs_to_indices) { dev_segment* dev_segments; dev_segment* host_segments = new dev_segment[track_h->getNumSegments()]; @@ -90,10 +92,10 @@ void clone_track_on_gpu(Track* track_h, dev_track* track_d, new_track._uid = track_h->getUid(); new_track._num_segments = track_h->getNumSegments(); new_track._azim_angle_index = track_h->getAzimAngleIndex(); - new_track._refl_in = track_h->isReflIn(); - new_track._refl_out = track_h->isReflOut(); - new_track._bc_in = track_h->getBCIn(); - new_track._bc_out = track_h->getBCOut(); + new_track._next_in = track_h->isNextIn(); + new_track._next_out = track_h->isNextOut(); + new_track._transfer_flux_in = track_h->getTransferFluxIn(); + new_track._transfer_flux_out = track_h->getTransferFluxOut(); cudaMalloc((void**)&dev_segments, track_h->getNumSegments() * sizeof(dev_segment)); @@ -103,7 +105,7 @@ void clone_track_on_gpu(Track* track_h, dev_track* track_d, segment* curr = track_h->getSegment(s); host_segments[s]._length = curr->_length; host_segments[s]._region_uid = curr->_region_id; - host_segments[s]._material_index = + host_segments[s]._material_index = material_IDs_to_indices[curr->_material->getId()]; } @@ -116,4 +118,4 @@ void clone_track_on_gpu(Track* track_h, dev_track* track_d, delete [] host_segments; return; -} +} \ No newline at end of file diff --git a/src/accel/cuda/clone.h b/src/accel/cuda/clone.h index 3f5a972b7..ee4ef7e38 100644 --- a/src/accel/cuda/clone.h +++ b/src/accel/cuda/clone.h @@ -10,6 +10,6 @@ #include "../DeviceTrack.h" #include -void clone_material_on_gpu(Material* material_h, dev_material* material_d); -void clone_track_on_gpu(Track* track_h, dev_track* track_d, +void clone_material(Material* material_h, dev_material* material_d); +void clone_track(Track* track_h, dev_track* track_d, std::map &material_IDs_to_indices); diff --git a/src/boundary_type.h b/src/boundary_type.h index 076a7796e..90ca3921a 100644 --- a/src/boundary_type.h +++ b/src/boundary_type.h @@ -19,6 +19,9 @@ enum boundaryType { /** A reflective boundary condition */ REFLECTIVE, + /** A reflective boundary condition */ + PERIODIC, + /** No boundary type (typically an interface between flat source regions) */ BOUNDARY_NONE }; diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 000000000..a8865f2b5 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,109 @@ +/** + * @file constants.h + * @brief Math constants and comparision tolerances. + * @date April 9, 2015. + * @author William Boyd, MIT, Course 22 (wboyd@mit.edu) + */ + +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + + +/** The minimum auto ID used for Surfaces, Cells, Materials and Universes */ +#define DEFAULT_INIT_ID 10000 + +/** The value of 4pi: \f$ 4\pi \f$ */ +#define FOUR_PI 12.5663706143 + +/** The values of 1 divided by 4pi: \f$ \frac{1}{4\pi} \f$ */ +#define ONE_OVER_FOUR_PI 0.0795774715 + +/** A negligible cross-section value to over-ride user-defined + * cross-sections very near zero (e.g., within (-1E-10, 1E-10)) */ +#define ZERO_SIGMA_T 1E-10 + +/** Threshold to determine how close the sum of \f$ \Sigma_a \f$ and + * \f$ \Sigma_s \f$ must match \f$ \Sigma_t \f$ for each energy group */ +#define SIGMA_T_THRESH 1E-3 + +/** Distance a Point is moved to cross over a Surface into a new Cell */ +#define TINY_MOVE 1E-10 + +/** Threshold to determine if a Point is on the boundary of a Lattice cell */ +#define ON_LATTICE_CELL_THRESH 1E-12 + +/** Error threshold to determine if a point is to be considered on a Surface */ +#define ON_SURFACE_THRESH 1E-12 + +/** Tolerance for difference of the sum of polar weights with respect to 1.0 */ +#define POLAR_WEIGHT_SUM_TOL 1E-5 + +/** The default maximum optical path length */ +#define MAX_OPTICAL_LENGTH FP_PRECISION(10.) + +/** A small amount to increment the tau, the max optical path length, to ensure + * that tracks with the max optical path length are not split. */ +#define TAU_NUDGE 1E-12 + +/** The minimum acceptable precision for exponential evaluations from + * the ExpEvaluator's linear interpolation table. This default precision + * was selected based on analysis by Yamamoto's 2004 paper on the topic. */ +#define EXP_PRECISION FP_PRECISION(1E-5) + +/** The maximum number of iterations allowed for a power method eigenvalue + * solve in linalg.cpp */ +#define MIN_LINALG_POWER_ITERATIONS 10 +#define MAX_LINALG_POWER_ITERATIONS 25000 + +/** The maximum number of iterations allowed for a linear solve in linalg.cpp */ +#define MIN_LINEAR_SOLVE_ITERATIONS 10 +#define MAX_LINEAR_SOLVE_ITERATIONS 1000 + +/** The faces and edges that collectively make up the surfaces of a + * horizontal slice of a rectangular prism. The faces are denoted + * as "f" and edges denoted as "e" on the illustration below: + * + * e f e + * +----------------------+ + * | | + * | | + * | | + * f | | f + * | | + * | | + * | | + * +----------------------+ + * e f e + * + */ +#define NUM_FACES 4 +#define NUM_EDGES 4 +#define NUM_SURFACES 8 +#define SURFACE_X_MIN 0 +#define SURFACE_Y_MIN 1 +#define SURFACE_X_MAX 2 +#define SURFACE_Y_MAX 3 +#define SURFACE_X_MIN_Y_MIN 4 +#define SURFACE_X_MAX_Y_MIN 5 +#define SURFACE_X_MAX_Y_MAX 6 +#define SURFACE_X_MIN_Y_MAX 7 + +/** The number of values used in representing a Track when the Tracks are + * retrieved from the TrackGenerator. */ +#define NUM_VALUES_PER_RETRIEVED_TRACK 6 + +/** The number of values used in representing a Segment when the Segments are + * retrieved from the TrackGenerator. */ +#define NUM_VALUES_PER_RETRIEVED_SEGMENT 7 + +#ifdef NVCC + +/** The maximum number of polar angles to reserve constant memory on GPU */ +#define MAX_POLAR_ANGLES_GPU 10 + +/** The maximum number of azimuthal angles to reserve constant memory on GPU */ +#define MAX_AZIM_ANGLES_GPU 256 + +#endif + +#endif /* CONSTANTS_H_ */ diff --git a/src/linalg.cpp b/src/linalg.cpp new file mode 100644 index 000000000..fa17a73c8 --- /dev/null +++ b/src/linalg.cpp @@ -0,0 +1,313 @@ +#include "linalg.h" + +/** + * @brief Solves a generalized eigenvalue problem using the Power method. + * @details This function takes in a loss + streaming Matrix (A), + * a fission gain Matrix (M), a flux Vector (X), a tolerance used + * for both the power method and linear solve convergence (tol), and + * a successive over-relaxation factor (SOR_factor) and computes the + * dominant eigenvalue and eigenvector using the Power method. The + * eigenvalue is returned and the input X Vector is modified in + * place to be the corresponding eigenvector. + * @param A the loss + streaming Matrix object + * @param M the fission gain Matrix object + * @param X the flux Vector object + * @param tol the power method and linear solve source convergence threshold + * @param SOR_factor the successive over-relaxation factor + * @return k_eff the dominant eigenvalue + */ +FP_PRECISION eigenvalueSolve(Matrix* A, Matrix* M, Vector* X, FP_PRECISION tol, + FP_PRECISION SOR_factor) { + + log_printf(INFO, "Computing the Matrix-Vector eigenvalue..."); + + /* Check for consistency of matrix and vector dimensions */ + if (A->getNumX() != M->getNumX() || A->getNumX() != X->getNumX()) + log_printf(ERROR, "Cannot compute the Matrix-Vector eigenvalue with " + "different x dimensions for the A matrix, M matrix, and X vector" + ": (%d, %d, %d)", A->getNumX(), M->getNumX(), X->getNumX()); + else if (A->getNumY() != M->getNumY() || A->getNumY() != X->getNumY()) + log_printf(ERROR, "Cannot compute the Matrix-Vector eigenvalue with " + "different y dimensions for the A matrix, M matrix, and X vector" + ": (%d, %d, %d)", A->getNumY(), M->getNumY(), X->getNumY()); + else if (A->getNumGroups() != M->getNumGroups() || + A->getNumGroups() != X->getNumGroups()) + log_printf(ERROR, "Cannot compute the Matrix-Vector eigenvalue with " + "different num groups for the A matrix, M matrix, and X vector:" + " (%d, %d, %d)", A->getNumGroups(), M->getNumGroups(), + X->getNumGroups()); + + /* Initialize variables */ + omp_lock_t* cell_locks = X->getCellLocks(); + int num_rows = X->getNumRows(); + int num_x = X->getNumX(); + int num_y = X->getNumY(); + int num_groups = X->getNumGroups(); + Vector old_source(cell_locks, num_x, num_y, num_groups); + Vector new_source(cell_locks, num_x, num_y, num_groups); + FP_PRECISION residual, _k_eff; + int iter; + + /* Compute and normalize the initial source */ + matrixMultiplication(M, X, &old_source); + old_source.scaleByValue(num_rows / old_source.getSum()); + X->scaleByValue(num_rows / old_source.getSum()); + + /* Power iteration Matrix-Vector solver */ + for (iter = 0; iter < MAX_LINALG_POWER_ITERATIONS; iter++) { + + /* Solve X = A^-1 * old_source */ + linearSolve(A, M, X, &old_source, tol*1e1, SOR_factor); + + /* Compute the new source */ + matrixMultiplication(M, X, &new_source); + + /* Compute and set keff */ + _k_eff = new_source.getSum() / num_rows; + + /* Scale the new source by 1 / k_eff */ + new_source.scaleByValue(1.0 / _k_eff); + + /* Compute the residual */ + residual = computeRMSE(&new_source, &old_source, true); + + /* Copy the new source to the old source */ + new_source.copyTo(&old_source); + + log_printf(INFO, "Matrix-Vector eigenvalue iter: %d, keff: %f, residual: " + "%f", iter, _k_eff, residual); + + /* Check for convergence */ + if (residual < tol && iter > MIN_LINALG_POWER_ITERATIONS) + break; + } + + log_printf(INFO, "Matrix-Vector eigenvalue solve iterations: %d", iter); + + return _k_eff; +} + + +/** + * @brief Solves a linear system using Red-Black Gauss Seidel with + * successive over-relaxation. + * @details This function takes in a loss + streaming Matrix (A), + * a fission gain Matrix (M), a flux Vector (X), a source Vector (B), + * a source convergence tolerance (tol) and a successive + * over-relaxation factor (SOR_factor) and computes the + * solution to the linear system. The input X Vector is modified in + * place to be the solution vector. + * @param A the loss + streaming Matrix object + * @param M the fission gain Matrix object + * @param X the flux Vector object + * @param B the source Vector object + * @param tol the power method and linear solve source convergence threshold + * @param SOR_factor the successive over-relaxation factor + */ +void linearSolve(Matrix* A, Matrix* M, Vector* X, Vector* B, FP_PRECISION tol, + FP_PRECISION SOR_factor) { + + /* Check for consistency of matrix and vector dimensions */ + if (A->getNumX() != B->getNumX() || A->getNumX() != X->getNumX() || + A->getNumX() != M->getNumX()) + log_printf(ERROR, "Cannot perform linear solve with different x dimensions" + " for the A matrix, M matrix, B vector, and X vector: " + "(%d, %d, %d, %d)", A->getNumX(), M->getNumX(), + B->getNumX(), X->getNumX()); + else if (A->getNumY() != B->getNumY() || A->getNumY() != X->getNumY() || + A->getNumY() != M->getNumY()) + log_printf(ERROR, "Cannot perform linear solve with different y dimensions" + " for the A matrix, M matrix, B vector, and X vector: " + "(%d, %d, %d, %d)", A->getNumY(), M->getNumY(), + B->getNumY(), X->getNumY()); + else if (A->getNumGroups() != B->getNumGroups() || + A->getNumGroups() != X->getNumGroups() || + A->getNumGroups() != M->getNumGroups()) + log_printf(ERROR, "Cannot perform linear solve with different num groups" + " for the A matrix, M matrix, B vector, and X vector: " + "(%d, %d, %d, %d)", A->getNumGroups(), M->getNumGroups(), + B->getNumGroups(), X->getNumGroups()); + + /* Initialize variables */ + FP_PRECISION residual; + int iter = 0; + omp_lock_t* cell_locks = X->getCellLocks(); + int num_x = X->getNumX(); + int num_y = X->getNumY(); + int num_groups = X->getNumGroups(); + int num_rows = X->getNumRows(); + Vector X_old(cell_locks, num_x, num_y, num_groups); + FP_PRECISION* x_old = X_old.getArray(); + int* ILU = A->getILU(); + int* JLU = A->getJLU(); + FP_PRECISION* DIAG = A->getDiag(); + FP_PRECISION* lu = A->getLU(); + FP_PRECISION* x = X->getArray(); + FP_PRECISION* b = B->getArray(); + int row; + Vector old_source(cell_locks, num_x, num_y, num_groups); + Vector new_source(cell_locks, num_x, num_y, num_groups); + FP_PRECISION val; + + /* Compute initial source */ + matrixMultiplication(M, X, &old_source); + + while (iter < MAX_LINEAR_SOLVE_ITERATIONS) { + + /* Pass new flux to old flux */ + X->copyTo(&X_old); + + /* Perform parallel red/black SOR iteration */ + for (int color=0; color < 2; color++) { +#pragma omp parallel for private(row, val) + for (int yc=0; yc < num_y; yc++) { + for (int xc=(yc + color) % 2; xc < num_x; xc+=2) { + for (int g=0; g < num_groups; g++) { + + /* Get the current matrix row */ + row = (yc * num_x + xc) * num_groups + g; + + /* Accumulate off diagonals multiplied by corresponding fluxes */ + val = 0.0; + for (int i = ILU[row]; i < ILU[row+1]; i++) + val += lu[i] * x[JLU[i]]; + + /* Update the flux for this row */ + x[row] += SOR_factor * ((b[row] - val) / DIAG[row] - x[row]); + } + } + } + } + + /* Compute the new source */ + matrixMultiplication(M, X, &new_source); + + /* Compute the residual */ + residual = computeRMSE(&new_source, &old_source, true); + + /* Copy the new source to the old source */ + new_source.copyTo(&old_source); + + /* Increment the interations counter */ + iter++; + + log_printf(INFO, "SOR iter: %d, residual: %f", iter, residual); + + if (residual < tol && iter > MIN_LINEAR_SOLVE_ITERATIONS) + break; + } + + log_printf(INFO, "linear solve iterations: %d", iter); +} + + +/** + * @brief Performs a matrix vector multiplication. + * @details This function takes in a Matrix (A), a variable Vector (X), + * and a solution Vector (B) and computes the matrix vector product. + * The solution Vector is modified in place. + * @param A a Matrix object + * @param X the variable Vector object + * @param B the solution Vector object + */ +void matrixMultiplication(Matrix* A, Vector* X, Vector* B) { + + /* Check for consistency of matrix and vector dimensions */ + if (A->getNumX() != B->getNumX() || A->getNumX() != X->getNumX()) + log_printf(ERROR, "Cannot perform matrix multiplication with different x " + "dimensions for the A matrix, B vector, and X vector: " + "(%d, %d, %d)", A->getNumX(), B->getNumX(), X->getNumX()); + else if (A->getNumY() != B->getNumY() || A->getNumY() != X->getNumY()) + log_printf(ERROR, "Cannot perform matrix multiplication with different y " + "dimensions for the A matrix, B vector, and X vector: " + "(%d, %d, %d)", A->getNumY(), B->getNumY(), X->getNumY()); + else if (A->getNumGroups() != B->getNumGroups() || + A->getNumGroups() != X->getNumGroups()) + log_printf(ERROR, "Cannot perform matrix multiplication with different " + "num groups for the A matrix, M matrix, and X vector: " + "(%d, %d, %d)", A->getNumGroups(), B->getNumGroups(), + X->getNumGroups()); + + B->setAll(0.0); + int* IA = A->getIA(); + int* JA = A->getJA(); + FP_PRECISION* a = A->getA(); + FP_PRECISION* x = X->getArray(); + FP_PRECISION* b = B->getArray(); + int num_rows = X->getNumRows(); + +#pragma omp parallel for + for (int row = 0; row < num_rows; row++) { + for (int i = IA[row]; i < IA[row+1]; i++) + b[row] += a[i] * x[JA[i]]; + } +} + + +/** + * @brief Computes the Root Mean Square Error of two Vectors. + * @details This function takes in two vectors (X and Y) and computes the + * Root Mean Square Error of the Vector Y with respect to Vector X. + * The boolean integrated must also be given to indicate whether the + * operation on the vector should be group-wise integrated before + * performing the RMSE operation. + * @param X a Vector object + * @param Y a second Vector object + * @param integrated a boolean indicating whether to group-wise integrate. + */ +FP_PRECISION computeRMSE(Vector* X, Vector* Y, bool integrated) { + + /* Check for consistency of vector dimensions */ + if (X->getNumX() != Y->getNumX() || X->getNumY() != Y->getNumY() || + X->getNumGroups() != Y->getNumGroups()) + log_printf(ERROR, "Cannot compute RMSE with different vector dimensions: " + "(%d, %d, %d) and (%d, %d, %d)", + X->getNumX(), X->getNumY(), X->getNumGroups(), + Y->getNumX(), Y->getNumY(), Y->getNumGroups()); + + FP_PRECISION rmse; + int num_x = X->getNumX(); + int num_y = X->getNumY(); + int num_groups = X->getNumGroups(); + omp_lock_t* cell_locks = X->getCellLocks(); + + if (integrated) { + + FP_PRECISION new_source, old_source; + Vector residual(cell_locks, num_x, num_y, 1); + + /* Compute the RMSE */ +#pragma omp parallel for private(new_source, old_source) + for (int i = 0; i < num_x*num_y; i++) { + new_source = 0.0; + old_source = 0.0; + for (int g = 0; g < num_groups; g++) { + new_source += X->getValue(i, g); + old_source += Y->getValue(i, g); + } + + if (new_source != 0.0) + residual.setValue(i, 0, pow((new_source - old_source) / new_source, 2)); + } + + rmse = sqrt(residual.getSum() / (num_x * num_y)); + } + else{ + + Vector residual(cell_locks, num_x, num_y, num_groups); + + /* Compute the RMSE */ +#pragma omp parallel for + for (int i = 0; i < num_x*num_y; i++) { + for (int g = 0; g < num_groups; g++) { + if (X->getValue(i, g) != 0.0) + residual.setValue(i, g, pow((X->getValue(i, g) - Y->getValue(i, g)) / + X->getValue(i, g), 2)); + } + } + + rmse = sqrt(residual.getSum() / (num_x * num_y * num_groups)); + } + + return rmse; +} diff --git a/src/linalg.h b/src/linalg.h index d5b592f45..112c61962 100644 --- a/src/linalg.h +++ b/src/linalg.h @@ -1,88 +1,54 @@ /** * @file linalg.h - * @brief Utility function for performing linear algebra in CMFD solver. - * @author Samuel Shaner (shaner@mit.edu) - * @date August 26, 2014 + * @details This file contains a library of functions for performing linear + * algebra operations. + * @date July 3, 2015 + * @author Samuel Shaner, MIT, Course 22 (shaner@mit.edu) */ -/** - * @brief Copy a vector to another vector. - * @param vector_from vector to be copied - * @param vector_to vector to receive copied data - * @param length length of vector - */ -template -inline void vector_copy(T* vector_from, T* vector_to, int length){ - - for (int i = 0; i < length; i++) - vector_to[i] = vector_from[i]; -} - - -/** - * @brief Assign all elements in a matrix to zero. - * @param matrix matrix to be zeroed - * @param width width of matrix row - * @param length length of matrix column - */ -template -inline void matrix_zero(T** matrix, int width, int length){ - - for (int i = 0; i < length; i++){ - for (int g = 0; g < width; g++) - matrix[i][g] = 0.0; - } -} +/* File: linalg.h */ +#ifndef LINALG_H_ +#define LINALG_H_ -/** - * @brief Assign all elements in a matrix to zero. - * @param vector vector to be zeroed - * @param length length of vector - */ -template -inline void vector_zero(T* vector, int length){ +#ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif +#include "log.h" +#include "Matrix.h" +#include "Vector.h" +#include "constants.h" +#include +#include +#include +#endif - for (int i = 0; i < length; i++) - vector[i] = 0.0; -} +FP_PRECISION eigenvalueSolve(Matrix* A, Matrix* M, Vector* X, FP_PRECISION tol, + FP_PRECISION SOR_factor=1.5); +void linearSolve(Matrix* A, Matrix* M, Vector* X, Vector* B, FP_PRECISION tol, + FP_PRECISION SOR_factor=1.5); +void matrixMultiplication(Matrix* A, Vector* X, Vector* B); +FP_PRECISION computeRMSE(Vector* x, Vector* y, bool integrated); /** - * @brief Multiply matrix by vector (i.e., y = M *x). - * @param matrix source matrix - * @param vector_x x vector - * @param vector_y y vector - * @param num_blocks number of cell blocks in M matrix. - * @param block_width number of elements in cell blocks in M matrix. + * @brief Transpose a 2D matrix. + * @param matrix array to transpose + * @param dim1 first dimension length + * @param dim2 second dimension length */ -template -inline void matrix_multiplication(T** matrix, T* vector_x, - T* vector_y, int num_blocks, - int block_width){ +template +inline void matrix_transpose(T* matrix, int dim1, int dim2) { - vector_zero(vector_y, num_blocks*block_width); + std::vector temp(dim1 * dim2); - for (int i = 0; i < num_blocks; i++){ - for (int g = 0; g < block_width; g++){ - for (int e = 0; e < block_width; e++){ - vector_y[i*block_width+g] += matrix[i][g*block_width+e] - * vector_x[i*block_width+e]; - } - } + for (int i=0; i < dim1; i++) { + for (int j=0; j < dim2; j++) + temp[i * dim1 + j] = matrix[j * dim1 + i]; } -} - -/** - * @brief Scale vectgor by some scalar value. - * @param vector vector to be scaled - * @param scale_value value to scale vector - * @param length vector length - */ -template -inline void vector_scale(T* vector, T scale_value, int length){ - - for (int i = 0; i < length; i++) - vector[i] *= scale_value; + std::copy(temp.begin(), temp.end(), matrix); } + +#endif /* LINALG_H_ */ diff --git a/src/log.cpp b/src/log.cpp index 9c1230dcd..3f5b3df61 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -69,6 +69,27 @@ static char title_char = '*'; static int line_length = 67; +/** + * @var log_error_lock + * @brief OpenMP mutex lock for ERROR messages which throw exceptions + */ +static omp_lock_t log_error_lock; + + +/** + * @brief Initializes the logger for use. + * @details This should be immediately called when the logger is imported + * into Python and before any of its other routines are called. The + * routine initializes an OpenMP mutual exclusion lock which is used + * to preclude race conditions from occurring when an ERROR message + * is reported and program execution is terminated. + */ +void initialize_logger() { + /* Initialize OpenMP mutex lock for ERROR messages with exceptions */ + omp_init_lock(&log_error_lock); +} + + /** * @brief Sets the output directory for log files. * @details If the directory does not exist, it creates it for the user. @@ -77,15 +98,14 @@ static int line_length = 67; void set_output_directory(char* directory) { output_directory = std::string(directory); + std::string log_directory; /* Check to see if directory exists - if not, create it */ struct stat st; - if (!stat(directory, &st) == 0) { - mkdir(directory, S_IRWXU); - mkdir((output_directory+"/log").c_str(), S_IRWXU); + if ((stat(directory, &st)) == 0) { + log_directory = std::string("") + directory + std::string("/log"); + mkdir(log_directory.c_str(), S_IRWXU); } - - return; } @@ -223,16 +243,10 @@ void set_log_level(const char* new_level) { log_level = RESULT; log_printf(INFO, "Logging level set to RESULT"); } - else if (strcmp("UNITTEST", new_level) == 0) { - log_level = UNITTEST; - log_printf(INFO, "Logging level set to UNITTEST"); - } else if (strcmp("ERROR", new_level) == 0) { log_level = ERROR; log_printf(INFO, "Logging level set to ERROR"); } - - return; } @@ -240,8 +254,44 @@ void set_log_level(const char* new_level) { * @brief Return the minimum level for log messages printed to the screen. * @return the minimum level for log messages */ -int get_log_level(){ - return log_level; +const char* get_log_level() { + + std::string level; + + switch (log_level) { + case (DEBUG): + level = "DEBUG"; + break; + case (INFO): + level = "INFO"; + break; + case (NORMAL): + level = "NORMAL"; + break; + case (SEPARATOR): + level = "SEPARATOR"; + break; + case (HEADER): + level = "HEADER"; + break; + case (TITLE): + level = "TITLE"; + break; + case (WARNING): + level = "WARNING"; + break; + case (CRITICAL): + level = "CRITICAL"; + break; + case (RESULT): + level = "RESULT"; + break; + case (ERROR): + level = "ERROR"; + break; + } + + return level.c_str(); } @@ -254,20 +304,29 @@ int get_log_level(){ */ void log_printf(logLevel level, const char* format, ...) { - char message[1024]; - std::string msg_string; if (level >= log_level) { va_list args; - va_start(args, format); - vsprintf(message, format, args); + + int size = 256; + char* buffer = new char[size]; + std::string msg_string; + int n = vsnprintf(buffer, size, format, args); + + /* Resize buffer as needed for strings longer than 256 characters */ + if (size <= n) { + delete [] buffer; + buffer = new char[n+1]; + n = vsnprintf(buffer, n+1, format, args); + } + + std::string msg = std::string(buffer); va_end(args); /* Append the log level to the message */ switch (level) { case (DEBUG): { - std::string msg = std::string(message); std::string level_prefix = "[ DEBUG ] "; /* If message is too long for a line, split into many lines */ @@ -282,7 +341,6 @@ void log_printf(logLevel level, const char* format, ...) { } case (INFO): { - std::string msg = std::string(message); std::string level_prefix = "[ INFO ] "; /* If message is too long for a line, split into many lines */ @@ -297,7 +355,6 @@ void log_printf(logLevel level, const char* format, ...) { } case (NORMAL): { - std::string msg = std::string(message); std::string level_prefix = "[ NORMAL ] "; /* If message is too long for a line, split into many lines */ @@ -321,33 +378,32 @@ void log_printf(logLevel level, const char* format, ...) { } case (HEADER): { - int size = strlen(message); + int size = strlen(buffer); int halfpad = (line_length - 4 - size) / 2; std::string pad1 = std::string(halfpad, header_char); std::string pad2 = std::string(halfpad + (line_length - 4 - size) % 2, header_char); std::string prefix = std::string("[ HEADER ] "); std::stringstream ss; - ss << prefix << pad1 << " " << message << " " << pad2 << "\n"; + ss << prefix << pad1 << " " << buffer << " " << pad2 << "\n"; msg_string = ss.str(); break; } case (TITLE): { - int size = strlen(message); + int size = strlen(buffer); int halfpad = (line_length - size) / 2; std::string pad = std::string(halfpad, ' '); std::string prefix = std::string("[ TITLE ] "); std::stringstream ss; ss << prefix << std::string(line_length, title_char) << "\n"; - ss << prefix << pad << message << pad << "\n"; + ss << prefix << pad << buffer << pad << "\n"; ss << prefix << std::string(line_length, title_char) << "\n"; msg_string = ss.str(); break; } case (WARNING): { - std::string msg = std::string(message); std::string level_prefix = "[ WARNING ] "; /* If message is too long for a line, split into many lines */ @@ -362,7 +418,6 @@ void log_printf(logLevel level, const char* format, ...) { } case (CRITICAL): { - std::string msg = std::string(message); std::string level_prefix = "[ CRITICAL] "; /* If message is too long for a line, split into many lines */ @@ -377,24 +432,8 @@ void log_printf(logLevel level, const char* format, ...) { } case (RESULT): { - std::string msg = std::string(message); std::string level_prefix = "[ RESULT ] "; - /* If message is too long for a line, split into many lines */ - if (int(msg.length()) > line_length) - msg_string = create_multiline_msg(level_prefix, msg); - - /* Puts message on single line */ - else - msg_string = level_prefix + msg + "\n"; - - break; - } - case (UNITTEST): - { - std::string msg = std::string(message); - std::string level_prefix = "[ TEST ] "; - /* If message is too long for a line, split into many lines */ if (int(msg.length()) > line_length) msg_string = create_multiline_msg(level_prefix, msg); @@ -408,11 +447,7 @@ void log_printf(logLevel level, const char* format, ...) { case (ERROR): { /* Create message based on runtime error stack */ - va_start(args, format); - vsprintf(message, format, args); - va_end(args); - std::string msg = std::string(message); - std::string level_prefix = "[ ERROR ] "; + std::string level_prefix = ""; /* If message is too long for a line, split into many lines */ if (int(msg.length()) > line_length) @@ -429,15 +464,12 @@ void log_printf(logLevel level, const char* format, ...) { /* If output directory was not defined by user, then log file is * written to a "log" subdirectory. Create it if it doesn't exist */ - if (output_directory.compare(".") == 0) { - struct stat st; - if (!stat("log", &st) == 0) - mkdir("log", S_IRWXU); - } + if (output_directory.compare(".") == 0) + set_output_directory((char*)"."); /* Write the message to the output file */ std::ofstream log_file; - log_file.open((output_directory + "/" + log_filename).c_str(), + log_file.open((output_directory + "/log/" + log_filename).c_str(), std::ios::app); /* Append date, time to the top of log output file */ @@ -453,19 +485,22 @@ void log_printf(logLevel level, const char* format, ...) { /* Write the log message to the log_file */ std::ofstream log_file; - log_file.open((output_directory + "/" + log_filename).c_str(), + log_file.open((output_directory + "/log/" + log_filename).c_str(), std::ios::app); log_file << msg_string; log_file.close(); /* Write the log message to the shell */ - std::cout << msg_string; + if (level == ERROR) { + omp_set_lock(&log_error_lock); + { + throw std::logic_error(msg_string.c_str()); + } + omp_unset_lock(&log_error_lock); + } + else + printf("%s", msg_string.c_str()); } - - - /* If the message was a runtime error, exit the program */ - if (level == ERROR) - exit(1); } @@ -489,7 +524,7 @@ std::string create_multiline_msg(std::string level, std::string message) { std::string msg_string; /* Loop over msg creating substrings for each line */ - while (end < size + line_length) { + while (end <= size + line_length) { /* Append log level to the beginning of each line */ msg_string += level; @@ -502,7 +537,7 @@ std::string create_multiline_msg(std::string level, std::string message) { substring = message.substr(start, line_length); /* Truncate substring to last complete word */ - if (end < size-1) { + if (end <= size) { int endspace = substring.find_last_of(" "); if (message.at(endspace+1) != ' ' && endspace != int(std::string::npos)) { @@ -519,7 +554,7 @@ std::string create_multiline_msg(std::string level, std::string message) { line_length -= 4; /* Update substring indices */ - start = end + 1; + start = end; end += line_length + 1; } diff --git a/src/log.h b/src/log.h index 8ab0dc55c..bba0b7a3d 100644 --- a/src/log.h +++ b/src/log.h @@ -12,6 +12,9 @@ #define LOG_H_ #ifdef __cplusplus +#ifdef SWIG +#include "Python.h" +#endif #include #include #include @@ -25,8 +28,14 @@ #include #include #include +#include +#endif + +#ifdef SWIG +#define printf PySys_WriteStdout #endif + /** * @enum logLevels * @brief Logging levels characterize an ordered set of message types @@ -67,9 +76,6 @@ typedef enum logLevels { /** A message containing program results */ RESULT, - /** A messsage for unit testing */ - UNITTEST, - /** A message reporting error conditions */ ERROR } logLevel; @@ -84,6 +90,7 @@ typedef enum logLevels { */ extern void set_err(const char *msg); +void initialize_logger(); void set_output_directory(char* directory); const char* get_output_directory(); void set_log_filename(char* filename); @@ -97,7 +104,7 @@ void set_title_character(char c); char get_title_character(); void set_line_length(int length); void set_log_level(const char* new_level); -int get_log_level(); +const char* get_log_level(); void log_printf(logLevel level, const char *format, ...); std::string create_multiline_msg(std::string level, std::string message); diff --git a/src/pairwise_sum.h b/src/pairwise_sum.h index 0547b8dd6..204e0347e 100644 --- a/src/pairwise_sum.h +++ b/src/pairwise_sum.h @@ -23,7 +23,7 @@ inline T pairwise_sum(T* vector, int length) { /* Base case: if length is less than 16, perform summation */ if (length < 16) { - #pragma simd reduction(+:sum) +#pragma simd reduction(+:sum) for (int i=0; i < length; i++) sum += vector[i]; } diff --git a/tests/cleanup b/tests/cleanup new file mode 100755 index 000000000..b3e74c7ba --- /dev/null +++ b/tests/cleanup @@ -0,0 +1,10 @@ +#!/bin/bash + +# This simple script ensures that all binary +# output files have been deleted in all the +# folders. This can occur if a previous error +# occurred and the test suite was rerun without +# deleting left over binary files. This will +# cause an assertion error in some of the +# tests. +find . \( -name ".data" -o -name "*.h5" \) -exec rm -f {} \; diff --git a/tests/input_set.py b/tests/input_set.py new file mode 100644 index 000000000..69649995b --- /dev/null +++ b/tests/input_set.py @@ -0,0 +1,488 @@ +import sys +from abc import ABCMeta, abstractmethod + +import numpy + +sys.path.insert(0, 'openmoc') +import openmoc + + +class InputSet(object): + """An abstract class for defining OpenMOC test geometries.""" + + __metaclass__ = ABCMeta + + def __init__(self): + self.materials = {} + self.geometry = None + + @abstractmethod + def create_materials(self): + """Instantiate Materials.""" + return + + @abstractmethod + def create_geometry(self): + """Instantiate a Geometry.""" + return + + +class HomInfMedInput(InputSet): + """A homogeneous infinite medium problem with 2-group cross sections.""" + + def create_materials(self): + + sigma_f = numpy.array([0.000625, 0.135416667]) + nu_sigma_f = numpy.array([0.0015, 0.325]) + sigma_s = numpy.array([[0.1, 0.117], [0., 1.42]]) + chi = numpy.array([1.0, 0.0]) + sigma_t = numpy.array([0.2208, 1.604]) + + self.materials['infinite medium'] = openmoc.Material() + self.materials['infinite medium'].setName('2-group infinite medium') + self.materials['infinite medium'].setNumEnergyGroups(2) + self.materials['infinite medium'].setSigmaF(sigma_f) + self.materials['infinite medium'].setNuSigmaF(nu_sigma_f) + self.materials['infinite medium'].setSigmaS(sigma_s.flat) + self.materials['infinite medium'].setChi(chi) + self.materials['infinite medium'].setSigmaT(sigma_t) + + def create_geometry(self): + """Instantiate an infinite medium lattice Geometry.""" + + length = 2.5 + num_cells_x = 10 + num_cells_y = 10 + + xmin = openmoc.XPlane(x=-length/2., name='xmin') + xmax = openmoc.XPlane(x=+length/2., name='xmax') + ymin = openmoc.YPlane(y=-length/2., name='ymin') + ymax = openmoc.YPlane(y=+length/2., name='ymax') + + xmax.setBoundaryType(openmoc.REFLECTIVE) + xmin.setBoundaryType(openmoc.REFLECTIVE) + ymin.setBoundaryType(openmoc.REFLECTIVE) + ymax.setBoundaryType(openmoc.REFLECTIVE) + + fill = openmoc.Cell(name='fill') + fill.setFill(self.materials['infinite medium']) + + root_cell = openmoc.Cell(name='root cell') + root_cell.addSurface(halfspace=+1, surface=xmin) + root_cell.addSurface(halfspace=-1, surface=xmax) + root_cell.addSurface(halfspace=+1, surface=ymin) + root_cell.addSurface(halfspace=-1, surface=ymax) + + fill_universe = openmoc.Universe(name='homogeneous fill cell') + fill_universe.addCell(fill) + + root_universe = openmoc.Universe(name='root universe') + root_universe.addCell(root_cell) + + lattice = openmoc.Lattice(name='MxN lattice') + lattice.setWidth(width_x=length/num_cells_x, width_y=length/num_cells_y) + lattice.setUniverses([[[fill_universe] * num_cells_x]*num_cells_y]) + root_cell.setFill(lattice) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(HomInfMedInput, self).create_geometry() + + +class PinCellInput(InputSet): + """A pin cell problem from sample-input/pin-cell.""" + + def create_materials(self): + """Instantiate C5G7 Materials.""" + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + def create_geometry(self): + """Instantiate a pin cell Geometry.""" + + zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, radius=1.0, name='pin') + xmin = openmoc.XPlane(x=-2.0, name='xmin') + xmax = openmoc.XPlane(x=+2.0, name='xmax') + ymin = openmoc.YPlane(y=-2.0, name='ymin') + ymax = openmoc.YPlane(y=+2.0, name='ymax') + + xmin.setBoundaryType(openmoc.REFLECTIVE) + xmax.setBoundaryType(openmoc.REFLECTIVE) + ymin.setBoundaryType(openmoc.REFLECTIVE) + ymax.setBoundaryType(openmoc.REFLECTIVE) + + fuel = openmoc.Cell(name='fuel') + fuel.setFill(self.materials['UO2']) + fuel.addSurface(halfspace=-1, surface=zcylinder) + + moderator = openmoc.Cell(name='moderator') + moderator.setFill(self.materials['Water']) + moderator.addSurface(halfspace=+1, surface=zcylinder) + moderator.addSurface(halfspace=+1, surface=xmin) + moderator.addSurface(halfspace=-1, surface=xmax) + moderator.addSurface(halfspace=+1, surface=ymin) + moderator.addSurface(halfspace=-1, surface=ymax) + + root_universe = openmoc.Universe(name='root universe') + root_universe.addCell(fuel) + root_universe.addCell(moderator) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(PinCellInput, self).create_geometry() + + +class GridInput(InputSet): + """Sets up a simple grid problem using explicit planes""" + + def create_materials(self): + """Instantiate C5G7 Materials.""" + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + def create_geometry(self): + """Instantiate a 3x3 grid Geometry.""" + + # Create the planes that bound the cell and geometry + xplanes = [None] * 4 + yplanes = [None] * 4 + for i in range(4): + val = -3.0 + 6.0/3 * i + xplanes[i] = openmoc.XPlane(x=val, name='xplane' + str(i)) + yplanes[i] = openmoc.YPlane(y=val, name='yplane' + str(i)) + + xplanes[0].setBoundaryType(openmoc.REFLECTIVE) + xplanes[-1].setBoundaryType(openmoc.REFLECTIVE) + yplanes[0].setBoundaryType(openmoc.REFLECTIVE) + yplanes[-1].setBoundaryType(openmoc.REFLECTIVE) + + # Create the cells and set the central cell to UO2, the rest as water + cells = [[None]*3 for i in range(3)] + for i in range(3): + for j in range(3): + cells[i][j] = openmoc.Cell(name='Cell ' + str(3*i+j)) + if i == 1 and j == 1: + cells[i][j].setFill(self.materials['UO2']) + else: + cells[i][j].setFill(self.materials['Water']) + cells[i][j].addSurface(halfspace=+1, surface=xplanes[i]) + cells[i][j].addSurface(halfspace=-1, surface=xplanes[i+1]) + cells[i][j].addSurface(halfspace=+1, surface=yplanes[j]) + cells[i][j].addSurface(halfspace=-1, surface=yplanes[j+1]) + + # Add the cells to the universe + root_universe = openmoc.Universe(name='root universe') + for i in range(3): + for j in range(3): + root_universe.addCell(cells[i][j]) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(GridInput, self).create_geometry() + + +class LatticeGridInput(InputSet): + """A simple lattice problem equivalent to the grid case""" + + def create_materials(self): + """Instantiate C5G7 Materials.""" + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + def create_geometry(self): + """Instantiate a 3x3 grid Geometry by making a lattice""" + + # Create the planes bounding the geometry + xmin = openmoc.XPlane(x=-3.0, name='xmin') + xmax = openmoc.XPlane(x=3.0, name='xmax') + ymin = openmoc.YPlane(y=-3.0, name='ymin') + ymax = openmoc.YPlane(y=3.0, name='ymax') + + xmin.setBoundaryType(openmoc.REFLECTIVE) + xmax.setBoundaryType(openmoc.REFLECTIVE) + ymin.setBoundaryType(openmoc.REFLECTIVE) + ymax.setBoundaryType(openmoc.REFLECTIVE) + + # Create the root cell, bounded by the geometry bounds + root_cell = openmoc.Cell(name='root cell') + root_cell.addSurface(halfspace=+1, surface=xmin) + root_cell.addSurface(halfspace=-1, surface=xmax) + root_cell.addSurface(halfspace=+1, surface=ymin) + root_cell.addSurface(halfspace=-1, surface=ymax) + + # Create UO2 and water cells + uo2_cell = openmoc.Cell(name='UO2 Cell') + uo2_cell.setFill(self.materials['UO2']) + water_cell = openmoc.Cell(name='Water Cell') + water_cell.setFill(self.materials['Water']) + + # Create universes and fill with the associated cell + root_universe = openmoc.Universe(name='root universe') + root_universe.addCell(root_cell) + uo2 = openmoc.Universe(name='uo2 universe') + uo2.addCell(uo2_cell) + water = openmoc.Universe(name='uo2 universe') + water.addCell(water_cell) + + # Create the lattice and fill it with the appropriate universes + lattice = openmoc.Lattice(name='3x3 lattice') + lattice.setWidth(width_x=2.0, width_y=2.0) + lattice.setUniverses([[[water, water, water], + [water, uo2, water], + [water, water, water]]]) + root_cell.setFill(lattice) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(LatticeGridInput, self).create_geometry() + + + +class SimpleLatticeInput(InputSet): + """A 4x4 pin cell lattice problem from sample-input/simple-lattice.""" + + def create_materials(self): + """Instantiate C5G7 Materials.""" + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + def create_geometry(self): + """Instantiate a 4x4 pin cell lattice Geometry.""" + + xmin = openmoc.XPlane(x=-2.0, name='xmin') + xmax = openmoc.XPlane(x=+2.0, name='xmax') + ymax = openmoc.YPlane(y=+2.0, name='ymin') + ymin = openmoc.YPlane(y=-2.0, name='ymax') + boundaries = [xmin, xmax, ymin, ymax] + + large_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, + radius=0.4, name='large pin') + medium_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, + radius=0.3, name='medium pin') + small_zcylinder = openmoc.ZCylinder(x=0.0, y=0.0, + radius=0.2, name='small pin') + + for boundary in boundaries: boundary.setBoundaryType(openmoc.REFLECTIVE) + + large_fuel = openmoc.Cell(name='large pin fuel') + large_fuel.setNumRings(3) + large_fuel.setNumSectors(8) + large_fuel.setFill(self.materials['UO2']) + large_fuel.addSurface(halfspace=-1, surface=large_zcylinder) + + large_moderator = openmoc.Cell(name='large pin moderator') + large_moderator.setNumSectors(8) + large_moderator.setFill(self.materials['Water']) + large_moderator.addSurface(halfspace=+1, surface=large_zcylinder) + + medium_fuel = openmoc.Cell(name='medium pin fuel') + medium_fuel.setNumRings(3) + medium_fuel.setNumSectors(8) + medium_fuel.setFill(self.materials['UO2']) + medium_fuel.addSurface(halfspace=-1, surface=medium_zcylinder) + + medium_moderator = openmoc.Cell(name='medium pin moderator') + medium_moderator.setNumSectors(8) + medium_moderator.setFill(self.materials['Water']) + medium_moderator.addSurface(halfspace=+1, surface=medium_zcylinder) + + small_fuel = openmoc.Cell(name='small pin fuel') + small_fuel.setNumRings(3) + small_fuel.setNumSectors(8) + small_fuel.setFill(self.materials['UO2']) + small_fuel.addSurface(halfspace=-1, surface=small_zcylinder) + + small_moderator = openmoc.Cell(name='small pin moderator') + small_moderator.setNumSectors(8) + small_moderator.setFill(self.materials['Water']) + small_moderator.addSurface(halfspace=+1, surface=small_zcylinder) + + lattice_cell = openmoc.Cell(name='lattice cell') + + root_cell = openmoc.Cell(name='root cell') + root_cell.addSurface(halfspace=+1, surface=boundaries[0]) + root_cell.addSurface(halfspace=-1, surface=boundaries[1]) + root_cell.addSurface(halfspace=+1, surface=boundaries[2]) + root_cell.addSurface(halfspace=-1, surface=boundaries[3]) + + pin1 = openmoc.Universe(name='large pin cell') + pin2 = openmoc.Universe(name='medium pin cell') + pin3 = openmoc.Universe(name='small pin cell') + assembly = openmoc.Universe(name='2x2 lattice') + root_universe = openmoc.Universe(name='root universe') + + pin1.addCell(large_fuel) + pin1.addCell(large_moderator) + pin2.addCell(medium_fuel) + pin2.addCell(medium_moderator) + pin3.addCell(small_fuel) + pin3.addCell(small_moderator) + assembly.addCell(lattice_cell) + root_universe.addCell(root_cell) + + # 2x2 assembly + lattice = openmoc.Lattice(name='2x2 lattice') + lattice.setWidth(width_x=1.0, width_y=1.0) + lattice.setUniverses([[[pin1, pin2], [pin1, pin3]]]) + lattice_cell.setFill(lattice) + + # 2x2 core + core = openmoc.Lattice(name='2x2 core') + core.setWidth(width_x=2.0, width_y=2.0) + core.setUniverses([[[assembly, assembly], [assembly, assembly]]]) + root_cell.setFill(core) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(SimpleLatticeInput, self).create_geometry() + + +class PwrAssemblyInput(InputSet): + """A 17x17 pin cell lattice problem from sample-input/ipython-notebook.""" + + def create_materials(self): + """Instantiate C5G7 Materials.""" + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + def create_geometry(self): + """Instantiate a 17x17 pin cell lattice Geometry.""" + + # Create ZCylinder for the fuel and moderator + fuel_radius = openmoc.ZCylinder(x=0.0, y=0.0, radius=0.54) + + # Create planes to bound the entire geometry + xmin = openmoc.XPlane(x=-10.71, name='xmin') + xmax = openmoc.XPlane(x=+10.71, name='xmax') + ymin = openmoc.YPlane(y=-10.71, name='ymin') + ymax = openmoc.YPlane(y=+10.71, name='xmax') + + xmin.setBoundaryType(openmoc.REFLECTIVE) + xmax.setBoundaryType(openmoc.REFLECTIVE) + ymin.setBoundaryType(openmoc.REFLECTIVE) + ymax.setBoundaryType(openmoc.REFLECTIVE) + + # 4.3% MOX pin cell + mox43_cell = openmoc.Cell() + mox43_cell.setFill(self.materials['MOX-4.3%']) + mox43_cell.setNumRings(3) + mox43_cell.setNumSectors(8) + mox43_cell.addSurface(-1, fuel_radius) + + mox43 = openmoc.Universe(name='MOX-4.3%') + mox43.addCell(mox43_cell) + + # 7% MOX pin cell + mox7_cell = openmoc.Cell() + mox7_cell.setFill(self.materials['MOX-7%']) + mox7_cell.setNumRings(3) + mox7_cell.setNumSectors(8) + mox7_cell.addSurface(-1, fuel_radius) + + mox7 = openmoc.Universe(name='MOX-7%') + mox7.addCell(mox7_cell) + + # 8.7% MOX pin cell + mox87_cell = openmoc.Cell() + mox87_cell.setFill(self.materials['MOX-8.7%']) + mox87_cell.setNumRings(3) + mox87_cell.setNumSectors(8) + mox87_cell.addSurface(-1, fuel_radius) + + mox87 = openmoc.Universe(name='MOX-8.7%') + mox87.addCell(mox87_cell) + + # Fission chamber pin cell + fission_chamber_cell = openmoc.Cell() + fission_chamber_cell.setFill(self.materials['Fission Chamber']) + fission_chamber_cell.setNumRings(3) + fission_chamber_cell.setNumSectors(8) + fission_chamber_cell.addSurface(-1, fuel_radius) + + fission_chamber = openmoc.Universe(name='Fission Chamber') + fission_chamber.addCell(fission_chamber_cell) + + # Guide tube pin cell + guide_tube_cell = openmoc.Cell() + guide_tube_cell.setFill(self.materials['Guide Tube']) + guide_tube_cell.setNumRings(3) + guide_tube_cell.setNumSectors(8) + guide_tube_cell.addSurface(-1, fuel_radius) + + guide_tube = openmoc.Universe(name='Guide Tube') + guide_tube.addCell(guide_tube_cell) + + # Moderator cell + moderator = openmoc.Cell() + moderator.setFill(self.materials['Water']) + moderator.addSurface(+1, fuel_radius) + moderator.setNumRings(3) + moderator.setNumSectors(8) + + # Add moderator to each pin cell + pins = [mox43, mox7, mox87, fission_chamber, guide_tube] + for pin in pins: + pin.addCell(moderator) + + # CellFills for the assembly + assembly1_cell = openmoc.Cell(name='Assembly 1') + assembly1 = openmoc.Universe(name='Assembly 1') + assembly1.addCell(assembly1_cell) + + # A mixed enrichment PWR MOX fuel assembly + assembly = openmoc.Lattice(name='MOX Assembly') + assembly.setWidth(width_x=1.26, width_y=1.26) + + # Create a template to map to pin cell types + template = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 5, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1], + [1, 2, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 2, 1], + [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1], + [1, 2, 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 2, 1], + [1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 1], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + + universes = {1 : mox43, 2 : mox7, 3 : mox87, + 4 : guide_tube, 5 : fission_chamber} + + for i in range(17): + for j in range(17): + template[i][j] = universes[template[i][j]] + + assembly.setUniverses([template]) + + # Root Cell/Universe + root_cell = openmoc.Cell(name='Full Geometry') + root_cell.setFill(assembly) + root_cell.addSurface(+1, xmin) + root_cell.addSurface(-1, xmax) + root_cell.addSurface(+1, ymin) + root_cell.addSurface(-1, ymax) + + root_universe = openmoc.Universe(name='Root Universe') + root_universe.addCell(root_cell) + + self.geometry = openmoc.Geometry() + self.geometry.setRootUniverse(root_universe) + + super(PwrAssemblyInput, self).create_geometry() diff --git a/tests/pickle-rcparams.py b/tests/pickle-rcparams.py new file mode 100644 index 000000000..e9c2260c8 --- /dev/null +++ b/tests/pickle-rcparams.py @@ -0,0 +1,294 @@ +from cycler import cycler +import pickle + +# Default matplotlib 1.5 rcparams for Anaconda +rcparams={u'agg.path.chunksize': 0, + u'animation.avconv_args': [], + u'animation.avconv_path': u'avconv', + u'animation.bitrate': -1, + u'animation.codec': u'mpeg4', + u'animation.convert_args': [], + u'animation.convert_path': u'convert', + u'animation.ffmpeg_args': [], + u'animation.ffmpeg_path': u'ffmpeg', + u'animation.frame_format': u'png', + u'animation.html': u'none', + u'animation.mencoder_args': [], + u'animation.mencoder_path': u'mencoder', + u'animation.writer': u'ffmpeg', + u'axes.axisbelow': False, + u'axes.edgecolor': u'k', + u'axes.facecolor': u'w', + u'axes.formatter.limits': [-7, 7], + u'axes.formatter.use_locale': False, + u'axes.formatter.use_mathtext': False, + u'axes.formatter.useoffset': True, + u'axes.grid': False, + u'axes.grid.axis': u'both', + u'axes.grid.which': u'major', + u'axes.hold': True, + u'axes.labelcolor': u'k', + u'axes.labelpad': 5.0, + u'axes.labelsize': u'medium', + u'axes.labelweight': u'normal', + u'axes.linewidth': 1.0, + u'axes.prop_cycle': cycler(u'color', [u'b', u'g', u'r', u'c', u'm', u'y', u'k']), + u'axes.spines.bottom': True, + u'axes.spines.left': True, + u'axes.spines.right': True, + u'axes.spines.top': True, + u'axes.titlesize': u'large', + u'axes.titleweight': u'normal', + u'axes.unicode_minus': True, + u'axes.xmargin': 0.0, + u'axes.ymargin': 0.0, + u'axes3d.grid': True, + u'backend': u'agg', + u'backend.qt4': u'PyQt4', + u'backend.qt5': u'PyQt5', + u'backend_fallback': True, + u'boxplot.bootstrap': None, + u'boxplot.boxprops.color': u'b', + u'boxplot.boxprops.linestyle': u'-', + u'boxplot.boxprops.linewidth': 1.0, + u'boxplot.capprops.color': u'k', + u'boxplot.capprops.linestyle': u'-', + u'boxplot.capprops.linewidth': 1.0, + u'boxplot.flierprops.color': u'b', + u'boxplot.flierprops.linestyle': u'none', + u'boxplot.flierprops.linewidth': 1.0, + u'boxplot.flierprops.marker': u'+', + u'boxplot.flierprops.markeredgecolor': u'k', + u'boxplot.flierprops.markerfacecolor': u'b', + u'boxplot.flierprops.markersize': 6.0, + u'boxplot.meanline': False, + u'boxplot.meanprops.color': u'r', + u'boxplot.meanprops.linestyle': u'-', + u'boxplot.meanprops.linewidth': 1.0, + u'boxplot.medianprops.color': u'r', + u'boxplot.medianprops.linestyle': u'-', + u'boxplot.medianprops.linewidth': 1.0, + u'boxplot.notch': False, + u'boxplot.patchartist': False, + u'boxplot.showbox': True, + u'boxplot.showcaps': True, + u'boxplot.showfliers': True, + u'boxplot.showmeans': False, + u'boxplot.vertical': True, + u'boxplot.whiskerprops.color': u'b', + u'boxplot.whiskerprops.linestyle': u'--', + u'boxplot.whiskerprops.linewidth': 1.0, + u'boxplot.whiskers': 1.5, + u'contour.corner_mask': True, + u'contour.negative_linestyle': u'dashed', + u'docstring.hardcopy': False, + u'errorbar.capsize': 3.0, + u'examples.directory': u'', + u'figure.autolayout': False, + u'figure.dpi': 80.0, + u'figure.edgecolor': u'w', + u'figure.facecolor': u'0.75', + u'figure.figsize': [8.0, 6.0], + u'figure.frameon': True, + u'figure.max_open_warning': 20, + u'figure.subplot.bottom': 0.1, + u'figure.subplot.hspace': 0.2, + u'figure.subplot.left': 0.125, + u'figure.subplot.right': 0.9, + u'figure.subplot.top': 0.9, + u'figure.subplot.wspace': 0.2, + u'figure.titlesize': u'medium', + u'figure.titleweight': u'normal', + u'font.cursive': [u'Apple Chancery', + u'Textile', + u'Zapf Chancery', + u'Sand', + u'Script MT', + u'Felipa', + u'cursive'], + u'font.family': [u'sans-serif'], + u'font.fantasy': [u'Comic Sans MS', + u'Chicago', + u'Charcoal', + u'ImpactWestern', + u'Humor Sans', + u'fantasy'], + u'font.monospace': [u'Bitstream Vera Sans Mono', + u'DejaVu Sans Mono', + u'Andale Mono', + u'Nimbus Mono L', + u'Courier New', + u'Courier', + u'Fixed', + u'Terminal', + u'monospace'], + u'font.sans-serif': [u'Bitstream Vera Sans', + u'DejaVu Sans', + u'Lucida Grande', + u'Verdana', + u'Geneva', + u'Lucid', + u'Arial', + u'Helvetica', + u'Avant Garde', + u'sans-serif'], + u'font.serif': [u'Bitstream Vera Serif', + u'DejaVu Serif', + u'New Century Schoolbook', + u'Century Schoolbook L', + u'Utopia', + u'ITC Bookman', + u'Bookman', + u'Nimbus Roman No9 L', + u'Times New Roman', + u'Times', + u'Palatino', + u'Charter', + u'serif'], + u'font.size': 12.0, + u'font.stretch': u'normal', + u'font.style': u'normal', + u'font.variant': u'normal', + u'font.weight': u'normal', + u'grid.alpha': 1.0, + u'grid.color': u'k', + u'grid.linestyle': u':', + u'grid.linewidth': 0.5, + u'image.aspect': u'equal', + u'image.cmap': u'jet', + u'image.composite_image': True, + u'image.interpolation': u'bilinear', + u'image.lut': 256, + u'image.origin': u'upper', + u'image.resample': False, + u'interactive': False, + u'keymap.all_axes': [u'a'], + u'keymap.back': [u'left', u'c', u'backspace'], + u'keymap.forward': [u'right', u'v'], + u'keymap.fullscreen': [u'f', u'ctrl+f'], + u'keymap.grid': [u'g'], + u'keymap.home': [u'h', u'r', u'home'], + u'keymap.pan': [u'p'], + u'keymap.quit': [u'ctrl+w', u'cmd+w'], + u'keymap.save': [u's', u'ctrl+s'], + u'keymap.xscale': [u'k', u'L'], + u'keymap.yscale': [u'l'], + u'keymap.zoom': [u'o'], + u'legend.borderaxespad': 0.5, + u'legend.borderpad': 0.4, + u'legend.columnspacing': 2.0, + u'legend.edgecolor': u'inherit', + u'legend.facecolor': u'inherit', + u'legend.fancybox': False, + u'legend.fontsize': u'large', + u'legend.framealpha': None, + u'legend.frameon': True, + u'legend.handleheight': 0.7, + u'legend.handlelength': 2.0, + u'legend.handletextpad': 0.8, + u'legend.isaxes': True, + u'legend.labelspacing': 0.5, + u'legend.loc': u'upper right', + u'legend.markerscale': 1.0, + u'legend.numpoints': 2, + u'legend.scatterpoints': 3, + u'legend.shadow': False, + u'lines.antialiased': True, + u'lines.color': u'b', + u'lines.dash_capstyle': u'butt', + u'lines.dash_joinstyle': u'round', + u'lines.linestyle': u'-', + u'lines.linewidth': 1.0, + u'lines.marker': u'None', + u'lines.markeredgewidth': 0.5, + u'lines.markersize': 6.0, + u'lines.solid_capstyle': u'projecting', + u'lines.solid_joinstyle': u'round', + u'markers.fillstyle': u'full', + u'mathtext.bf': u'serif:bold', + u'mathtext.cal': u'cursive', + u'mathtext.default': u'it', + u'mathtext.fallback_to_cm': True, + u'mathtext.fontset': u'cm', + u'mathtext.it': u'serif:italic', + u'mathtext.rm': u'serif', + u'mathtext.sf': u'sans\\-serif', + u'mathtext.tt': u'monospace', + u'nbagg.transparent': True, + u'patch.antialiased': True, + u'patch.edgecolor': u'k', + u'patch.facecolor': u'b', + u'patch.linewidth': 1.0, + u'path.effects': [], + u'path.simplify': True, + u'path.simplify_threshold': 0.1111111111111111, + u'path.sketch': None, + u'path.snap': True, + u'pdf.compression': 6, + u'pdf.fonttype': 3, + u'pdf.inheritcolor': False, + u'pdf.use14corefonts': False, + u'pgf.debug': False, + u'pgf.preamble': [], + u'pgf.rcfonts': True, + u'pgf.texsystem': u'xelatex', + u'plugins.directory': u'.matplotlib_plugins', + u'polaraxes.grid': True, + u'ps.distiller.res': 6000, + u'ps.fonttype': 3, + u'ps.papersize': u'letter', + u'ps.useafm': False, + u'ps.usedistiller': False, + u'savefig.bbox': None, + u'savefig.directory': u'~', + u'savefig.dpi': 100.0, + u'savefig.edgecolor': u'w', + u'savefig.facecolor': u'w', + u'savefig.format': u'png', + u'savefig.frameon': True, + u'savefig.jpeg_quality': 95, + u'savefig.orientation': u'portrait', + u'savefig.pad_inches': 0.1, + u'savefig.transparent': False, + u'svg.fonttype': u'path', + u'svg.image_inline': True, + u'svg.image_noscale': False, + u'text.antialiased': True, + u'text.color': u'k', + u'text.dvipnghack': None, + u'text.hinting': u'auto', + u'text.hinting_factor': 8, + u'text.latex.preamble': [], + u'text.latex.preview': False, + u'text.latex.unicode': False, + u'text.usetex': False, + u'timezone': u'UTC', + u'tk.window_focus': False, + u'toolbar': u'toolbar2', + u'verbose.fileo': u'sys.stdout', + u'verbose.level': u'silent', + u'webagg.open_in_browser': True, + u'webagg.port': 8988, + u'webagg.port_retries': 50, + u'xtick.color': u'k', + u'xtick.direction': u'in', + u'xtick.labelsize': u'medium', + u'xtick.major.pad': 4.0, + u'xtick.major.size': 4.0, + u'xtick.major.width': 0.5, + u'xtick.minor.pad': 4.0, + u'xtick.minor.size': 2.0, + u'xtick.minor.visible': False, + u'xtick.minor.width': 0.5, + u'ytick.color': u'k', + u'ytick.direction': u'in', + u'ytick.labelsize': u'medium', + u'ytick.major.pad': 4.0, + u'ytick.major.size': 4.0, + u'ytick.major.width': 0.5, + u'ytick.minor.pad': 4.0, + u'ytick.minor.size': 2.0, + u'ytick.minor.visible': False, + u'ytick.minor.width': 0.5} + +pickle.dump(rcparams, open('rcparams.pkl', 'wb')) diff --git a/tests/rcparams.pkl b/tests/rcparams.pkl new file mode 100644 index 000000000..c2dc91af7 --- /dev/null +++ b/tests/rcparams.pkl @@ -0,0 +1,981 @@ +(dp0 +Vanimation.frame_format +p1 +Vpng +p2 +sVfigure.subplot.right +p3 +F0.9 +sVimage.lut +p4 +I256 +sVfont.fantasy +p5 +(lp6 +VComic Sans MS +p7 +aVChicago +p8 +aVCharcoal +p9 +aVImpactWestern +p10 +aVHumor Sans +p11 +aVfantasy +p12 +asVxtick.minor.pad +p13 +F4.0 +sVsavefig.frameon +p14 +I01 +sVboxplot.flierprops.linewidth +p15 +F1.0 +sVsvg.fonttype +p16 +Vpath +p17 +sVboxplot.whiskerprops.color +p18 +Vb +p19 +sVfigure.subplot.hspace +p20 +F0.2 +sVkeymap.fullscreen +p21 +(lp22 +Vf +p23 +aVctrl+f +p24 +asVxtick.direction +p25 +Vin +p26 +sVmathtext.fontset +p27 +Vcm +p28 +sVanimation.mencoder_path +p29 +Vmencoder +p30 +sVkeymap.pan +p31 +(lp32 +Vp +p33 +asVnbagg.transparent +p34 +I01 +sVlines.markersize +p35 +F6.0 +sVimage.origin +p36 +Vupper +p37 +sVpatch.edgecolor +p38 +Vk +p39 +sVlegend.labelspacing +p40 +F0.5 +sVexamples.directory +p41 +V +p42 +sVtext.antialiased +p43 +I01 +sVsavefig.bbox +p44 +NsVmathtext.rm +p45 +Vserif +p46 +sVlegend.facecolor +p47 +Vinherit +p48 +sVaxes.formatter.limits +p49 +(lp50 +I-7 +aI7 +asVfont.serif +p51 +(lp52 +VBitstream Vera Serif +p53 +aVDejaVu Serif +p54 +aVNew Century Schoolbook +p55 +aVCentury Schoolbook L +p56 +aVUtopia +p57 +aVITC Bookman +p58 +aVBookman +p59 +aVNimbus Roman No9 L +p60 +aVTimes New Roman +p61 +aVTimes +p62 +aVPalatino +p63 +aVCharter +p64 +ag46 +asVaxes.grid.axis +p65 +Vboth +p66 +sVtk.window_focus +p67 +I00 +sVaxes.formatter.use_mathtext +p68 +I00 +sVytick.major.width +p69 +F0.5 +sVpath.effects +p70 +(lp71 +sVaxes.xmargin +p72 +F0.0 +sVsavefig.facecolor +p73 +Vw +p74 +sVboxplot.flierprops.color +p75 +g19 +sVytick.minor.size +p76 +F2.0 +sVsavefig.pad_inches +p77 +F0.1 +sVfont.stretch +p78 +Vnormal +p79 +sVtext.dvipnghack +p80 +NsVpath.sketch +p81 +NsVsavefig.directory +p82 +V~ +p83 +sVytick.color +p84 +g39 +sVimage.aspect +p85 +Vequal +p86 +sVfigure.subplot.left +p87 +F0.125 +sVxtick.color +p88 +g39 +sVxtick.major.pad +p89 +F4.0 +sVxtick.labelsize +p90 +Vmedium +p91 +sVboxplot.flierprops.markeredgecolor +p92 +g39 +sVboxplot.bootstrap +p93 +NsVfigure.figsize +p94 +(lp95 +F8.0 +aF6.0 +asVaxes.linewidth +p96 +F1.0 +sVmathtext.fallback_to_cm +p97 +I01 +sVsavefig.jpeg_quality +p98 +I95 +sVaxes.spines.top +p99 +I01 +sVfont.size +p100 +F12.0 +sVpath.simplify +p101 +I01 +sVkeymap.all_axes +p102 +(lp103 +Va +p104 +asVaxes.spines.bottom +p105 +I01 +sVtext.hinting +p106 +Vauto +p107 +sVgrid.linewidth +p108 +F0.5 +sVlegend.framealpha +p109 +NsVfigure.autolayout +p110 +I00 +sVfigure.facecolor +p111 +V0.75 +p112 +sVanimation.convert_args +p113 +(lp114 +sVps.usedistiller +p115 +I00 +sVlegend.isaxes +p116 +I01 +sVfigure.edgecolor +p117 +g74 +sVmathtext.tt +p118 +Vmonospace +p119 +sVaxes.formatter.use_locale +p120 +I00 +sVlines.markeredgewidth +p121 +F0.5 +sVkeymap.home +p122 +(lp123 +Vh +p124 +aVr +p125 +aVhome +p126 +asVboxplot.medianprops.linewidth +p127 +F1.0 +sVboxplot.capprops.linestyle +p128 +V- +p129 +sVaxes.edgecolor +p130 +g39 +sVytick.minor.width +p131 +F0.5 +sVaxes.titlesize +p132 +Vlarge +p133 +sVbackend +p134 +Vagg +p135 +sVboxplot.meanprops.linestyle +p136 +g129 +sVkeymap.xscale +p137 +(lp138 +g39 +aVL +p139 +asVlegend.fontsize +p140 +g133 +sVlines.solid_capstyle +p141 +Vprojecting +p142 +sVtoolbar +p143 +Vtoolbar2 +p144 +sVaxes.unicode_minus +p145 +I01 +sVfigure.frameon +p146 +I01 +sVtext.hinting_factor +p147 +I8 +sVanimation.mencoder_args +p148 +(lp149 +sVpdf.inheritcolor +p150 +I00 +sVpdf.use14corefonts +p151 +I00 +sVlegend.markerscale +p152 +F1.0 +sVboxplot.meanprops.linewidth +p153 +F1.0 +sVpatch.antialiased +p154 +I01 +sVfont.style +p155 +g79 +sVfigure.titlesize +p156 +g91 +sVbackend_fallback +p157 +I01 +sVboxplot.boxprops.color +p158 +g19 +sVplugins.directory +p159 +V.matplotlib_plugins +p160 +sVgrid.linestyle +p161 +V: +p162 +sVaxes.labelcolor +p163 +g39 +sVboxplot.flierprops.markerfacecolor +p164 +g19 +sVlegend.loc +p165 +Vupper right +p166 +sVboxplot.boxprops.linestyle +p167 +g129 +sVcontour.negative_linestyle +p168 +Vdashed +p169 +sVsvg.image_inline +p170 +I01 +sVboxplot.capprops.linewidth +p171 +F1.0 +sVaxes.grid +p172 +I00 +sVaxes.labelpad +p173 +F5.0 +sVpgf.debug +p174 +I00 +sVytick.major.pad +p175 +F4.0 +sVlegend.borderpad +p176 +F0.4 +sVboxplot.showfliers +p177 +I01 +sVlines.antialiased +p178 +I01 +sVboxplot.whiskerprops.linewidth +p179 +F1.0 +sVfigure.subplot.bottom +p180 +F0.1 +sVtext.latex.preamble +p181 +(lp182 +sVboxplot.flierprops.markersize +p183 +F6.0 +sVaxes.formatter.useoffset +p184 +I01 +sVfont.sans-serif +p185 +(lp186 +VBitstream Vera Sans +p187 +aVDejaVu Sans +p188 +aVLucida Grande +p189 +aVVerdana +p190 +aVGeneva +p191 +aVLucid +p192 +aVArial +p193 +aVHelvetica +p194 +aVAvant Garde +p195 +aVsans-serif +p196 +asVboxplot.flierprops.linestyle +p197 +Vnone +p198 +sVsavefig.format +p199 +g2 +sVkeymap.quit +p200 +(lp201 +Vctrl+w +p202 +aVcmd+w +p203 +asVlegend.borderaxespad +p204 +F0.5 +sVmathtext.sf +p205 +Vsans\u005c-serif +p206 +sVboxplot.whiskers +p207 +F1.5 +sVaxes.hold +p208 +I01 +sVverbose.level +p209 +Vsilent +p210 +sVaxes.titleweight +p211 +g79 +sVerrorbar.capsize +p212 +F3.0 +sVkeymap.yscale +p213 +(lp214 +Vl +p215 +asVxtick.minor.visible +p216 +I00 +sVytick.labelsize +p217 +g91 +sVimage.composite_image +p218 +I01 +sVboxplot.showbox +p219 +I01 +sVaxes.spines.right +p220 +I01 +sVmathtext.cal +p221 +Vcursive +p222 +sVps.useafm +p223 +I00 +sVpgf.texsystem +p224 +Vxelatex +p225 +sVboxplot.capprops.color +p226 +g39 +sVcontour.corner_mask +p227 +I01 +sVmathtext.bf +p228 +Vserif:bold +p229 +sVaxes.facecolor +p230 +g74 +sVytick.direction +p231 +g26 +sVgrid.alpha +p232 +F1.0 +sVanimation.writer +p233 +Vffmpeg +p234 +sVpath.snap +p235 +I01 +sVaxes.axisbelow +p236 +I00 +sVanimation.bitrate +p237 +I-1 +sVfigure.dpi +p238 +F80.0 +sVtext.usetex +p239 +I00 +sVsavefig.transparent +p240 +I00 +sVanimation.convert_path +p241 +Vconvert +p242 +sVanimation.ffmpeg_args +p243 +(lp244 +sVlines.solid_joinstyle +p245 +Vround +p246 +sVfont.monospace +p247 +(lp248 +VBitstream Vera Sans Mono +p249 +aVDejaVu Sans Mono +p250 +aVAndale Mono +p251 +aVNimbus Mono L +p252 +aVCourier New +p253 +aVCourier +p254 +aVFixed +p255 +aVTerminal +p256 +ag119 +asVfigure.subplot.wspace +p257 +F0.2 +sVsavefig.edgecolor +p258 +g74 +sVimage.cmap +p259 +Vjet +p260 +sVlines.marker +p261 +VNone +p262 +sVboxplot.patchartist +p263 +I00 +sVbackend.qt4 +p264 +VPyQt4 +p265 +sVboxplot.meanline +p266 +I00 +sVaxes.spines.left +p267 +I01 +sVboxplot.whiskerprops.linestyle +p268 +V-- +p269 +sVanimation.avconv_path +p270 +Vavconv +p271 +sVaxes.ymargin +p272 +F0.0 +sVboxplot.medianprops.linestyle +p273 +g129 +sVpatch.facecolor +p274 +g19 +sVkeymap.zoom +p275 +(lp276 +Vo +p277 +asVlegend.handletextpad +p278 +F0.8 +sVlines.linewidth +p279 +F1.0 +sVsavefig.dpi +p280 +F100.0 +sVverbose.fileo +p281 +Vsys.stdout +p282 +sVsvg.image_noscale +p283 +I00 +sVdocstring.hardcopy +p284 +I00 +sVfigure.max_open_warning +p285 +I20 +sVxtick.major.size +p286 +F4.0 +sVlegend.edgecolor +p287 +g48 +sVpolaraxes.grid +p288 +I01 +sVpdf.compression +p289 +I6 +sVlegend.frameon +p290 +I01 +sVboxplot.showcaps +p291 +I01 +sVaxes.prop_cycle +p292 +ccopy_reg +_reconstructor +p293 +(ccycler +Cycler +p294 +c__builtin__ +object +p295 +Ntp296 +Rp297 +(dp298 +S'_right' +p299 +NsS'_keys' +p300 +c__builtin__ +set +p301 +((lp302 +Vcolor +p303 +atp304 +Rp305 +sS'_left' +p306 +(lp307 +(dp308 +g303 +g19 +sa(dp309 +g303 +Vg +p310 +sa(dp311 +g303 +g125 +sa(dp312 +g303 +Vc +p313 +sa(dp314 +g303 +Vm +p315 +sa(dp316 +g303 +Vy +p317 +sa(dp318 +g303 +g39 +sasS'_op' +p319 +NsbsVxtick.minor.width +p320 +F0.5 +sVwebagg.port +p321 +I8988 +sVanimation.ffmpeg_path +p322 +g234 +sVytick.minor.visible +p323 +I00 +sVimage.interpolation +p324 +Vbilinear +p325 +sVaxes.grid.which +p326 +Vmajor +p327 +sVanimation.avconv_args +p328 +(lp329 +sVaxes3d.grid +p330 +I01 +sVlegend.scatterpoints +p331 +I3 +sVxtick.minor.size +p332 +F2.0 +sVboxplot.showmeans +p333 +I00 +sVps.fonttype +p334 +I3 +sVfont.cursive +p335 +(lp336 +VApple Chancery +p337 +aVTextile +p338 +aVZapf Chancery +p339 +aVSand +p340 +aVScript MT +p341 +aVFelipa +p342 +ag222 +asVlegend.shadow +p343 +I00 +sVmathtext.it +p344 +Vserif:italic +p345 +sVkeymap.save +p346 +(lp347 +Vs +p348 +aVctrl+s +p349 +asVfont.variant +p350 +g79 +sVboxplot.boxprops.linewidth +p351 +F1.0 +sVbackend.qt5 +p352 +VPyQt5 +p353 +sVanimation.html +p354 +g198 +sVps.distiller.res +p355 +I6000 +sVaxes.labelweight +p356 +g79 +sVpdf.fonttype +p357 +I3 +sVytick.minor.pad +p358 +F4.0 +sVlines.dash_capstyle +p359 +Vbutt +p360 +sVlines.color +p361 +g19 +sVfigure.subplot.top +p362 +F0.9 +sVpgf.preamble +p363 +(lp364 +sVboxplot.vertical +p365 +I01 +sVkeymap.forward +p366 +(lp367 +Vright +p368 +aVv +p369 +asVlegend.fancybox +p370 +I00 +sVboxplot.notch +p371 +I00 +sVtext.color +p372 +g39 +sVinteractive +p373 +I00 +sVsavefig.orientation +p374 +Vportrait +p375 +sVfigure.titleweight +p376 +g79 +sVmarkers.fillstyle +p377 +Vfull +p378 +sVytick.major.size +p379 +F4.0 +sVboxplot.flierprops.marker +p380 +V+ +p381 +sVboxplot.medianprops.color +p382 +g125 +sVgrid.color +p383 +g39 +sVtimezone +p384 +VUTC +p385 +sVpgf.rcfonts +p386 +I01 +sVwebagg.port_retries +p387 +I50 +sVlines.dash_joinstyle +p388 +g246 +sVtext.latex.unicode +p389 +I00 +sVlegend.handleheight +p390 +F0.7 +sVanimation.codec +p391 +Vmpeg4 +p392 +sVlegend.numpoints +p393 +I2 +sVlegend.handlelength +p394 +F2.0 +sVkeymap.grid +p395 +(lp396 +g310 +asVfont.family +p397 +(lp398 +g196 +asVxtick.major.width +p399 +F0.5 +sVaxes.labelsize +p400 +g91 +sVpatch.linewidth +p401 +F1.0 +sVboxplot.meanprops.color +p402 +g125 +sVmathtext.default +p403 +Vit +p404 +sVlines.linestyle +p405 +g129 +sVlegend.columnspacing +p406 +F2.0 +sVwebagg.open_in_browser +p407 +I01 +sVtext.latex.preview +p408 +I00 +sVfont.weight +p409 +g79 +sVimage.resample +p410 +I00 +sVagg.path.chunksize +p411 +I0 +sVpath.simplify_threshold +p412 +F0.1111111111111111 +sVps.papersize +p413 +Vletter +p414 +sVkeymap.back +p415 +(lp416 +Vleft +p417 +ag313 +aVbackspace +p418 +as. \ No newline at end of file diff --git a/tests/readme.rst b/tests/readme.rst new file mode 100644 index 000000000..3e193f433 --- /dev/null +++ b/tests/readme.rst @@ -0,0 +1,44 @@ +================== +OpenMOC Test Suite +================== + +The purpose of this test suite is to ensure that that all user input options +can be used successfully without breaking the code. The test suite is based on +regression or integrated testing where different types of input files are +configured and the full OpenMOC code is executed. Results from simulations +are compared with expected results. The test suite is comprised of many tests +which reside in sub-directories in the tests directory. + +The test suite is designed to integrate with cmake using ctest_. To run the +full test suite run: + +.. code-block:: sh + + python run_tests.py + +A subset of build configurations and/or tests can be run. To see how to use +the script run: + +.. code-block:: sh + + python run_tests.py --help + +As an example, say we want to run all tests with that have "adjoint" and +"pwr" in their name. Also, we wish to split the tests across 4 processors. +We can run: + +.. code-block:: sh + + python run_tests.py -j 4 -R "adjoint|pwr" + +Note that standard regular expression syntax is used for selecting build +configurations and tests. To print out a list of build configurations, we +can run: + +.. code-block:: sh + + python run_tests.py -l + +Note that the test suite requires h5py, matplotlib (>=1.5) and Pandas (>=0.13). + +.. _ctest: http://www.cmake.org/cmake/help/v2.8.12/ctest.html diff --git a/tests/run_tests.py b/tests/run_tests.py new file mode 100755 index 000000000..2fd7adb26 --- /dev/null +++ b/tests/run_tests.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import sys +import shutil +import re +import glob +import subprocess +from collections import OrderedDict +from optparse import OptionParser + +# Command line parsing +parser = OptionParser() +parser.add_option('-j', '--parallel', dest='n_procs', default='1', + help="Number of parallel jobs.") +parser.add_option('-R', '--tests-regex', dest='regex_tests', + help="Run tests matching regular expression. " + "Test names are the directories present in tests folder. " + "This uses standard regex syntax to select tests.") +parser.add_option('-C', '--build-config', dest='build_config', + help="Build configurations matching regular expression. " + "Specific build configurations can be printed out with " + "optional argument -p, --print. This uses standard " + "regex syntax to select build configurations.") +parser.add_option('-l', '--list', action="store_true", + dest="list_build_configs", default=False, + help="List out build configurations.") +(options, args) = parser.parse_args() + +# Default build options +FP = 'double' + +# Define test data structure +tests = OrderedDict() + +class Test(object): + + # A class attribute to cache the setup install commands from + # previous Tests, if any (this helps eliminate redundant builds) + _setup_cmd = [] + + def __init__(self, name, cc='gcc', num_threads=1, debug=False): + self.name = name + self.cc = cc + self.fp = FP + self.num_threads = num_threads + self.debug = debug + self.success = True + self.msg = None + + def run_setup_install(self): + """Install OpenMOC with distutils""" + + setup_cmd = [sys.executable, 'setup.py', 'install'] + setup_cmd += ['--install-purelib=tests/openmoc'] + setup_cmd += ['--cc={0}'.format(self.cc), '--fp={0}'.format(self.fp)] + if self.debug: + setup_cmd += ['--debug-mode'] + + # Run setup.py if it was not run for the previous Test + if setup_cmd != Test._setup_cmd: + rc = subprocess.call(setup_cmd) + rc = subprocess.call(setup_cmd) + + # Check for error code + if rc != 0: + self.success = False + self.msg = 'Failed on setup.py' + # Cache the setup install command for the next Test + else: + Test._setup_cmd = setup_cmd + + def run_cmake(self): + """Run CMake to create CTest script""" + + cmake_cmd = ['cmake', '-H..', '-Bbuild'] + cmake_cmd += ['-DPYTHON_EXECUTABLE=' + sys.executable] + + # Run CMake + rc = subprocess.call(cmake_cmd) + + # Check for error code + if rc != 0: + self.success = False + self.msg = 'Failed on cmake.' + + def run_ctests(self): + """Run CTest on all tests""" + if not self.success: + return + + os.environ['OMP_NUM_THREADS'] = str(self.num_threads) + + # Default CTest string + ctest_cmd = ['ctest'] + + # Check for parallel + if options.n_procs: + ctest_cmd += ['-j', str(options.n_procs)] + + # Check for subset of tests + if options.regex_tests: + ctest_cmd += ['-R', str(options.regex_tests)] + + # Run CTest + rc = subprocess.call(ctest_cmd) + + # Check for error code + if rc != 0: + self.success = False + self.msg = 'Failed on testing.' + + +# Simple function to add a test to the global tests dictionary +def add_test(name, cc='gcc', num_threads=1, debug=False, ): + tests.update({name: Test(name, cc, num_threads, debug)}) + +# List of all tests that may be run. User can add -C to command line to specify +# a subset of these configurations +add_test('normal-gcc', cc='gcc', num_threads=1) +add_test('normal-openmp-gcc', cc='gcc', num_threads=4) +#add_test('normal-icpc', cc='icpc', num_threads=1) +#add_test('normal-openmp-icpc', cc='icpc', num_threads=4) +#add_test('normal-clang', cc='clang', num_threads=1) +#add_test('normal-openmp-clang', cc='clang', num_threads=4) + +# Check to see if we should just print build configuration information to user +if options.list_build_configs: + for key in tests: + print('Configuration Name: {0}'.format(key)) + exit() + +# Delete items of dictionary that don't match regular expression +if options.build_config is not None: + for key in tests: + if not re.search(options.build_config, key): + del tests[key] + +# Check if tests empty +if len(list(tests.keys())) == 0: + print('No tests to run.') + exit() + +# Removes all binary track and output files from tests +shutil.rmtree('build', ignore_errors=True) +subprocess.call(['./cleanup']) + +# Run each Test in sequence +for key in iter(tests): + test = tests[key] + + # Print header for this test + print('-'*(len(key) + 6)) + print(key + ' tests') + print('-'*(len(key) + 6)) + sys.stdout.flush() + + # Run CMake to setup CTest + test.run_cmake() + + # Go into main OpenMOC directory + os.chdir('..') + + # Run setup.py to build and install OpenMOC + test.run_setup_install() + + # Go into build directory + os.chdir('tests/build') + + # Run CTest + test.run_ctests() + + # Leave build directory + os.chdir('..') + + # Copy over log file + logfile = glob.glob('build/Testing/Temporary/LastTest.log') + if len(logfile) > 0: + logfilename = os.path.split(logfile[0])[1] + logfilename = os.path.splitext(logfilename)[0] + logfilename = logfilename + '_{0}.log'.format(test.name) + shutil.copy(logfile[0], logfilename) + +# Clear build directory and remove binary and hdf5 files +shutil.rmtree('build', ignore_errors=True) +shutil.rmtree('openmoc', ignore_errors=True) +subprocess.call(['./cleanup']) + +# Print out summary of results +print('\n' + '='*54) +print('Summary of Compilation Option Testing:\n') + +if sys.stdout.isatty(): + OK = '\033[92m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' +else: + OK = '' + FAIL = '' + ENDC = '' + BOLD = '' + +return_code = 0 + +for test in tests: + print(test + '.'*(50 - len(test)), end='') + if tests[test].success: + print(BOLD + OK + '[OK]' + ENDC) + else: + print(BOLD + FAIL + '[FAILED]' + ENDC) + print(' '*len(test)+tests[test].msg) + return_code = 1 + +sys.exit(return_code) diff --git a/tests/test_1d_gradient/results_true.dat b/tests/test_1d_gradient/results_true.dat new file mode 100644 index 000000000..9699ea9ba --- /dev/null +++ b/tests/test_1d_gradient/results_true.dat @@ -0,0 +1,203 @@ +# Iterations: 47 +keff: 1.68880E-01 +fluxes: +1.970264E+00 +4.070857E-01 +2.320617E+00 +5.841393E-01 +1.937336E+00 +4.023681E-01 +2.613272E+00 +7.191125E-01 +2.287181E+00 +5.773671E-01 +1.857945E+00 +3.885967E-01 +2.815637E+00 +8.088949E-01 +2.559246E+00 +7.048947E-01 +2.192895E+00 +5.563985E-01 +1.730238E+00 +3.611362E-01 +2.914094E+00 +8.521411E-01 +2.756250E+00 +7.914073E-01 +2.462952E+00 +6.785129E-01 +2.047585E+00 +5.208681E-01 +1.607878E+00 +3.314264E-01 +2.914090E+00 +8.521394E-01 +2.865029E+00 +8.368014E-01 +2.653274E+00 +7.612388E-01 +2.318374E+00 +6.399870E-01 +1.872152E+00 +4.748418E-01 +1.472510E+00 +2.992648E-01 +2.815625E+00 +8.088899E-01 +2.865025E+00 +8.367998E-01 +2.759296E+00 +8.049303E-01 +2.510181E+00 +7.193314E-01 +2.128065E+00 +5.883245E-01 +1.709541E+00 +4.282853E-01 +1.339415E+00 +2.649564E-01 +2.613255E+00 +7.191051E-01 +2.756240E+00 +7.914030E-01 +2.759294E+00 +8.049292E-01 +2.597919E+00 +7.577657E-01 +2.305692E+00 +6.625494E-01 +1.893582E+00 +5.233418E-01 +1.516399E+00 +3.750882E-01 +1.165306E+00 +2.216112E-01 +2.320599E+00 +5.841313E-01 +2.559233E+00 +7.048887E-01 +2.653268E+00 +7.612358E-01 +2.597918E+00 +7.577652E-01 +2.389997E+00 +6.973591E-01 +2.042549E+00 +5.896699E-01 +1.648103E+00 +4.520527E-01 +1.297982E+00 +3.127541E-01 +9.831192E-01 +1.710125E-01 +1.970249E+00 +4.070794E-01 +2.287167E+00 +5.773607E-01 +2.462943E+00 +6.785088E-01 +2.510179E+00 +7.193298E-01 +2.389998E+00 +6.973589E-01 +2.133573E+00 +6.238477E-01 +1.752310E+00 +5.048281E-01 +1.396987E+00 +3.749057E-01 +1.067703E+00 +2.412634E-01 +8.311296E-01 +1.190277E-01 +1.937323E+00 +4.023629E-01 +2.192885E+00 +5.563942E-01 +2.318371E+00 +6.399847E-01 +2.305694E+00 +6.625491E-01 +2.133574E+00 +6.238479E-01 +1.821383E+00 +5.349789E-01 +1.452409E+00 +4.132539E-01 +1.126453E+00 +2.875368E-01 +8.347995E-01 +1.579923E-01 +1.857935E+00 +3.885931E-01 +2.047581E+00 +5.208656E-01 +2.128066E+00 +5.883238E-01 +2.042552E+00 +5.896702E-01 +1.821385E+00 +5.349792E-01 +1.476698E+00 +4.321341E-01 +1.146736E+00 +3.134154E-01 +8.466629E-01 +1.873492E-01 +1.730232E+00 +3.611342E-01 +1.872152E+00 +4.748409E-01 +1.893586E+00 +5.233422E-01 +1.752314E+00 +5.048289E-01 +1.476699E+00 +4.321344E-01 +1.136013E+00 +3.220269E-01 +8.397196E-01 +2.029724E-01 +1.607876E+00 +3.314254E-01 +1.709545E+00 +4.282854E-01 +1.648108E+00 +4.520537E-01 +1.452413E+00 +4.132547E-01 +1.136013E+00 +3.220271E-01 +8.274396E-01 +2.087229E-01 +1.472511E+00 +2.992647E-01 +1.516405E+00 +3.750891E-01 +1.396992E+00 +3.749067E-01 +1.146738E+00 +3.134160E-01 +8.274400E-01 +2.087230E-01 +1.339418E+00 +2.649568E-01 +1.297987E+00 +3.127551E-01 +1.126457E+00 +2.875376E-01 +8.397207E-01 +2.029727E-01 +1.165311E+00 +2.216119E-01 +1.067707E+00 +2.412643E-01 +8.466651E-01 +1.873497E-01 +9.831237E-01 +1.710132E-01 +8.348025E-01 +1.579929E-01 +8.311332E-01 +1.190282E-01 diff --git a/tests/test_1d_gradient/test_1d_gradient.py b/tests/test_1d_gradient/test_1d_gradient.py new file mode 100644 index 000000000..d62fc58c7 --- /dev/null +++ b/tests/test_1d_gradient/test_1d_gradient.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput +import openmoc + + +class OneDGradientTestHarness(TestHarness): + """An eigenvalue calculation in a cube with vacuum BCs in x + and reflective BCs in y with 2-group cross section data.""" + + def _create_geometry(self): + """Put VACUUM boundary conditions on left and right boundaries.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Get the root Cell + cells = self.input_set.geometry.getAllCells() + for cell_id in cells: + cell = cells[cell_id] + if cell.getName() == 'root cell': + root_cell = cell + + # Apply VACUUM BCs on the min/max XPlane surfaces + surfaces = root_cell.getSurfaces() + for surface_id in surfaces: + surface = surfaces[surface_id]._surface + if 'x' in surface.getName(): + surface.setBoundaryType(openmoc.VACUUM) + + def __init__(self): + super(OneDGradientTestHarness, self).__init__() + self.input_set = HomInfMedInput() + + +if __name__ == '__main__': + harness = OneDGradientTestHarness() + harness.main() diff --git a/tests/test_2d_gradient/results_true.dat b/tests/test_2d_gradient/results_true.dat new file mode 100644 index 000000000..7091b9d65 --- /dev/null +++ b/tests/test_2d_gradient/results_true.dat @@ -0,0 +1,203 @@ +# Iterations: 57 +keff: 3.39810E-01 +fluxes: +2.245010E+00 +8.949276E-01 +2.197237E+00 +8.789047E-01 +2.197237E+00 +8.789047E-01 +2.105945E+00 +8.461837E-01 +2.152254E+00 +8.621924E-01 +2.105945E+00 +8.461837E-01 +1.979197E+00 +7.983328E-01 +2.069794E+00 +8.315058E-01 +2.069794E+00 +8.315058E-01 +1.979197E+00 +7.983328E-01 +1.830184E+00 +7.384469E-01 +1.958543E+00 +7.875516E-01 +2.003812E+00 +8.037664E-01 +1.958543E+00 +7.875516E-01 +1.830184E+00 +7.384469E-01 +1.665543E+00 +6.673705E-01 +1.814155E+00 +7.288619E-01 +1.902641E+00 +7.626773E-01 +1.902641E+00 +7.626773E-01 +1.814155E+00 +7.288619E-01 +1.665543E+00 +6.673705E-01 +1.481061E+00 +5.832801E-01 +1.641201E+00 +6.563378E-01 +1.768153E+00 +7.068410E-01 +1.811063E+00 +7.232954E-01 +1.768153E+00 +7.068410E-01 +1.641201E+00 +6.563378E-01 +1.481061E+00 +5.832801E-01 +1.279126E+00 +4.847528E-01 +1.455331E+00 +5.716616E-01 +1.601320E+00 +6.354170E-01 +1.685970E+00 +6.700778E-01 +1.685970E+00 +6.700778E-01 +1.601320E+00 +6.354170E-01 +1.455331E+00 +5.716616E-01 +1.279126E+00 +4.847528E-01 +1.072660E+00 +3.744664E-01 +1.267104E+00 +4.780535E-01 +1.424060E+00 +5.545353E-01 +1.551443E+00 +6.075487E-01 +1.592648E+00 +6.245863E-01 +1.551443E+00 +6.075487E-01 +1.424060E+00 +5.545353E-01 +1.267104E+00 +4.780535E-01 +1.072660E+00 +3.744664E-01 +8.748606E-01 +2.535352E-01 +1.074527E+00 +3.731881E-01 +1.244208E+00 +4.651441E-01 +1.389220E+00 +5.325404E-01 +1.471793E+00 +5.689847E-01 +1.471793E+00 +5.689847E-01 +1.389220E+00 +5.325404E-01 +1.244208E+00 +4.651441E-01 +1.074527E+00 +3.731881E-01 +8.748606E-01 +2.535352E-01 +8.753770E-01 +2.523569E-01 +1.058929E+00 +3.645469E-01 +1.210168E+00 +4.459757E-01 +1.335798E+00 +5.022074E-01 +1.375089E+00 +5.202936E-01 +1.335798E+00 +5.022074E-01 +1.210168E+00 +4.459757E-01 +1.058929E+00 +3.645469E-01 +8.753770E-01 +2.523569E-01 +8.666278E-01 +2.473364E-01 +1.024742E+00 +3.474233E-01 +1.164602E+00 +4.196180E-01 +1.242919E+00 +4.584078E-01 +1.242919E+00 +4.584078E-01 +1.164602E+00 +4.196180E-01 +1.024742E+00 +3.474233E-01 +8.666278E-01 +2.473364E-01 +8.420887E-01 +2.346440E-01 +9.840695E-01 +3.243338E-01 +1.105481E+00 +3.852158E-01 +1.142213E+00 +4.048932E-01 +1.105481E+00 +3.852158E-01 +9.840695E-01 +3.243338E-01 +8.420887E-01 +2.346440E-01 +8.241600E-01 +2.204736E-01 +9.598525E-01 +3.014878E-01 +1.035523E+00 +3.444901E-01 +1.035523E+00 +3.444901E-01 +9.598525E-01 +3.014878E-01 +8.241600E-01 +2.204736E-01 +7.995149E-01 +2.045729E-01 +9.179353E-01 +2.738508E-01 +9.536305E-01 +2.965792E-01 +9.179353E-01 +2.738508E-01 +7.995149E-01 +2.045729E-01 +7.805847E-01 +1.869829E-01 +8.527712E-01 +2.372502E-01 +8.527712E-01 +2.372502E-01 +7.805847E-01 +1.869829E-01 +7.383966E-01 +1.625774E-01 +7.721480E-01 +1.905972E-01 +7.383966E-01 +1.625774E-01 +6.841067E-01 +1.306260E-01 +6.841067E-01 +1.306260E-01 +6.416652E-01 +9.473353E-02 diff --git a/tests/test_2d_gradient/test_2d_gradient.py b/tests/test_2d_gradient/test_2d_gradient.py new file mode 100644 index 000000000..db8273c62 --- /dev/null +++ b/tests/test_2d_gradient/test_2d_gradient.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput +import openmoc + + +class TwoDGradientTestHarness(TestHarness): + """An eigenvalue calculation in a cube with vacuum BCs along xmin and + ymax and reflective BCs elsewhere with 2-group cross section data.""" + + def _create_geometry(self): + """Put VACUUM boundary conditions on left and right boundaries.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Get the root Cell + cells = self.input_set.geometry.getAllCells() + for cell_id in cells: + cell = cells[cell_id] + if cell.getName() == 'root cell': + root_cell = cell + + # Apply VACUUM BCs on the xmin and ymax surfaces + surfaces = root_cell.getSurfaces() + for surface_id in surfaces: + surface = surfaces[surface_id]._surface + if surface.getName() == 'xmin': + surface.setBoundaryType(openmoc.VACUUM) + if surface.getName() == 'ymax': + surface.setBoundaryType(openmoc.VACUUM) + + def __init__(self): + super(TwoDGradientTestHarness, self).__init__() + self.input_set = HomInfMedInput() + + +if __name__ == '__main__': + harness = TwoDGradientTestHarness() + harness.main() diff --git a/tests/test_adjoint_hom_inf_medium/results_true.dat b/tests/test_adjoint_hom_inf_medium/results_true.dat new file mode 100644 index 000000000..d1a8f970c --- /dev/null +++ b/tests/test_adjoint_hom_inf_medium/results_true.dat @@ -0,0 +1,203 @@ +# Iterations: 120 +keff: 1.72293E+00 +fluxes: +4.781101E-01 +4.901007E-01 +4.781108E-01 +4.901021E-01 +4.781108E-01 +4.901021E-01 +4.781116E-01 +4.901034E-01 +4.781111E-01 +4.901031E-01 +4.781116E-01 +4.901034E-01 +4.781124E-01 +4.901045E-01 +4.781118E-01 +4.901041E-01 +4.781118E-01 +4.901041E-01 +4.781124E-01 +4.901045E-01 +4.781131E-01 +4.901052E-01 +4.781125E-01 +4.901051E-01 +4.781121E-01 +4.901049E-01 +4.781125E-01 +4.901051E-01 +4.781131E-01 +4.901052E-01 +4.781138E-01 +4.901058E-01 +4.781133E-01 +4.901059E-01 +4.781127E-01 +4.901056E-01 +4.781127E-01 +4.901056E-01 +4.781133E-01 +4.901059E-01 +4.781138E-01 +4.901058E-01 +4.781144E-01 +4.901063E-01 +4.781140E-01 +4.901065E-01 +4.781134E-01 +4.901063E-01 +4.781129E-01 +4.901062E-01 +4.781134E-01 +4.901063E-01 +4.781140E-01 +4.901065E-01 +4.781144E-01 +4.901063E-01 +4.781151E-01 +4.901067E-01 +4.781146E-01 +4.901070E-01 +4.781141E-01 +4.901069E-01 +4.781135E-01 +4.901067E-01 +4.781135E-01 +4.901067E-01 +4.781141E-01 +4.901069E-01 +4.781146E-01 +4.901070E-01 +4.781151E-01 +4.901067E-01 +4.781157E-01 +4.901070E-01 +4.781152E-01 +4.901073E-01 +4.781147E-01 +4.901073E-01 +4.781141E-01 +4.901071E-01 +4.781136E-01 +4.901070E-01 +4.781141E-01 +4.901071E-01 +4.781147E-01 +4.901073E-01 +4.781152E-01 +4.901073E-01 +4.781157E-01 +4.901070E-01 +4.781160E-01 +4.901070E-01 +4.781156E-01 +4.901074E-01 +4.781151E-01 +4.901075E-01 +4.781145E-01 +4.901073E-01 +4.781139E-01 +4.901071E-01 +4.781139E-01 +4.901071E-01 +4.781145E-01 +4.901073E-01 +4.781151E-01 +4.901075E-01 +4.781156E-01 +4.901074E-01 +4.781160E-01 +4.901070E-01 +4.781157E-01 +4.901070E-01 +4.781152E-01 +4.901073E-01 +4.781147E-01 +4.901073E-01 +4.781141E-01 +4.901071E-01 +4.781136E-01 +4.901070E-01 +4.781141E-01 +4.901071E-01 +4.781147E-01 +4.901073E-01 +4.781152E-01 +4.901073E-01 +4.781157E-01 +4.901070E-01 +4.781151E-01 +4.901067E-01 +4.781146E-01 +4.901070E-01 +4.781141E-01 +4.901069E-01 +4.781135E-01 +4.901067E-01 +4.781135E-01 +4.901067E-01 +4.781141E-01 +4.901069E-01 +4.781146E-01 +4.901070E-01 +4.781151E-01 +4.901067E-01 +4.781144E-01 +4.901063E-01 +4.781140E-01 +4.901065E-01 +4.781134E-01 +4.901063E-01 +4.781129E-01 +4.901062E-01 +4.781134E-01 +4.901063E-01 +4.781140E-01 +4.901065E-01 +4.781144E-01 +4.901063E-01 +4.781138E-01 +4.901058E-01 +4.781133E-01 +4.901059E-01 +4.781127E-01 +4.901056E-01 +4.781127E-01 +4.901056E-01 +4.781133E-01 +4.901059E-01 +4.781138E-01 +4.901058E-01 +4.781131E-01 +4.901052E-01 +4.781125E-01 +4.901051E-01 +4.781121E-01 +4.901049E-01 +4.781125E-01 +4.901051E-01 +4.781131E-01 +4.901052E-01 +4.781124E-01 +4.901045E-01 +4.781118E-01 +4.901041E-01 +4.781118E-01 +4.901041E-01 +4.781124E-01 +4.901045E-01 +4.781116E-01 +4.901034E-01 +4.781111E-01 +4.901031E-01 +4.781116E-01 +4.901034E-01 +4.781108E-01 +4.901021E-01 +4.781108E-01 +4.901021E-01 +4.781101E-01 +4.901007E-01 diff --git a/tests/test_adjoint_hom_inf_medium/test_adjoint_hom_inf_medium.py b/tests/test_adjoint_hom_inf_medium/test_adjoint_hom_inf_medium.py new file mode 100644 index 000000000..302c50f15 --- /dev/null +++ b/tests/test_adjoint_hom_inf_medium/test_adjoint_hom_inf_medium.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput +import openmoc + + +class HomInfMedAdjointTestHarness(TestHarness): + """An adjoint eigenvalue calculation in a reflected cube with 2-group + cross section data.""" + + def __init__(self): + super(HomInfMedAdjointTestHarness, self).__init__() + self.input_set = HomInfMedInput() + self.calculation_mode = openmoc.ADJOINT + + +if __name__ == '__main__': + harness = HomInfMedAdjointTestHarness() + harness.main() diff --git a/tests/test_adjoint_pin_cell/results_true.dat b/tests/test_adjoint_pin_cell/results_true.dat new file mode 100644 index 000000000..834e43ddf --- /dev/null +++ b/tests/test_adjoint_pin_cell/results_true.dat @@ -0,0 +1,17 @@ +# Iterations: 223 +keff: 1.04645E+00 +fluxes: +3.207360E-01 +3.157962E-01 +3.168678E-01 +3.201595E-01 +3.286809E-01 +3.305842E-01 +3.294580E-01 +3.254698E-01 +3.151990E-01 +3.129689E-01 +3.034176E-01 +3.324840E-01 +3.570337E-01 +3.934150E-01 diff --git a/tests/test_adjoint_pin_cell/test_adjoint_pin_cell.py b/tests/test_adjoint_pin_cell/test_adjoint_pin_cell.py new file mode 100644 index 000000000..280013512 --- /dev/null +++ b/tests/test_adjoint_pin_cell/test_adjoint_pin_cell.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput +import openmoc + + +class PinCellAdjointTestHarness(TestHarness): + """An adjoint eigenvalue calculation in a pin cell with 7-group C5G7 + cross section data.""" + + def __init__(self): + super(PinCellAdjointTestHarness, self).__init__() + self.input_set = PinCellInput() + self.calculation_mode = openmoc.ADJOINT + + +if __name__ == '__main__': + harness = PinCellAdjointTestHarness() + harness.main() diff --git a/tests/test_adjoint_simple_lattice/results_true.dat b/tests/test_adjoint_simple_lattice/results_true.dat new file mode 100644 index 000000000..0d56f2f8b --- /dev/null +++ b/tests/test_adjoint_simple_lattice/results_true.dat @@ -0,0 +1 @@ +1d1e2b6e8ab195d7be5f321baf40cb344b06cecf2f12d7ec94d76959bf3227f9ee4c34b2970fb588f14c107997ffa34a54f1e6b8e872fd21be79a8ee2bdf4547 \ No newline at end of file diff --git a/tests/test_adjoint_simple_lattice/test_adjoint_simple_lattice.py b/tests/test_adjoint_simple_lattice/test_adjoint_simple_lattice.py new file mode 100644 index 000000000..643761801 --- /dev/null +++ b/tests/test_adjoint_simple_lattice/test_adjoint_simple_lattice.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import SimpleLatticeInput +import openmoc + + +class SimpleLatticeAdjointTestHarness(TestHarness): + """An adjoint eigenvalue calculation for a 4x4 lattice with 7-group C5G7 + cross section data.""" + + def __init__(self): + super(SimpleLatticeAdjointTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + self.calculation_mode = openmoc.ADJOINT + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=True): + """Digest info in the solver and return hash as a string.""" + return super(SimpleLatticeAdjointTestHarness, self)._get_results( + num_iters=num_iters, keff=keff, fluxes=fluxes, + num_fsrs=num_fsrs, num_tracks=num_tracks, + num_segments=num_segments, hash_output=hash_output) + + +if __name__ == '__main__': + harness = SimpleLatticeAdjointTestHarness() + harness.main() diff --git a/tests/test_cmfd_pwr_assembly/results_true.dat b/tests/test_cmfd_pwr_assembly/results_true.dat new file mode 100644 index 000000000..6ce97d444 --- /dev/null +++ b/tests/test_cmfd_pwr_assembly/results_true.dat @@ -0,0 +1 @@ +84f6086c811192656f71363e1a9a79ae55e884607fdb514348d57519c48afa76a9967a141fae99fb551cc5e7dd5b470fe3543fba7e78fb31fbbd3cd045f62a06 \ No newline at end of file diff --git a/tests/test_cmfd_pwr_assembly/test_cmfd_pwr_assembly.py b/tests/test_cmfd_pwr_assembly/test_cmfd_pwr_assembly.py new file mode 100644 index 000000000..b3c881cc8 --- /dev/null +++ b/tests/test_cmfd_pwr_assembly/test_cmfd_pwr_assembly.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PwrAssemblyInput +import openmoc + + +class CmfdPwrAssemblyTestHarness(TestHarness): + """An eigenvalue calculation for a 17x17 lattice with 7-group C5G7 + cross section data.""" + + def __init__(self): + super(CmfdPwrAssemblyTestHarness, self).__init__() + self.input_set = PwrAssemblyInput() + + def _create_geometry(self): + """Initialize CMFD and add it to the Geometry.""" + + super(CmfdPwrAssemblyTestHarness, self)._create_geometry() + + # Initialize CMFD + cmfd = openmoc.Cmfd() + cmfd.setSORRelaxationFactor(1.5) + cmfd.setLatticeStructure(17,17) + cmfd.setGroupStructure([1,4,8]) + cmfd.setKNearest(3) + + # Add CMFD to the Geometry + self.input_set.geometry.setCmfd(cmfd) + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=True): + """Digest info in the solver and return hash as a string.""" + return super(CmfdPwrAssemblyTestHarness, self)._get_results( + num_iters=num_iters, keff=keff, fluxes=fluxes, + num_fsrs=num_fsrs, num_tracks=num_tracks, + num_segments=num_segments, hash_output=hash_output) + + +if __name__ == '__main__': + harness = CmfdPwrAssemblyTestHarness() + harness.main() diff --git a/tests/test_compute_flux/results_true.dat b/tests/test_compute_flux/results_true.dat new file mode 100644 index 000000000..8874eddb6 --- /dev/null +++ b/tests/test_compute_flux/results_true.dat @@ -0,0 +1,702 @@ +# Iterations: 3 +fluxes: +4.471999E-02 +1.055432E-02 +3.276680E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.422951E-02 +3.531230E-03 +1.134771E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.422951E-02 +3.531230E-03 +1.134771E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.817150E-02 +1.259973E-02 +4.195402E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.584176E-02 +4.360615E-03 +1.503336E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.584176E-02 +4.360615E-03 +1.503336E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.374567E-02 +1.561519E-02 +5.579225E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.744514E-02 +5.343896E-03 +1.977149E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.744514E-02 +5.343896E-03 +1.977149E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.842908E-02 +1.894967E-02 +7.268094E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.902136E-02 +6.530281E-03 +2.594999E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.902136E-02 +6.530281E-03 +2.594999E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.592591E-02 +2.411450E-02 +9.950194E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.153867E-02 +8.408078E-03 +3.605577E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.153867E-02 +8.408078E-03 +3.605577E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.378633E-02 +3.106814E-02 +1.393272E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.245286E-02 +3.814914E-03 +1.410892E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.400224E-02 +4.807217E-03 +1.909383E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.537479E-02 +6.001257E-03 +2.571738E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.138507E-02 +1.888211E-02 +8.897563E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.138507E-02 +1.888211E-02 +8.897563E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.537479E-02 +6.001257E-03 +2.571738E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.400224E-02 +4.807217E-03 +1.909383E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.245286E-02 +3.814914E-03 +1.410892E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.879711E-02 +2.232061E-02 +8.567631E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.643668E-02 +2.797709E-02 +1.155505E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.426350E-02 +3.552093E-02 +1.595428E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.716436E-01 +8.254892E-02 +4.004867E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.426350E-02 +3.552093E-02 +1.595428E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.643668E-02 +2.797709E-02 +1.155505E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.879711E-02 +2.232061E-02 +8.567631E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.650554E-02 +5.673037E-03 +2.251753E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.811888E-02 +7.082053E-03 +3.032855E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.489376E-02 +2.049951E-02 +9.656902E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.489376E-02 +2.049951E-02 +9.656902E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.811888E-02 +7.082053E-03 +3.032855E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.650554E-02 +5.673037E-03 +2.251753E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.378633E-02 +3.106814E-02 +1.393272E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.153867E-02 +8.408078E-03 +3.605577E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.153867E-02 +8.408078E-03 +3.605577E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.491167E-02 +2.374351E-02 +9.797114E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.902136E-02 +6.530281E-03 +2.594999E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.902136E-02 +6.530281E-03 +2.594999E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.934204E-02 +1.924576E-02 +7.381658E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 diff --git a/tests/test_compute_flux/test_compute_flux.py b/tests/test_compute_flux/test_compute_flux.py new file mode 100644 index 000000000..df47b5089 --- /dev/null +++ b/tests/test_compute_flux/test_compute_flux.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput +import openmoc + + +class ComputeFluxTestHarness(TestHarness): + """A fixed source flux calculation in a cube of water with 7-group + cross sections. This tests the Solver::computeFlux(...) method.""" + + def __init__(self): + super(ComputeFluxTestHarness, self).__init__() + self.input_set = HomInfMedInput() + self.res_type = openmoc.SCALAR_FLUX + self.solution_type = 'flux' + + def _create_geometry(self): + """Put a box source """ + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Get the root Cell + cells = self.input_set.geometry.getAllCells() + for cell_id in cells: + cell = cells[cell_id] + if cell.getName() == 'root cell': + root_cell = cell + + # Apply VACUUM BCs on all bounding surfaces + surfaces = root_cell.getSurfaces() + for surface_id in surfaces: + surface = surfaces[surface_id]._surface + surface.setBoundaryType(openmoc.VACUUM) + + # Replace fissionable infinite medium material with C5G7 water + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + lattice = openmoc.castUniverseToLattice(root_cell.getFillUniverse()) + num_x = lattice.getNumX() + num_y = lattice.getNumY() + width_x = lattice.getWidthX() + width_y = lattice.getWidthY() + + # Create cells filled with water to put in Lattice + water_cell = openmoc.Cell(name='water') + water_cell.setFill(self.materials['Water']) + water_univ = openmoc.Universe(name='water') + water_univ.addCell(water_cell) + + self.source_cell = openmoc.Cell(name='source') + self.source_cell.setFill(self.materials['Water']) + source_univ = openmoc.Universe(name='source') + source_univ.addCell(self.source_cell) + + # Create 2D array of Universes in each lattice cell + universes = [[[water_univ]*num_x for _ in range(num_y)]] + + # Place fixed source Universe at (x=0.5, y=0.5) + source_x = 0.5 + source_y = 0.5 + lat_x = (root_cell.getMaxX() - source_x) / width_x + lat_y = (root_cell.getMaxY() - source_y) / width_y + universes[0][int(lat_x)][int(lat_y)] = source_univ + + # Create a new Lattice for the Universes + lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) + lattice.setWidth(width_x=width_x, width_y=width_y) + lattice.setUniverses(universes) + root_cell.setFill(lattice) + + def _create_solver(self): + """Instantiate a CPUSolver.""" + super(ComputeFluxTestHarness, self)._create_solver() + self.solver.setFixedSourceByCell(self.source_cell, 1, 1.0) + self.solver.setFixedSourceByCell(self.source_cell, 2, 0.5) + self.solver.setFixedSourceByCell(self.source_cell, 3, 0.25) + + +if __name__ == '__main__': + harness = ComputeFluxTestHarness() + harness.main() diff --git a/tests/test_compute_source/results_true.dat b/tests/test_compute_source/results_true.dat new file mode 100644 index 000000000..60c41f031 --- /dev/null +++ b/tests/test_compute_source/results_true.dat @@ -0,0 +1,702 @@ +# Iterations: 131 +fluxes: +4.693901E-02 +4.588587E-03 +5.337686E-04 +1.027865E-04 +4.162183E-05 +2.697635E-05 +2.468317E-05 +1.558603E-02 +3.211348E-03 +5.133292E-04 +1.108535E-04 +4.810125E-05 +3.501393E-05 +3.782484E-05 +1.558603E-02 +3.211348E-03 +5.133292E-04 +1.108535E-04 +4.810125E-05 +3.501393E-05 +3.782484E-05 +6.459894E-04 +1.835189E-03 +4.231738E-04 +1.054701E-04 +4.961742E-05 +4.011904E-05 +4.836575E-05 +5.058890E-02 +5.514907E-03 +7.357984E-04 +1.497950E-04 +6.496824E-05 +5.024057E-05 +6.120382E-05 +6.459894E-04 +1.835189E-03 +4.231738E-04 +1.054701E-04 +4.961742E-05 +4.011904E-05 +4.836575E-05 +4.120746E-04 +1.304116E-03 +3.642636E-04 +9.868228E-05 +4.887057E-05 +4.222941E-05 +5.392805E-05 +1.733760E-02 +3.843284E-03 +6.833344E-04 +1.553331E-04 +7.126899E-05 +5.934940E-05 +7.811006E-05 +1.733760E-02 +3.843284E-03 +6.833344E-04 +1.553331E-04 +7.126899E-05 +5.934940E-05 +7.811006E-05 +4.120746E-04 +1.304116E-03 +3.642636E-04 +9.868228E-05 +4.887057E-05 +4.222941E-05 +5.392805E-05 +4.991425E-04 +1.441689E-03 +3.670693E-04 +9.796419E-05 +4.867140E-05 +4.284263E-05 +5.582084E-05 +7.056410E-04 +2.174341E-03 +5.545663E-04 +1.436919E-04 +7.044359E-05 +6.309345E-05 +8.793260E-05 +5.635929E-02 +6.320977E-03 +9.051654E-04 +1.925076E-04 +8.695473E-05 +7.341624E-05 +1.001503E-04 +7.056410E-04 +2.174341E-03 +5.545663E-04 +1.436919E-04 +7.044359E-05 +6.309345E-05 +8.793260E-05 +4.991425E-04 +1.441689E-03 +3.670693E-04 +9.796419E-05 +4.867140E-05 +4.284263E-05 +5.582084E-05 +4.235179E-04 +1.280304E-03 +3.498417E-04 +9.499742E-05 +4.755390E-05 +4.219627E-05 +5.537025E-05 +4.559770E-04 +1.564902E-03 +4.737820E-04 +1.318124E-04 +6.732714E-05 +6.320636E-05 +9.118595E-05 +1.904660E-02 +4.353922E-03 +8.207625E-04 +1.926079E-04 +9.098649E-05 +8.064495E-05 +1.144322E-04 +1.904660E-02 +4.353922E-03 +8.207625E-04 +1.926079E-04 +9.098649E-05 +8.064495E-05 +1.144322E-04 +4.559770E-04 +1.564902E-03 +4.737820E-04 +1.318124E-04 +6.732714E-05 +6.320636E-05 +9.118595E-05 +4.235179E-04 +1.280304E-03 +3.498417E-04 +9.499742E-05 +4.755390E-05 +4.219627E-05 +5.537025E-05 +4.901980E-04 +1.384672E-03 +3.433832E-04 +9.163423E-05 +4.570522E-05 +4.029495E-05 +5.259599E-05 +5.599051E-04 +1.746764E-03 +4.747643E-04 +1.292013E-04 +6.583535E-05 +6.219959E-05 +9.047416E-05 +7.777778E-04 +2.538885E-03 +6.699107E-04 +1.764033E-04 +8.806657E-05 +8.240781E-05 +1.211858E-04 +6.117248E-02 +6.951817E-03 +1.040934E-03 +2.275650E-04 +1.052133E-04 +9.287680E-05 +1.330898E-04 +7.777778E-04 +2.538885E-03 +6.699107E-04 +1.764033E-04 +8.806657E-05 +8.240781E-05 +1.211858E-04 +5.599051E-04 +1.746764E-03 +4.747643E-04 +1.292013E-04 +6.583535E-05 +6.219959E-05 +9.047416E-05 +4.901980E-04 +1.384672E-03 +3.433832E-04 +9.163423E-05 +4.570522E-05 +4.029495E-05 +5.259599E-05 +3.102985E-04 +9.794356E-04 +2.870150E-04 +8.115421E-05 +4.124493E-05 +3.608675E-05 +4.611271E-05 +4.629657E-04 +1.515111E-03 +4.410514E-04 +1.223798E-04 +6.278877E-05 +5.923381E-05 +8.571848E-05 +4.976107E-04 +1.812651E-03 +5.670475E-04 +1.598880E-04 +8.278494E-05 +8.014150E-05 +1.202231E-04 +2.069316E-02 +4.751303E-03 +9.299143E-04 +2.230648E-04 +1.072353E-04 +9.787567E-05 +1.431094E-04 +2.069316E-02 +4.751303E-03 +9.299143E-04 +2.230648E-04 +1.072353E-04 +9.787567E-05 +1.431094E-04 +4.976107E-04 +1.812651E-03 +5.670475E-04 +1.598880E-04 +8.278494E-05 +8.014150E-05 +1.202231E-04 +4.629657E-04 +1.515111E-03 +4.410514E-04 +1.223798E-04 +6.278877E-05 +5.923381E-05 +8.571848E-05 +3.102985E-04 +9.794356E-04 +2.870150E-04 +8.115421E-05 +4.124493E-05 +3.608675E-05 +4.611271E-05 +2.574975E-04 +7.906510E-04 +2.425386E-04 +7.036892E-05 +3.565312E-05 +2.978659E-05 +3.533241E-05 +5.423679E-04 +1.639903E-03 +4.224050E-04 +1.141657E-04 +5.795658E-05 +5.333938E-05 +7.502097E-05 +6.189175E-04 +2.037583E-03 +5.611603E-04 +1.534884E-04 +7.873579E-05 +7.548001E-05 +1.122651E-04 +8.510913E-04 +2.896787E-03 +7.675686E-04 +2.029138E-04 +1.018167E-04 +9.611471E-05 +1.428429E-04 +6.883258E-02 +7.613236E-03 +1.160751E-03 +2.568249E-04 +1.198121E-04 +1.069534E-04 +1.548754E-04 +8.510913E-04 +2.896787E-03 +7.675686E-04 +2.029138E-04 +1.018167E-04 +9.611471E-05 +1.428429E-04 +6.189175E-04 +2.037583E-03 +5.611603E-04 +1.534884E-04 +7.873579E-05 +7.548001E-05 +1.122651E-04 +5.423679E-04 +1.639903E-03 +4.224050E-04 +1.141657E-04 +5.795658E-05 +5.333938E-05 +7.502097E-05 +2.574975E-04 +7.906510E-04 +2.425386E-04 +7.036892E-05 +3.565312E-05 +2.978659E-05 +3.533241E-05 +2.262821E-04 +6.794693E-04 +2.087870E-04 +6.092962E-05 +2.993593E-05 +2.265296E-05 +2.290713E-05 +3.573059E-04 +1.179331E-03 +3.487336E-04 +9.772150E-05 +4.961329E-05 +4.390664E-05 +5.822289E-05 +5.298645E-04 +1.812269E-03 +5.196396E-04 +1.419922E-04 +7.221852E-05 +6.756894E-05 +9.783950E-05 +5.686957E-04 +2.138856E-03 +6.532571E-04 +1.812658E-04 +9.293305E-05 +8.892467E-05 +1.325657E-04 +2.333319E-02 +5.275129E-03 +1.035852E-03 +2.474338E-04 +1.184282E-04 +1.072273E-04 +1.558283E-04 +2.333319E-02 +5.275129E-03 +1.035852E-03 +2.474338E-04 +1.184282E-04 +1.072273E-04 +1.558283E-04 +5.686957E-04 +2.138856E-03 +6.532571E-04 +1.812658E-04 +9.293305E-05 +8.892467E-05 +1.325657E-04 +5.298645E-04 +1.812269E-03 +5.196396E-04 +1.419922E-04 +7.221852E-05 +6.756894E-05 +9.783950E-05 +3.573059E-04 +1.179331E-03 +3.487336E-04 +9.772150E-05 +4.961329E-05 +4.390664E-05 +5.822289E-05 +2.262821E-04 +6.794693E-04 +2.087870E-04 +6.092962E-05 +2.993593E-05 +2.265296E-05 +2.290713E-05 +3.686351E-04 +1.074029E-03 +2.944699E-04 +8.033359E-05 +3.901667E-05 +3.124818E-05 +3.606017E-05 +6.952423E-04 +2.144111E-03 +5.064161E-04 +1.290391E-04 +6.310443E-05 +5.595327E-05 +7.675259E-05 +7.856301E-04 +2.620104E-03 +6.620619E-04 +1.715007E-04 +8.509277E-05 +7.894317E-05 +1.148737E-04 +1.031055E-03 +3.556014E-03 +8.795358E-04 +2.228247E-04 +1.089051E-04 +1.001206E-04 +1.460729E-04 +7.690467E-02 +8.413092E-03 +1.281063E-03 +2.778448E-04 +1.272928E-04 +1.112129E-04 +1.583607E-04 +1.031055E-03 +3.556014E-03 +8.795358E-04 +2.228247E-04 +1.089051E-04 +1.001206E-04 +1.460729E-04 +7.856301E-04 +2.620104E-03 +6.620619E-04 +1.715007E-04 +8.509277E-05 +7.894317E-05 +1.148737E-04 +6.952423E-04 +2.144111E-03 +5.064161E-04 +1.290391E-04 +6.310443E-05 +5.595327E-05 +7.675259E-05 +3.686351E-04 +1.074029E-03 +2.944699E-04 +8.033359E-05 +3.901667E-05 +3.124818E-05 +3.606017E-05 +1.352614E-02 +2.717218E-03 +4.732882E-04 +1.091014E-04 +4.989301E-05 +3.986506E-05 +4.819292E-05 +1.533263E-02 +3.736477E-03 +6.928306E-04 +1.600603E-04 +7.485556E-05 +6.518953E-05 +8.977444E-05 +1.677452E-02 +4.226308E-03 +8.491831E-04 +2.027525E-04 +9.680519E-05 +8.748251E-05 +1.257719E-04 +4.403597E-02 +7.497052E-03 +1.242118E-03 +2.701135E-04 +1.226981E-04 +1.061485E-04 +1.496124E-04 +4.403597E-02 +7.497052E-03 +1.242118E-03 +2.701135E-04 +1.226981E-04 +1.061485E-04 +1.496124E-04 +1.677452E-02 +4.226308E-03 +8.491831E-04 +2.027525E-04 +9.680519E-05 +8.748251E-05 +1.257719E-04 +1.533263E-02 +3.736477E-03 +6.928306E-04 +1.600603E-04 +7.485556E-05 +6.518953E-05 +8.977444E-05 +1.352614E-02 +2.717218E-03 +4.732882E-04 +1.091014E-04 +4.989301E-05 +3.986506E-05 +4.819292E-05 +7.138098E-02 +6.080652E-03 +7.112672E-04 +1.376815E-04 +5.902061E-05 +4.616789E-05 +5.610408E-05 +7.925399E-02 +7.184301E-03 +9.250323E-04 +1.867668E-04 +8.312723E-05 +7.067487E-05 +9.653805E-05 +8.738493E-02 +8.442291E-03 +1.167905E-03 +2.406815E-04 +1.077218E-04 +9.252487E-05 +1.290568E-04 +1.768726E-01 +1.341696E-02 +1.572127E-03 +2.956323E-04 +1.260774E-04 +1.037263E-04 +1.416780E-04 +8.738493E-02 +8.442291E-03 +1.167905E-03 +2.406815E-04 +1.077218E-04 +9.252487E-05 +1.290568E-04 +7.925399E-02 +7.184301E-03 +9.250323E-04 +1.867668E-04 +8.312723E-05 +7.067487E-05 +9.653805E-05 +7.138098E-02 +6.080652E-03 +7.112672E-04 +1.376815E-04 +5.902061E-05 +4.616789E-05 +5.610408E-05 +1.784362E-02 +3.633795E-03 +6.027128E-04 +1.318044E-04 +5.924910E-05 +4.812917E-05 +5.957896E-05 +1.953447E-02 +4.178031E-03 +7.714249E-04 +1.764403E-04 +8.205384E-05 +7.142838E-05 +9.804610E-05 +4.756348E-02 +7.441243E-03 +1.161254E-03 +2.432034E-04 +1.078134E-04 +9.032654E-05 +1.229352E-04 +4.756348E-02 +7.441243E-03 +1.161254E-03 +2.432034E-04 +1.078134E-04 +9.032654E-05 +1.229352E-04 +1.953447E-02 +4.178031E-03 +7.714249E-04 +1.764403E-04 +8.205384E-05 +7.142838E-05 +9.804610E-05 +1.784362E-02 +3.633795E-03 +6.027128E-04 +1.318044E-04 +5.924910E-05 +4.812917E-05 +5.957896E-05 +7.836078E-04 +2.436233E-03 +5.234497E-04 +1.246733E-04 +5.806002E-05 +4.830111E-05 +6.030962E-05 +1.024817E-03 +3.364458E-03 +7.450740E-04 +1.765772E-04 +8.230067E-05 +7.053588E-05 +9.493488E-05 +7.682840E-02 +7.975056E-03 +1.122105E-03 +2.286216E-04 +9.994849E-05 +8.166896E-05 +1.080931E-04 +1.024817E-03 +3.364458E-03 +7.450740E-04 +1.765772E-04 +8.230067E-05 +7.053588E-05 +9.493488E-05 +7.836078E-04 +2.436233E-03 +5.234497E-04 +1.246733E-04 +5.806002E-05 +4.830111E-05 +6.030962E-05 +5.531913E-04 +1.872310E-03 +4.718733E-04 +1.188205E-04 +5.642786E-05 +4.706373E-05 +5.835484E-05 +2.325281E-02 +4.754160E-03 +8.241286E-04 +1.805860E-04 +8.078402E-05 +6.572667E-05 +8.451885E-05 +2.325281E-02 +4.754160E-03 +8.241286E-04 +1.805860E-04 +8.078402E-05 +6.572667E-05 +8.451885E-05 +5.531913E-04 +1.872310E-03 +4.718733E-04 +1.188205E-04 +5.642786E-05 +4.706373E-05 +5.835484E-05 +8.254781E-04 +2.511904E-03 +5.269659E-04 +1.234745E-04 +5.625231E-05 +4.441054E-05 +5.240958E-05 +6.762202E-02 +6.651552E-03 +8.664301E-04 +1.710378E-04 +7.275694E-05 +5.539984E-05 +6.632853E-05 +8.254781E-04 +2.511904E-03 +5.269659E-04 +1.234745E-04 +5.625231E-05 +4.441054E-05 +5.240958E-05 +2.056791E-02 +3.924894E-03 +6.052301E-04 +1.259959E-04 +5.359527E-05 +3.850439E-05 +4.100511E-05 +2.056791E-02 +3.924894E-03 +6.052301E-04 +1.259959E-04 +5.359527E-05 +3.850439E-05 +4.100511E-05 +6.181493E-02 +5.493806E-03 +6.189235E-04 +1.153938E-04 +4.600586E-05 +2.956819E-05 +2.675950E-05 diff --git a/tests/test_compute_source/test_compute_source.py b/tests/test_compute_source/test_compute_source.py new file mode 100644 index 000000000..a1fdee632 --- /dev/null +++ b/tests/test_compute_source/test_compute_source.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +import os +import sys + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput +import openmoc + + +class ComputeSourceTestHarness(TestHarness): + """A source calculation in a cube of water with 7-group cross sections and + a fixed box source. This tests the Solver::computeSource(...) method.""" + + def __init__(self): + super(ComputeSourceTestHarness, self).__init__() + self.input_set = HomInfMedInput() + self.res_type = openmoc.TOTAL_SOURCE + self.solution_type = 'source' + self.source_cell = None + + def _create_geometry(self): + """Put a box source in the cube.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Get the root Cell + cells = self.input_set.geometry.getAllCells() + for cell_id in cells: + cell = cells[cell_id] + if cell.getName() == 'root cell': + root_cell = cell + + # Apply VACUUM BCs on all bounding surfaces + surfaces = root_cell.getSurfaces() + for surface_id in surfaces: + surface = surfaces[surface_id]._surface + surface.setBoundaryType(openmoc.VACUUM) + + # Replace fissionable infinite medium material with C5G7 water + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + lattice = openmoc.castUniverseToLattice(root_cell.getFillUniverse()) + num_x = lattice.getNumX() + num_y = lattice.getNumY() + width_x = lattice.getWidthX() + width_y = lattice.getWidthY() + + # Create cells filled with water to put in Lattice + water_cell = openmoc.Cell(name='water') + water_cell.setFill(self.materials['Water']) + water_univ = openmoc.Universe(name='water') + water_univ.addCell(water_cell) + + self.source_cell = openmoc.Cell(name='source') + self.source_cell.setFill(self.materials['Water']) + source_univ = openmoc.Universe(name='source') + source_univ.addCell(self.source_cell) + + # Create 2D array of Universes in each lattice cell + universes = [[[water_univ]*num_x for _ in range(num_y)]] + + # Place fixed source Universe at (x=0.5, y=0.5) + source_x = 0.5 + source_y = 0.5 + lat_x = (root_cell.getMaxX() - source_x) / width_x + lat_y = (root_cell.getMaxY() - source_y) / width_y + universes[0][int(lat_x)][int(lat_y)] = source_univ + + # Create a new Lattice for the Universes + lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) + lattice.setWidth(width_x=width_x, width_y=width_y) + lattice.setUniverses(universes) + root_cell.setFill(lattice) + + def _create_solver(self): + """Instantiate a CPUSolver.""" + super(ComputeSourceTestHarness, self)._create_solver() + self.solver.setFixedSourceByCell(self.source_cell, 1, 1.0) + + +if __name__ == '__main__': + harness = ComputeSourceTestHarness() + harness.main() diff --git a/tests/test_correct_fsr_volume/results_true.dat b/tests/test_correct_fsr_volume/results_true.dat new file mode 100644 index 000000000..95b45a669 --- /dev/null +++ b/tests/test_correct_fsr_volume/results_true.dat @@ -0,0 +1 @@ + 3.1330725384 2.7000000000 \ No newline at end of file diff --git a/tests/test_correct_fsr_volume/test_correct_fsr_volume.py b/tests/test_correct_fsr_volume/test_correct_fsr_volume.py new file mode 100644 index 000000000..a4c612305 --- /dev/null +++ b/tests/test_correct_fsr_volume/test_correct_fsr_volume.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput + + +class CorrectFSRVolumeTestHarness(TestHarness): + """Tests Geometry::correctFSRVolume() method.""" + + def __init__(self): + super(CorrectFSRVolumeTestHarness, self).__init__() + self.input_set = PinCellInput() + self._result = '' + + def _generate_tracks(self): + """Generate Tracks and segments and correct the FSR volume for + the fuel.""" + + # Always use 1 thread for FSR reproducibility + self.track_generator.setNumThreads(1) + self.track_generator.generateTracks() + + # Correct FSR volumes with the appropriate number of threads + self.track_generator.setNumThreads(self.num_threads) + old_volume = self.track_generator.getFSRVolume(1) + self.track_generator.correctFSRVolume(1, 2.7) + new_volume = self.track_generator.getFSRVolume(1) + + # Save results for one thread + self._result += '{0: 1.10f}'.format(old_volume) + self._result += '{0: 1.10f}'.format(new_volume) + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=False, num_segments=False, num_tracks=False): + """Return the result string""" + return self._result + + +if __name__ == '__main__': + harness = CorrectFSRVolumeTestHarness() + harness.main() diff --git a/tests/test_forward_hom_inf_medium/results_true.dat b/tests/test_forward_hom_inf_medium/results_true.dat new file mode 100644 index 000000000..816cfe2c4 --- /dev/null +++ b/tests/test_forward_hom_inf_medium/results_true.dat @@ -0,0 +1,203 @@ +# Iterations: 88 +keff: 1.72302E+00 +fluxes: +7.687170E-01 +4.887597E-01 +7.687173E-01 +4.887610E-01 +7.687173E-01 +4.887610E-01 +7.687178E-01 +4.887622E-01 +7.687175E-01 +4.887619E-01 +7.687178E-01 +4.887622E-01 +7.687183E-01 +4.887631E-01 +7.687179E-01 +4.887629E-01 +7.687179E-01 +4.887629E-01 +7.687183E-01 +4.887631E-01 +7.687188E-01 +4.887638E-01 +7.687183E-01 +4.887637E-01 +7.687180E-01 +4.887636E-01 +7.687183E-01 +4.887637E-01 +7.687188E-01 +4.887638E-01 +7.687192E-01 +4.887643E-01 +7.687188E-01 +4.887644E-01 +7.687183E-01 +4.887642E-01 +7.687183E-01 +4.887642E-01 +7.687188E-01 +4.887644E-01 +7.687192E-01 +4.887643E-01 +7.687196E-01 +4.887647E-01 +7.687192E-01 +4.887649E-01 +7.687188E-01 +4.887648E-01 +7.687185E-01 +4.887647E-01 +7.687188E-01 +4.887648E-01 +7.687192E-01 +4.887649E-01 +7.687196E-01 +4.887647E-01 +7.687200E-01 +4.887650E-01 +7.687196E-01 +4.887653E-01 +7.687192E-01 +4.887653E-01 +7.687188E-01 +4.887652E-01 +7.687188E-01 +4.887652E-01 +7.687192E-01 +4.887653E-01 +7.687196E-01 +4.887653E-01 +7.687200E-01 +4.887650E-01 +7.687204E-01 +4.887652E-01 +7.687200E-01 +4.887655E-01 +7.687196E-01 +4.887656E-01 +7.687191E-01 +4.887655E-01 +7.687189E-01 +4.887654E-01 +7.687191E-01 +4.887655E-01 +7.687196E-01 +4.887656E-01 +7.687200E-01 +4.887655E-01 +7.687204E-01 +4.887652E-01 +7.687206E-01 +4.887651E-01 +7.687202E-01 +4.887655E-01 +7.687198E-01 +4.887657E-01 +7.687194E-01 +4.887657E-01 +7.687190E-01 +4.887655E-01 +7.687190E-01 +4.887655E-01 +7.687194E-01 +4.887657E-01 +7.687198E-01 +4.887657E-01 +7.687202E-01 +4.887655E-01 +7.687206E-01 +4.887651E-01 +7.687204E-01 +4.887652E-01 +7.687200E-01 +4.887655E-01 +7.687196E-01 +4.887656E-01 +7.687191E-01 +4.887655E-01 +7.687189E-01 +4.887654E-01 +7.687191E-01 +4.887655E-01 +7.687196E-01 +4.887656E-01 +7.687200E-01 +4.887655E-01 +7.687204E-01 +4.887652E-01 +7.687200E-01 +4.887650E-01 +7.687196E-01 +4.887653E-01 +7.687192E-01 +4.887653E-01 +7.687188E-01 +4.887652E-01 +7.687188E-01 +4.887652E-01 +7.687192E-01 +4.887653E-01 +7.687196E-01 +4.887653E-01 +7.687200E-01 +4.887650E-01 +7.687196E-01 +4.887647E-01 +7.687192E-01 +4.887649E-01 +7.687188E-01 +4.887648E-01 +7.687185E-01 +4.887647E-01 +7.687188E-01 +4.887648E-01 +7.687192E-01 +4.887649E-01 +7.687196E-01 +4.887647E-01 +7.687192E-01 +4.887643E-01 +7.687188E-01 +4.887644E-01 +7.687183E-01 +4.887642E-01 +7.687183E-01 +4.887642E-01 +7.687188E-01 +4.887644E-01 +7.687192E-01 +4.887643E-01 +7.687188E-01 +4.887638E-01 +7.687183E-01 +4.887637E-01 +7.687180E-01 +4.887636E-01 +7.687183E-01 +4.887637E-01 +7.687188E-01 +4.887638E-01 +7.687183E-01 +4.887631E-01 +7.687179E-01 +4.887629E-01 +7.687179E-01 +4.887629E-01 +7.687183E-01 +4.887631E-01 +7.687178E-01 +4.887622E-01 +7.687175E-01 +4.887619E-01 +7.687178E-01 +4.887622E-01 +7.687173E-01 +4.887610E-01 +7.687173E-01 +4.887610E-01 +7.687170E-01 +4.887597E-01 diff --git a/tests/test_forward_hom_inf_medium/test_forward_hom_inf_medium.py b/tests/test_forward_hom_inf_medium/test_forward_hom_inf_medium.py new file mode 100644 index 000000000..c46860ef5 --- /dev/null +++ b/tests/test_forward_hom_inf_medium/test_forward_hom_inf_medium.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import HomInfMedInput + + +class HomInfMedTestHarness(TestHarness): + """An eigenvalue calculation in a homogeneous infinite medium with 2-group + cross section data.""" + + def __init__(self): + super(HomInfMedTestHarness, self).__init__() + self.input_set = HomInfMedInput() + + +if __name__ == '__main__': + harness = HomInfMedTestHarness() + harness.main() diff --git a/tests/test_forward_pin_cell/results_true.dat b/tests/test_forward_pin_cell/results_true.dat new file mode 100644 index 000000000..8469457f1 --- /dev/null +++ b/tests/test_forward_pin_cell/results_true.dat @@ -0,0 +1,17 @@ +# Iterations: 13 +keff: 8.48987E-01 +fluxes: +3.951635E-01 +6.378536E-01 +3.060618E-01 +1.279327E-01 +9.523942E-02 +2.420788E-01 +6.395380E-01 +6.791784E-01 +8.268482E-01 +2.942492E-01 +1.141492E-01 +9.150147E-02 +2.154790E-01 +4.690481E-01 diff --git a/tests/test_forward_pin_cell/test_forward_pin_cell.py b/tests/test_forward_pin_cell/test_forward_pin_cell.py new file mode 100644 index 000000000..cfd33134f --- /dev/null +++ b/tests/test_forward_pin_cell/test_forward_pin_cell.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput + + +class PinCellTestHarness(TestHarness): + """An eigenvalue calculation in a pin cell with 7-group C5G7 data.""" + + def __init__(self): + super(PinCellTestHarness, self).__init__() + self.input_set = PinCellInput() + + +if __name__ == '__main__': + harness = PinCellTestHarness() + harness.main() diff --git a/tests/test_forward_simple_lattice/results_true.dat b/tests/test_forward_simple_lattice/results_true.dat new file mode 100644 index 000000000..92c846f9b --- /dev/null +++ b/tests/test_forward_simple_lattice/results_true.dat @@ -0,0 +1 @@ +994452072d56bc285fa095c2fcbb5cc515610551f6f04d308c100f196050f5d1eacf4a240f95554e92b4e27f44607ef2cce293fd4198c2a020c724408a196f00 \ No newline at end of file diff --git a/tests/test_forward_simple_lattice/test_forward_simple_lattice.py b/tests/test_forward_simple_lattice/test_forward_simple_lattice.py new file mode 100644 index 000000000..0bc0e7cc0 --- /dev/null +++ b/tests/test_forward_simple_lattice/test_forward_simple_lattice.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import SimpleLatticeInput + + +class SimpleLatticeTestHarness(TestHarness): + """An eigenvalue calculation for a 4x4 lattice with 7-group C5G7 + cross section data.""" + + def __init__(self): + super(SimpleLatticeTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=True): + """Digest info in the solver and return hash as a string.""" + return super(SimpleLatticeTestHarness, self)._get_results( + num_iters=num_iters, keff=keff, fluxes=fluxes, + num_fsrs=num_fsrs, num_tracks=num_tracks, + num_segments=num_segments, hash_output=hash_output) + + +if __name__ == '__main__': + harness = SimpleLatticeTestHarness() + harness.main() diff --git a/tests/test_logger/results_true.dat b/tests/test_logger/results_true.dat new file mode 100644 index 000000000..42299588b --- /dev/null +++ b/tests/test_logger/results_true.dat @@ -0,0 +1,18 @@ +[ NORMAL ] This is a normal message +[SEPARATOR] ******************************************************************* +[ HEADER ] ******************* This is a header message ******************** +[ TITLE ] ******************************************************************* +[ TITLE ] This is a title message +[ TITLE ] ******************************************************************* +[ WARNING ] This is a warning message +[ CRITICAL] This is a critical message +[ RESULT ] This is a result message +[ NORMAL ] This is a normal message +[SEPARATOR] ******************************************************************* +[ HEADER ] ******************* This is a header message ******************** +[ TITLE ] ******************************************************************* +[ TITLE ] This is a title message +[ TITLE ] ******************************************************************* +[ WARNING ] This is a warning message +[ CRITICAL] This is a critical message +[ RESULT ] This is a result message: 5 diff --git a/tests/test_logger/test_logger.py b/tests/test_logger/test_logger.py new file mode 100644 index 000000000..0c0e5486e --- /dev/null +++ b/tests/test_logger/test_logger.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import os +import sys +import glob +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +import openmoc +from openmoc.log import py_printf + + +class LoggerTestHarness(TestHarness): + """A test of OpenMOC's logger module.""" + + def __init__(self): + super(LoggerTestHarness, self).__init__() + + def _create_geometry(self): + pass + + def _create_trackgenerator(self): + pass + + def _generate_tracks(self): + pass + + def _run_openmoc(self): + """Print a variety of log messages to a log file.""" + + # Set a log level which precludes some messages from being printed + openmoc.set_log_level('NORMAL') + + # Print messages using the pure C implementation + openmoc.log_printf(openmoc.DEBUG, 'This is a debug message') + openmoc.log_printf(openmoc.INFO, 'This is an info message') + openmoc.log_printf(openmoc.NORMAL, 'This is a normal message') + openmoc.log_printf(openmoc.SEPARATOR, 'This is a separator message') + openmoc.log_printf(openmoc.HEADER, 'This is a header message') + openmoc.log_printf(openmoc.TITLE, 'This is a title message') + openmoc.log_printf(openmoc.WARNING, 'This is a warning message') + openmoc.log_printf(openmoc.CRITICAL, 'This is a critical message') + openmoc.log_printf(openmoc.RESULT, 'This is a result message') + + # Print messages using the Python-wrapped version + py_printf('DEBUG', 'This is a debug message') + py_printf('INFO', 'This is an info message') + py_printf('NORMAL', 'This is a normal message') + py_printf('SEPARATOR', 'This is a separator message') + py_printf('HEADER', 'This is a header message') + py_printf('TITLE', 'This is a title message') + py_printf('WARNING', 'This is a warning message') + py_printf('CRITICAL', 'This is a critical message') + py_printf('RESULT', 'This is a result message: %d', 5) + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=False): + """Digest info in the log file and return as a string.""" + + # Find the log filename with the time and date + logfilename = glob.glob('log/openmoc-*') + + # Read the file into a list of strings for each line + with open(logfilename[0], 'r') as myfile: + lines = myfile.readlines() + + # Concatenate all strings in the file into a single string + # Exclude the first line which is the time and date + outstr = ''.join(lines[1:]) + return outstr + + +if __name__ == '__main__': + harness = LoggerTestHarness() + harness.main() diff --git a/tests/test_mesh_tally/results_true.dat b/tests/test_mesh_tally/results_true.dat new file mode 100644 index 000000000..5c84318db --- /dev/null +++ b/tests/test_mesh_tally/results_true.dat @@ -0,0 +1,34 @@ +Fission Rate Mesh Tally +3.353353E-02 +3.338218E-02 +3.294499E-02 +3.249079E-02 +9.750141E-03 +2.066646E-02 +9.611750E-03 +2.011758E-02 +3.825673E-02 +3.752810E-02 +3.678808E-02 +3.634697E-02 +1.120547E-02 +2.333152E-02 +1.059631E-02 +2.238678E-02 +Total Rate Mesh Tally +9.946562E-01 +9.873652E-01 +9.850319E-01 +9.738077E-01 +1.377744E+00 +1.215573E+00 +1.341348E+00 +1.196637E+00 +1.066607E+00 +1.046836E+00 +1.048249E+00 +1.033046E+00 +1.489862E+00 +1.311203E+00 +1.456958E+00 +1.272930E+00 diff --git a/tests/test_mesh_tally/test_mesh_tally.py b/tests/test_mesh_tally/test_mesh_tally.py new file mode 100644 index 000000000..e628c5360 --- /dev/null +++ b/tests/test_mesh_tally/test_mesh_tally.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +import os +import sys +import hashlib +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import SimpleLatticeInput +import openmoc.process as process +import numpy as np + + +class MeshTallyTestHarness(TestHarness): + """An eigenvalue calculation with a mesh tally of the fission rates + using the openmoc.process module.""" + + def __init__(self): + super(MeshTallyTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Run an OpenMOC eigenvalue calculation.""" + super(MeshTallyTestHarness, self)._run_openmoc() + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=True, num_tracks=True, num_segments=True, + hash_output=True): + """Digest info from the mesh tallies and return as a string.""" + + # Create OpenMOC Mesh on which to tally fission rates + mesh = process.Mesh() + mesh.dimension = [4, 4] + mesh.lower_left = [-2., -2.] + mesh.upper_right = [2., 2.] + mesh.width = [1., 1.] + + # Tally OpenMOC fission rates on the Mesh + fiss_rates = mesh.tally_fission_rates(self.solver) + + # Append fission rates to the output string + outstr = 'Fission Rate Mesh Tally\n' + rates = ['{0:12.6E}'.format(rate) for rate in fiss_rates.ravel()] + outstr += '\n'.join(rates) + '\n' + + # Retrieve the Materials and number of groups from the geometry + materials = self.input_set.geometry.getAllMaterials() + num_groups = self.input_set.geometry.getNumEnergyGroups() + + # Aggregate the total cross sections for each Material + # into a dictionary to pass to the mesh tally + domains_to_coeffs = {} + for material_id in materials: + domains_to_coeffs[material_id] = np.zeros(num_groups) + for group in range(num_groups): + domains_to_coeffs[material_id][group] = \ + materials[material_id].getSigmaTByGroup(group+1) + + # Tally volume-averaged OpenMOC total rates on the Mesh + tot_rates = mesh.tally_on_mesh(self.solver, domains_to_coeffs, + domain_type='material', + volume='integrated') + + # Append total rates to the output string + outstr += 'Total Rate Mesh Tally\n' + rates = ['{0:12.6E}'.format(rate) for rate in tot_rates.ravel()] + outstr += '\n'.join(rates) + '\n' + + return outstr + + +if __name__ == '__main__': + harness = MeshTallyTestHarness() + harness.main() diff --git a/tests/test_multisim_cmfd/results_true.dat b/tests/test_multisim_cmfd/results_true.dat new file mode 100644 index 000000000..f566a0885 --- /dev/null +++ b/tests/test_multisim_cmfd/results_true.dat @@ -0,0 +1,3 @@ +Iters: 5 keff: 1.21933E+00 +Iters: 5 keff: 1.21933E+00 +Iters: 5 keff: 1.21933E+00 diff --git a/tests/test_multisim_cmfd/test_multisim_cmfd.py b/tests/test_multisim_cmfd/test_multisim_cmfd.py new file mode 100644 index 000000000..2dad48266 --- /dev/null +++ b/tests/test_multisim_cmfd/test_multisim_cmfd.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import PwrAssemblyInput +import openmoc + + +class MultiSimCmfdTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation with CMFD for a 17x17 + lattice with 7-group C5G7 cross section data.""" + + def __init__(self): + super(MultiSimCmfdTestHarness, self).__init__() + self.input_set = PwrAssemblyInput() + self.max_iters = 5 + + def _create_geometry(self): + """Initialize CMFD and add it to the Geometry.""" + + super(MultiSimCmfdTestHarness, self)._create_geometry() + + # Initialize CMFD + cmfd = openmoc.Cmfd() + cmfd.setSORRelaxationFactor(1.5) + cmfd.setLatticeStructure(17,17) + cmfd.setGroupStructure([1,4,8]) + cmfd.setKNearest(3) + + # Add CMFD to the Geometry + self.input_set.geometry.setCmfd(cmfd) + + +if __name__ == '__main__': + harness = MultiSimCmfdTestHarness() + harness.main() diff --git a/tests/test_multisim_fixed_source/results_true.dat b/tests/test_multisim_fixed_source/results_true.dat new file mode 100644 index 000000000..ad6026ec1 --- /dev/null +++ b/tests/test_multisim_fixed_source/results_true.dat @@ -0,0 +1 @@ +c9fd368432375ff0d3e70252c743887e9909274b1554b8c01b848262d6f2f1ce8fca077f08059dc455f26be6a63ac0387fd346dd9488a7dc90b504f4539d2338 \ No newline at end of file diff --git a/tests/test_multisim_fixed_source/test_multisim_fixed_source.py b/tests/test_multisim_fixed_source/test_multisim_fixed_source.py new file mode 100644 index 000000000..7a1878411 --- /dev/null +++ b/tests/test_multisim_fixed_source/test_multisim_fixed_source.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +import os +import sys +import hashlib +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import HomInfMedInput +import openmoc +import openmoc.process + + +class MultiSimFixedSourceTestHarness(MultiSimTestHarness): + """A multi-simulation fixed source calculation for a cube of water with + 7-group cross sections and a fixed box source.""" + + def __init__(self): + super(MultiSimFixedSourceTestHarness, self).__init__() + self.input_set = HomInfMedInput() + self.res_type = openmoc.TOTAL_SOURCE + self.solution_type = 'source' + self.source_cell = None + self.fluxes = [] + + def _create_geometry(self): + """Put a box source in the cube.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Get the root Cell + cells = self.input_set.geometry.getAllCells() + for cell_id in cells: + cell = cells[cell_id] + if cell.getName() == 'root cell': + root_cell = cell + + # Apply VACUUM BCs on all bounding surfaces + surfaces = root_cell.getSurfaces() + for surface_id in surfaces: + surface = surfaces[surface_id]._surface + surface.setBoundaryType(openmoc.VACUUM) + + # Replace fissionable infinite medium material with C5G7 water + self.materials = \ + openmoc.materialize.load_from_hdf5(filename='c5g7-mgxs.h5', + directory='../../sample-input/') + + lattice = openmoc.castUniverseToLattice(root_cell.getFillUniverse()) + num_x = lattice.getNumX() + num_y = lattice.getNumY() + width_x = lattice.getWidthX() + width_y = lattice.getWidthY() + + # Create cells filled with water to put in Lattice + water_cell = openmoc.Cell(name='water') + water_cell.setFill(self.materials['Water']) + water_univ = openmoc.Universe(name='water') + water_univ.addCell(water_cell) + + self.source_cell = openmoc.Cell(name='source') + self.source_cell.setFill(self.materials['Water']) + source_univ = openmoc.Universe(name='source') + source_univ.addCell(self.source_cell) + + # Create 2D array of Universes in each lattice cell + universes = [[[water_univ]*num_x for _ in range(num_y)]] + + # Place fixed source Universe at (x=0.5, y=0.5) + source_x = 0.5 + source_y = 0.5 + lat_x = (root_cell.getMaxX() - source_x) / width_x + lat_y = (root_cell.getMaxY() - source_y) / width_y + universes[0][int(lat_x)][int(lat_y)] = source_univ + + # Create a new Lattice for the Universes + lattice = openmoc.Lattice(name='{0}x{1} lattice'.format(num_x, num_y)) + lattice.setWidth(width_x=width_x, width_y=width_y) + lattice.setUniverses(universes) + root_cell.setFill(lattice) + + def _create_solver(self): + """Instantiate a CPUSolver.""" + super(MultiSimFixedSourceTestHarness, self)._create_solver() + self.solver.setFixedSourceByCell(self.source_cell, 1, 1.0) + + def _run_openmoc(self): + """Run multiple OpenMOC fixed source calculations.""" + + for i in range(self.num_simulations): + super(MultiSimTestHarness, self)._run_openmoc() + self.num_iters.append(self.solver.getNumIterations()) + self.fluxes.append(openmoc.process.get_scalar_fluxes(self.solver)) + + def _get_results(self, num_iterations=True, keff=True, fluxes=False, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=True): + """Return eigenvalues from each simulation into a string.""" + + # Write out the iteration count and fluxes from each simulation + outstr = '' + for i, num_iters in enumerate(self.num_iters): + outstr += 'Iters: {0}\n'.format(num_iters) + + # Create a list of the floating point flux values + fluxes = \ + ['{0:12.6E}'.format(flux) for flux in self.fluxes[i].ravel()] + + # Add the fluxes to the output string + outstr += 'fluxes:\n' + outstr += '\n'.join(fluxes) + '\n' + + # Hash the results if necessary. + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + +if __name__ == '__main__': + harness = MultiSimFixedSourceTestHarness() + harness.main() diff --git a/tests/test_multisim_materials/results_true.dat b/tests/test_multisim_materials/results_true.dat new file mode 100644 index 000000000..779125e35 --- /dev/null +++ b/tests/test_multisim_materials/results_true.dat @@ -0,0 +1,3 @@ +Iters: 13 keff: 8.48987E-01 +Iters: 13 keff: 8.48987E-01 +Iters: 13 keff: 8.48987E-01 diff --git a/tests/test_multisim_materials/test_multisim_materials.py b/tests/test_multisim_materials/test_multisim_materials.py new file mode 100644 index 000000000..8c0a6b1a9 --- /dev/null +++ b/tests/test_multisim_materials/test_multisim_materials.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import PinCellInput +import openmoc + + +class MultiSimMaterialsTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation with different materials in + a pin cell problem with C5G7 7-group cross section data.""" + + def __init__(self): + super(MultiSimMaterialsTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Run multiple OpenMOC eigenvalue calculations with different + materials.""" + + for i in range(self.num_simulations): + + # Extract all of the Material-filled Cells in the Geometry + cells = self.input_set.geometry.getAllMaterialCells() + materials = self.input_set.geometry.getAllMaterials() + + # Exchange all of the Materials for their clones + for cell_id in cells: + material = cells[cell_id].getFillMaterial() + clone = material.clone() + cells[cell_id].setFill(clone) + + # Turn on SWIG flag to register old Materials + # with Python garbage collector + for material_id in materials: + materials[material_id].thisown = 1 + + # Run eigenvalue calculation and store the results + self.num_simulations = 1 + super(MultiSimMaterialsTestHarness, self)._run_openmoc() + + +if __name__ == '__main__': + harness = MultiSimMaterialsTestHarness() + harness.main() diff --git a/tests/test_multisim_materials_cmfd/results_true.dat b/tests/test_multisim_materials_cmfd/results_true.dat new file mode 100644 index 000000000..df494db9f --- /dev/null +++ b/tests/test_multisim_materials_cmfd/results_true.dat @@ -0,0 +1,3 @@ +Iters: 7 keff: 7.52495E-01 +Iters: 7 keff: 7.52495E-01 +Iters: 7 keff: 7.52495E-01 diff --git a/tests/test_multisim_materials_cmfd/test_multisim_materials_cmfd.py b/tests/test_multisim_materials_cmfd/test_multisim_materials_cmfd.py new file mode 100644 index 000000000..16cf2e3a1 --- /dev/null +++ b/tests/test_multisim_materials_cmfd/test_multisim_materials_cmfd.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import GridInput +import openmoc + + +class MultiSimMaterialsCmfdTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation with different materials in + a grid geometry with CMFD.""" + + def __init__(self): + super(MultiSimMaterialsCmfdTestHarness, self).__init__() + self.input_set = GridInput() + + def _create_geometry(self): + """Initialize CMFD and add it to the Geometry.""" + + super(MultiSimMaterialsCmfdTestHarness, self)._create_geometry() + + # Initialize CMFD + cmfd = openmoc.Cmfd() + cmfd.setSORRelaxationFactor(1.5) + cmfd.setLatticeStructure(3,3) + + # Add CMFD to the Geometry + self.input_set.geometry.setCmfd(cmfd) + + def _run_openmoc(self): + """Run multiple OpenMOC eigenvalue calculations with CMFD with + different materials.""" + + for i in range(self.num_simulations): + + # Extract all of the material-filled cells in the geometry + cells = self.input_set.geometry.getAllMaterialCells() + materials = self.input_set.geometry.getAllMaterials() + + # Exchange all of the materials for their clones + for cell_id in cells: + material = cells[cell_id].getFillMaterial() + clone = material.clone() + cells[cell_id].setFill(clone) + + # Turn on SWIG flag to register old Materials + # with Python garbage collector + for material_id in materials: + materials[material_id].thisown = 1 + + # Run eigenvalue calculation and store the results + self.num_simulations = 1 + super(MultiSimMaterialsCmfdTestHarness, self)._run_openmoc() + + +if __name__ == '__main__': + harness = MultiSimMaterialsCmfdTestHarness() + harness.main() diff --git a/tests/test_multisim_num_azim/results_true.dat b/tests/test_multisim_num_azim/results_true.dat new file mode 100644 index 000000000..387c1bfdd --- /dev/null +++ b/tests/test_multisim_num_azim/results_true.dat @@ -0,0 +1,6 @@ +# tracks: 116 # segments: 196 +# tracks: 212 # segments: 404 +# tracks: 420 # segments: 812 +Iters: 13 keff: 8.48987E-01 +Iters: 229 keff: 1.04414E+00 +Iters: 228 keff: 1.04574E+00 diff --git a/tests/test_multisim_num_azim/test_multisim_num_azim.py b/tests/test_multisim_num_azim/test_multisim_num_azim.py new file mode 100644 index 000000000..e3fde658b --- /dev/null +++ b/tests/test_multisim_num_azim/test_multisim_num_azim.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import PinCellInput +import openmoc + + +class MultiSimNumAzimTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation with varying azimuthal angle + counts for a simple pin cell with 7-group C5G7 cross section data.""" + + def __init__(self): + super(MultiSimNumAzimTestHarness, self).__init__() + self.input_set = PinCellInput() + self.num_simulations = 1 + self.num_tracks = [] + self.num_segments = [] + + def _setup(self): + """Build materials, geometry and dummy track generator.""" + self._create_geometry() + self._create_trackgenerator() + self._create_solver() + + def _create_solver(self): + """Instantiate a CPUSolver.""" + self.solver = openmoc.CPUSolver() + self.solver.setNumThreads(self.num_threads) + self.solver.setConvergenceThreshold(self.tolerance) + + def _run_openmoc(self): + """Run multiple OpenMOC eigenvalue calculations.""" + + for num_azim in [4, 8, 16]: + + # Generate tracks + self.track_generator.setNumAzim(num_azim) + super(MultiSimNumAzimTestHarness, self)._generate_tracks() + + # Assign TrackGenerator to Solver and run eigenvalue calculation + self.solver.setTrackGenerator(self.track_generator) + super(MultiSimNumAzimTestHarness, self)._run_openmoc() + + # Store results + self.num_tracks.append(self.track_generator.getNumTracks()) + self.num_segments.append(self.track_generator.getNumSegments()) + + def _get_results(self, num_iters=True, keff=True, fluxes=False, + num_fsrs=False, num_tracks=True, num_segments=True, + hash_output=False): + """Return track and segment counts and eigenvalues from each + simulation as a string.""" + + outstr = '' + + # Write out the numbers of tracks and segments + for num_tracks, num_segments in zip(self.num_tracks, self.num_segments): + outstr += '# tracks: {0}\t'.format(num_tracks) + outstr += '# segments: {0}\n'.format(num_segments) + + # Write out the iteration count and eigenvalues from each simulation + for num_iters, keff in zip(self.num_iters, self.keffs): + outstr += 'Iters: {0}\tkeff: {1:12.5E}\n'.format(num_iters, keff) + + return outstr + + +if __name__ == '__main__': + harness = MultiSimNumAzimTestHarness() + harness.main() diff --git a/tests/test_multisim_num_groups/results_true.dat b/tests/test_multisim_num_groups/results_true.dat new file mode 100644 index 000000000..57facf4d8 --- /dev/null +++ b/tests/test_multisim_num_groups/results_true.dat @@ -0,0 +1,2 @@ +Iters: 80 keff: 1.43248E+00 +Iters: 88 keff: 1.72302E+00 diff --git a/tests/test_multisim_num_groups/test_multisim_num_groups.py b/tests/test_multisim_num_groups/test_multisim_num_groups.py new file mode 100644 index 000000000..aeaaea6ad --- /dev/null +++ b/tests/test_multisim_num_groups/test_multisim_num_groups.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +import os +import sys + +import numpy as np + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import HomInfMedInput +import openmoc + + +class MultiSimNumGroupsTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation for a homogeneous infinite + medium with 1-group and 2-group data.""" + + def __init__(self): + super(MultiSimNumGroupsTestHarness, self).__init__() + self.input_set = HomInfMedInput() + self.num_simulations = 1 + + def _run_openmoc(self): + """Run multiple OpenMOC eigenvalue calculations with 1- and 2-group + cross sections in a homogeneous infinite medium.""" + + # Extract infinite medium material from input set + material = self.input_set.materials['infinite medium'] + + # Setup 2-group multi-group cross sections + material.setName('1-group infinite medium') + material.setNumEnergyGroups(1) + material.setNuSigmaF(np.array([0.0994076580])) + material.setSigmaS(np.array([0.383259177])) + material.setChi(np.array([1.0])) + material.setSigmaT(np.array([0.452648699])) + + # Run eigenvalue calculation and store the results + super(MultiSimNumGroupsTestHarness, self)._run_openmoc() + + # Setup 2-group multi-group cross sections + material.setName('2-group infinite medium') + material.setNumEnergyGroups(2) + material.setNuSigmaF(np.array([0.0015, 0.325])) + material.setSigmaS(np.array([0.1, 0.117, 0., 1.42])) + material.setChi(np.array([1.0, 0.0])) + material.setSigmaT(np.array([0.2208, 1.604])) + + # Run eigenvalue calculation and store the results + super(MultiSimNumGroupsTestHarness, self)._run_openmoc() + + +if __name__ == '__main__': + harness = MultiSimNumGroupsTestHarness() + harness.main() diff --git a/tests/test_multisim_simple/results_true.dat b/tests/test_multisim_simple/results_true.dat new file mode 100644 index 000000000..779125e35 --- /dev/null +++ b/tests/test_multisim_simple/results_true.dat @@ -0,0 +1,3 @@ +Iters: 13 keff: 8.48987E-01 +Iters: 13 keff: 8.48987E-01 +Iters: 13 keff: 8.48987E-01 diff --git a/tests/test_multisim_simple/test_multisim_simple.py b/tests/test_multisim_simple/test_multisim_simple.py new file mode 100644 index 000000000..006ce56fc --- /dev/null +++ b/tests/test_multisim_simple/test_multisim_simple.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import MultiSimTestHarness +from input_set import PinCellInput +import openmoc + + +class MultiSimSimpleTestHarness(MultiSimTestHarness): + """A multi-simulation eigenvalue calculation for a pin cell problem + with C5G7 7-group cross section data.""" + + def __init__(self): + super(MultiSimSimpleTestHarness, self).__init__() + self.input_set = PinCellInput() + + +if __name__ == '__main__': + harness = MultiSimSimpleTestHarness() + harness.main() diff --git a/tests/test_plot_cells/test_plot_cells.py b/tests/test_plot_cells/test_plot_cells.py new file mode 100644 index 000000000..9401aad8f --- /dev/null +++ b/tests/test_plot_cells/test_plot_cells.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_cells + + +class PlotCellsTestHarness(PlottingTestHarness): + """Test cell plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotCellsTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Plot the cells in the geometry.""" + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.append( + plot_cells(self.input_set.geometry, gridsize=100, + get_figure=True)) + self.figures.append( + plot_cells(self.input_set.geometry, gridsize=100, + zcoord=10., get_figure=True)) + self.figures.append( + plot_cells(self.input_set.geometry, gridsize=100, + get_figure=True, xlim=(0., 2.), ylim=(0., 2.))) + self.figures.append( + plot_cells(self.input_set.geometry, gridsize=100, + get_figure=True, library='pil')) + + +if __name__ == '__main__': + harness = PlotCellsTestHarness() + harness.main() diff --git a/tests/test_plot_cells/true-0.png b/tests/test_plot_cells/true-0.png new file mode 100644 index 000000000..ad8256d44 Binary files /dev/null and b/tests/test_plot_cells/true-0.png differ diff --git a/tests/test_plot_cells/true-1.png b/tests/test_plot_cells/true-1.png new file mode 100644 index 000000000..f19c1917c Binary files /dev/null and b/tests/test_plot_cells/true-1.png differ diff --git a/tests/test_plot_cells/true-2.png b/tests/test_plot_cells/true-2.png new file mode 100644 index 000000000..11d2f1a87 Binary files /dev/null and b/tests/test_plot_cells/true-2.png differ diff --git a/tests/test_plot_cells/true-3.png b/tests/test_plot_cells/true-3.png new file mode 100644 index 000000000..2abfab087 Binary files /dev/null and b/tests/test_plot_cells/true-3.png differ diff --git a/tests/test_plot_cmfd_cells/test_plot_cmfd_cells.py b/tests/test_plot_cmfd_cells/test_plot_cmfd_cells.py new file mode 100644 index 000000000..564bc8910 --- /dev/null +++ b/tests/test_plot_cmfd_cells/test_plot_cmfd_cells.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import PwrAssemblyInput +import openmoc +from openmoc.plotter import plot_cmfd_cells + + +class PlotCmfdCellsTestHarness(PlottingTestHarness): + """Test CMFD cells plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotCmfdCellsTestHarness, self).__init__() + self.cmfd = None + self.input_set = PwrAssemblyInput() + + def _create_geometry(self): + """Initialize CMFD and add it to the Geometry.""" + + super(PlotCmfdCellsTestHarness, self)._create_geometry() + + # Initialize CMFD + self.cmfd = openmoc.Cmfd() + self.cmfd.setSORRelaxationFactor(1.5) + self.cmfd.setLatticeStructure(17,17) + self.cmfd.setGroupStructure([1,4,8]) + self.cmfd.setKNearest(3) + + # Add CMFD to the Geometry + self.input_set.geometry.setCmfd(self.cmfd) + + def _run_openmoc(self): + """Plot the flat source regions in the geometry.""" + + # Run an eigenvalue calculation to setup CMFD cells + super(PlotCmfdCellsTestHarness, self)._run_openmoc() + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.append( + plot_cmfd_cells(self.input_set.geometry, self.cmfd, + gridsize=100, get_figure=True)) + self.figures.append( + plot_cmfd_cells(self.input_set.geometry, self.cmfd, gridsize=100, + get_figure=True, xlim=(0., 2.), ylim=(0., 2.))) + self.figures.append( + plot_cmfd_cells(self.input_set.geometry, self.cmfd, gridsize=100, + get_figure=True, library='pil')) + + +if __name__ == '__main__': + harness = PlotCmfdCellsTestHarness() + harness.main() diff --git a/tests/test_plot_cmfd_cells/true-0.png b/tests/test_plot_cmfd_cells/true-0.png new file mode 100644 index 000000000..fc9b064a8 Binary files /dev/null and b/tests/test_plot_cmfd_cells/true-0.png differ diff --git a/tests/test_plot_cmfd_cells/true-1.png b/tests/test_plot_cmfd_cells/true-1.png new file mode 100644 index 000000000..d316ccce4 Binary files /dev/null and b/tests/test_plot_cmfd_cells/true-1.png differ diff --git a/tests/test_plot_cmfd_cells/true-2.png b/tests/test_plot_cmfd_cells/true-2.png new file mode 100644 index 000000000..131021225 Binary files /dev/null and b/tests/test_plot_cmfd_cells/true-2.png differ diff --git a/tests/test_plot_energy_fluxes/test_plot_energy_fluxes.py b/tests/test_plot_energy_fluxes/test_plot_energy_fluxes.py new file mode 100644 index 000000000..511a49f7c --- /dev/null +++ b/tests/test_plot_energy_fluxes/test_plot_energy_fluxes.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import PinCellInput +from openmoc.plotter import plot_energy_fluxes + + +class PlotEnergyFluxesTestHarness(PlottingTestHarness): + """Test spatial flux plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotEnergyFluxesTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Run OpenMOC and plot the spatial fluxes in the geometry.""" + + # Run an eigenvalue calculation + super(PlotEnergyFluxesTestHarness, self)._run_openmoc() + + # Extract the FSR count from the geometry + num_fsrs = self.input_set.geometry.getNumFSRs() + fsrs = tuple(range(num_fsrs)) + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.extend(plot_energy_fluxes(self.solver, fsrs, + get_figure=True)) + self.figures.extend(plot_energy_fluxes(self.solver, fsrs, + get_figure=True, loglog=True)) + + +if __name__ == '__main__': + harness = PlotEnergyFluxesTestHarness() + harness.main() diff --git a/tests/test_plot_energy_fluxes/true-0.png b/tests/test_plot_energy_fluxes/true-0.png new file mode 100644 index 000000000..70218c709 Binary files /dev/null and b/tests/test_plot_energy_fluxes/true-0.png differ diff --git a/tests/test_plot_energy_fluxes/true-1.png b/tests/test_plot_energy_fluxes/true-1.png new file mode 100644 index 000000000..ae37d4ebf Binary files /dev/null and b/tests/test_plot_energy_fluxes/true-1.png differ diff --git a/tests/test_plot_energy_fluxes/true-2.png b/tests/test_plot_energy_fluxes/true-2.png new file mode 100644 index 000000000..70218c709 Binary files /dev/null and b/tests/test_plot_energy_fluxes/true-2.png differ diff --git a/tests/test_plot_energy_fluxes/true-3.png b/tests/test_plot_energy_fluxes/true-3.png new file mode 100644 index 000000000..ae37d4ebf Binary files /dev/null and b/tests/test_plot_energy_fluxes/true-3.png differ diff --git a/tests/test_plot_fission_rates/test_plot_fission_rates.py b/tests/test_plot_fission_rates/test_plot_fission_rates.py new file mode 100644 index 000000000..858d9e736 --- /dev/null +++ b/tests/test_plot_fission_rates/test_plot_fission_rates.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_fission_rates + + +class PlotFissionRatesTestHarness(PlottingTestHarness): + """Test fission rate plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotFissionRatesTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Run OpenMOC and plot the fission rates in the geometry.""" + + # Run an eigenvalue calculation + super(PlotFissionRatesTestHarness, self)._run_openmoc() + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.append( + plot_fission_rates(self.solver, gridsize=100, + get_figure=True)) + self.figures.append( + plot_fission_rates(self.solver, gridsize=100, get_figure=True, + xlim=(0., 2.), ylim=(0., 2.))) + self.figures.append( + plot_fission_rates(self.solver, gridsize=100, get_figure=True, + norm=False, transparent_zeros=False)) + self.figures.append( + plot_fission_rates(self.solver, gridsize=100, get_figure=True, + library='pil')) + + +if __name__ == '__main__': + harness = PlotFissionRatesTestHarness() + harness.main() diff --git a/tests/test_plot_fission_rates/true-0.png b/tests/test_plot_fission_rates/true-0.png new file mode 100644 index 000000000..01ec0dc63 Binary files /dev/null and b/tests/test_plot_fission_rates/true-0.png differ diff --git a/tests/test_plot_fission_rates/true-1.png b/tests/test_plot_fission_rates/true-1.png new file mode 100644 index 000000000..968d6aacd Binary files /dev/null and b/tests/test_plot_fission_rates/true-1.png differ diff --git a/tests/test_plot_fission_rates/true-2.png b/tests/test_plot_fission_rates/true-2.png new file mode 100644 index 000000000..01ec0dc63 Binary files /dev/null and b/tests/test_plot_fission_rates/true-2.png differ diff --git a/tests/test_plot_fission_rates/true-3.png b/tests/test_plot_fission_rates/true-3.png new file mode 100644 index 000000000..978ba8c26 Binary files /dev/null and b/tests/test_plot_fission_rates/true-3.png differ diff --git a/tests/test_plot_fsrs/test_plot_fsrs.py b/tests/test_plot_fsrs/test_plot_fsrs.py new file mode 100644 index 000000000..5b0ba14cb --- /dev/null +++ b/tests/test_plot_fsrs/test_plot_fsrs.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_flat_source_regions + + +class PlotFSRsTestHarness(PlottingTestHarness): + """Test flat source region plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotFSRsTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Plot the flat source regions in the geometry.""" + + # Run an eigenvalue calculation to setup FSR centroids + super(PlotFSRsTestHarness, self)._run_openmoc() + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.append( + plot_flat_source_regions(self.input_set.geometry, gridsize=100, + get_figure=True)) + self.figures.append( + plot_flat_source_regions(self.input_set.geometry, gridsize=100, + get_figure=True, xlim=(0., 2.), ylim=(0., 2.))) + self.figures.append( + plot_flat_source_regions(self.input_set.geometry, gridsize=100, + get_figure=True, centroids=True, marker_size=3)) + self.figures.append( + plot_flat_source_regions(self.input_set.geometry, gridsize=100, + get_figure=True, centroids=True, library='pil')) + + +if __name__ == '__main__': + harness = PlotFSRsTestHarness() + harness.main() diff --git a/tests/test_plot_fsrs/true-0.png b/tests/test_plot_fsrs/true-0.png new file mode 100644 index 000000000..b9db7afe6 Binary files /dev/null and b/tests/test_plot_fsrs/true-0.png differ diff --git a/tests/test_plot_fsrs/true-1.png b/tests/test_plot_fsrs/true-1.png new file mode 100644 index 000000000..934b12bdd Binary files /dev/null and b/tests/test_plot_fsrs/true-1.png differ diff --git a/tests/test_plot_fsrs/true-2.png b/tests/test_plot_fsrs/true-2.png new file mode 100644 index 000000000..a8a3182f0 Binary files /dev/null and b/tests/test_plot_fsrs/true-2.png differ diff --git a/tests/test_plot_fsrs/true-3.png b/tests/test_plot_fsrs/true-3.png new file mode 100644 index 000000000..7a6585b87 Binary files /dev/null and b/tests/test_plot_fsrs/true-3.png differ diff --git a/tests/test_plot_materials/test_plot_materials.py b/tests/test_plot_materials/test_plot_materials.py new file mode 100644 index 000000000..f823ec459 --- /dev/null +++ b/tests/test_plot_materials/test_plot_materials.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_materials + + +class PlotMaterialsTestHarness(PlottingTestHarness): + """Test material plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotMaterialsTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Plot the materials in the geometry.""" + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.append( + plot_materials(self.input_set.geometry, gridsize=100, + get_figure=True)) + self.figures.append( + plot_materials(self.input_set.geometry, gridsize=100, + zcoord=10., get_figure=True)) + self.figures.append( + plot_materials(self.input_set.geometry, gridsize=100, + get_figure=True, xlim=(0., 2.), ylim=(0., 2.))) + self.figures.append( + plot_materials(self.input_set.geometry, gridsize=100, + get_figure=True, library='pil')) + + +if __name__ == '__main__': + harness = PlotMaterialsTestHarness() + harness.main() diff --git a/tests/test_plot_materials/true-0.png b/tests/test_plot_materials/true-0.png new file mode 100644 index 000000000..a51054472 Binary files /dev/null and b/tests/test_plot_materials/true-0.png differ diff --git a/tests/test_plot_materials/true-1.png b/tests/test_plot_materials/true-1.png new file mode 100644 index 000000000..076f94538 Binary files /dev/null and b/tests/test_plot_materials/true-1.png differ diff --git a/tests/test_plot_materials/true-2.png b/tests/test_plot_materials/true-2.png new file mode 100644 index 000000000..7b311771f Binary files /dev/null and b/tests/test_plot_materials/true-2.png differ diff --git a/tests/test_plot_materials/true-3.png b/tests/test_plot_materials/true-3.png new file mode 100644 index 000000000..c1abf599f Binary files /dev/null and b/tests/test_plot_materials/true-3.png differ diff --git a/tests/test_plot_quadrature/test_plot_quadrature.py b/tests/test_plot_quadrature/test_plot_quadrature.py new file mode 100644 index 000000000..b7e4fb3c6 --- /dev/null +++ b/tests/test_plot_quadrature/test_plot_quadrature.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import PinCellInput +from openmoc.plotter import plot_quadrature + + +class PlotQuadratureTestHarness(PlottingTestHarness): + """Test quadrature plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotQuadratureTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Plot the polar quadrature.""" + + # Run an eigenvalue calculation to setup polar quadrature + super(PlotQuadratureTestHarness, self)._run_openmoc() + + # Create Matplotlib Figures for the polar quadrature + self.figures = [plot_quadrature(self.solver, get_figure=True)] + + +if __name__ == '__main__': + harness = PlotQuadratureTestHarness() + harness.main() diff --git a/tests/test_plot_quadrature/true-0.png b/tests/test_plot_quadrature/true-0.png new file mode 100644 index 000000000..d1bbcc503 Binary files /dev/null and b/tests/test_plot_quadrature/true-0.png differ diff --git a/tests/test_plot_segments/test_plot_segments.py b/tests/test_plot_segments/test_plot_segments.py new file mode 100644 index 000000000..edd989369 --- /dev/null +++ b/tests/test_plot_segments/test_plot_segments.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import PinCellInput +from openmoc.plotter import plot_segments + + +class PlotSegmentsTestHarness(PlottingTestHarness): + """Test segment plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotSegmentsTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Plot the tracks.""" + + # Run an eigenvalue calculation to setup track generator + super(PlotSegmentsTestHarness, self)._run_openmoc() + + # Create Matplotlib Figures for the tracks + self.figures = [plot_segments(self.track_generator, get_figure=True)] + + +if __name__ == '__main__': + harness = PlotSegmentsTestHarness() + harness.main() diff --git a/tests/test_plot_segments/true-0.png b/tests/test_plot_segments/true-0.png new file mode 100644 index 000000000..ed978494a Binary files /dev/null and b/tests/test_plot_segments/true-0.png differ diff --git a/tests/test_plot_spatial_data/test_plot_spatial_data.py b/tests/test_plot_spatial_data/test_plot_spatial_data.py new file mode 100644 index 000000000..58960f930 --- /dev/null +++ b/tests/test_plot_spatial_data/test_plot_spatial_data.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +import os +import sys + +import pandas as pd +import numpy as np + +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_spatial_data, PlotParams + + +class PlotSpatialDataTestHarness(PlottingTestHarness): + """Test general spatial data plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotSpatialDataTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Plot spatial data from Pandas DataFrames.""" + + # Run an eigenvalue calculation to setup FSR centroids + super(PlotSpatialDataTestHarness, self)._run_openmoc() + + # Seed NumPy's random number generator to ensure reproducible results + np.random.seed(1) + + # Initialize a Pandas DataFrame with normally distributed random data + num_fsrs = self.input_set.geometry.getNumFSRs() + df = pd.DataFrame(np.random.randn(num_fsrs,3), columns=list('ABC')) + + # Initialize a PlotParams object + plot_params = PlotParams() + plot_params.geometry = self.input_set.geometry + plot_params.suptitle = 'Pandas DataFrame' + plot_params.filename = 'pandas-df' + plot_params.colorbar = True + + # Enforce consistent color scheme across figures + plot_params.vmin = df.values.min() + plot_params.vmax = df.values.max() + + # Create a series Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.extend(plot_spatial_data(df, plot_params, get_figure=True)) + + plot_params.library = 'pil' + self.figures.extend(plot_spatial_data(df, plot_params, get_figure=True)) + +if __name__ == '__main__': + harness = PlotSpatialDataTestHarness() + harness.main() diff --git a/tests/test_plot_spatial_data/true-0.png b/tests/test_plot_spatial_data/true-0.png new file mode 100644 index 000000000..658c0febf Binary files /dev/null and b/tests/test_plot_spatial_data/true-0.png differ diff --git a/tests/test_plot_spatial_data/true-1.png b/tests/test_plot_spatial_data/true-1.png new file mode 100644 index 000000000..ffc05c247 Binary files /dev/null and b/tests/test_plot_spatial_data/true-1.png differ diff --git a/tests/test_plot_spatial_data/true-2.png b/tests/test_plot_spatial_data/true-2.png new file mode 100644 index 000000000..2c8bd8be9 Binary files /dev/null and b/tests/test_plot_spatial_data/true-2.png differ diff --git a/tests/test_plot_spatial_data/true-3.png b/tests/test_plot_spatial_data/true-3.png new file mode 100644 index 000000000..e764f4ce7 Binary files /dev/null and b/tests/test_plot_spatial_data/true-3.png differ diff --git a/tests/test_plot_spatial_data/true-4.png b/tests/test_plot_spatial_data/true-4.png new file mode 100644 index 000000000..ad6532169 Binary files /dev/null and b/tests/test_plot_spatial_data/true-4.png differ diff --git a/tests/test_plot_spatial_data/true-5.png b/tests/test_plot_spatial_data/true-5.png new file mode 100644 index 000000000..f62a5bd1b Binary files /dev/null and b/tests/test_plot_spatial_data/true-5.png differ diff --git a/tests/test_plot_spatial_fluxes/test_plot_spatial_fluxes.py b/tests/test_plot_spatial_fluxes/test_plot_spatial_fluxes.py new file mode 100644 index 000000000..a32827794 --- /dev/null +++ b/tests/test_plot_spatial_fluxes/test_plot_spatial_fluxes.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import SimpleLatticeInput +from openmoc.plotter import plot_spatial_fluxes + + +class PlotSpatialFluxesTestHarness(PlottingTestHarness): + """Test spatial flux plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotSpatialFluxesTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Run OpenMOC and plot the spatial fluxes in the geometry.""" + + # Run an eigenvalue calculation + super(PlotSpatialFluxesTestHarness, self)._run_openmoc() + + # Specify energy groups for which to plot the spatial flux + energy_groups = [1, 3, 5, 7] + + # Create a series of Matplotlib Figures / PIL Images for different + # plotting parameters and append to figures list + self.figures.extend( + plot_spatial_fluxes(self.solver, gridsize=100, + get_figure=True, energy_groups=energy_groups)) + self.figures.extend( + plot_spatial_fluxes(self.solver, gridsize=100, get_figure=True, + xlim=(0., 2.), ylim=(0., 2.), + energy_groups=energy_groups)) + self.figures.extend( + plot_spatial_fluxes(self.solver, gridsize=100, get_figure=True, + energy_groups=energy_groups, library='pil')) + + +if __name__ == '__main__': + harness = PlotSpatialFluxesTestHarness() + harness.main() diff --git a/tests/test_plot_spatial_fluxes/true-0.png b/tests/test_plot_spatial_fluxes/true-0.png new file mode 100644 index 000000000..57e0d079d Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-0.png differ diff --git a/tests/test_plot_spatial_fluxes/true-1.png b/tests/test_plot_spatial_fluxes/true-1.png new file mode 100644 index 000000000..9a6a2b76b Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-1.png differ diff --git a/tests/test_plot_spatial_fluxes/true-10.png b/tests/test_plot_spatial_fluxes/true-10.png new file mode 100644 index 000000000..d52e8a66e Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-10.png differ diff --git a/tests/test_plot_spatial_fluxes/true-11.png b/tests/test_plot_spatial_fluxes/true-11.png new file mode 100644 index 000000000..f2eca4e36 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-11.png differ diff --git a/tests/test_plot_spatial_fluxes/true-2.png b/tests/test_plot_spatial_fluxes/true-2.png new file mode 100644 index 000000000..b61af97f9 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-2.png differ diff --git a/tests/test_plot_spatial_fluxes/true-3.png b/tests/test_plot_spatial_fluxes/true-3.png new file mode 100644 index 000000000..79f3f4400 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-3.png differ diff --git a/tests/test_plot_spatial_fluxes/true-4.png b/tests/test_plot_spatial_fluxes/true-4.png new file mode 100644 index 000000000..5388338bf Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-4.png differ diff --git a/tests/test_plot_spatial_fluxes/true-5.png b/tests/test_plot_spatial_fluxes/true-5.png new file mode 100644 index 000000000..95b5fc056 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-5.png differ diff --git a/tests/test_plot_spatial_fluxes/true-6.png b/tests/test_plot_spatial_fluxes/true-6.png new file mode 100644 index 000000000..d2eb613b5 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-6.png differ diff --git a/tests/test_plot_spatial_fluxes/true-7.png b/tests/test_plot_spatial_fluxes/true-7.png new file mode 100644 index 000000000..8b6e0ecb1 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-7.png differ diff --git a/tests/test_plot_spatial_fluxes/true-8.png b/tests/test_plot_spatial_fluxes/true-8.png new file mode 100644 index 000000000..c7be5ee77 Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-8.png differ diff --git a/tests/test_plot_spatial_fluxes/true-9.png b/tests/test_plot_spatial_fluxes/true-9.png new file mode 100644 index 000000000..55f5577ae Binary files /dev/null and b/tests/test_plot_spatial_fluxes/true-9.png differ diff --git a/tests/test_plot_tracks/test_plot_tracks.py b/tests/test_plot_tracks/test_plot_tracks.py new file mode 100644 index 000000000..841c8583c --- /dev/null +++ b/tests/test_plot_tracks/test_plot_tracks.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import PlottingTestHarness +from input_set import PinCellInput +from openmoc.plotter import plot_tracks + + +class PlotTracksTestHarness(PlottingTestHarness): + """Test track plotting with a 4x4 lattice.""" + + def __init__(self): + super(PlotTracksTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Plot the tracks.""" + + # Run an eigenvalue calculation to setup track generator + super(PlotTracksTestHarness, self)._run_openmoc() + + # Create Matplotlib Figures for the tracks + self.figures = [plot_tracks(self.track_generator, get_figure=True)] + + +if __name__ == '__main__': + harness = PlotTracksTestHarness() + harness.main() diff --git a/tests/test_plot_tracks/true-0.png b/tests/test_plot_tracks/true-0.png new file mode 100644 index 000000000..e3d375340 Binary files /dev/null and b/tests/test_plot_tracks/true-0.png differ diff --git a/tests/test_rings/results_true.dat b/tests/test_rings/results_true.dat new file mode 100644 index 000000000..2884c1cd4 --- /dev/null +++ b/tests/test_rings/results_true.dat @@ -0,0 +1,3 @@ +# FSRs: 8 +# tracks: 116 +# segments: 700 diff --git a/tests/test_rings/test_rings.py b/tests/test_rings/test_rings.py new file mode 100644 index 000000000..a1d881f0b --- /dev/null +++ b/tests/test_rings/test_rings.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput + + +class RingTestHarness(TestHarness): + """Tests cell radial discretization.""" + + def __init__(self): + super(RingTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _create_geometry(self): + """Discretize fuel and moderator into rings.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Create different rings for each Cell + cells = self.input_set.geometry.getAllMaterialCells() + for i, cell_id in enumerate(cells): + cells[cell_id].setNumRings(i*2 + 3) + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=True, num_segments=True, num_tracks=True, + hash_output=False): + """Digest info from geometry and return as a string.""" + + return super(RingTestHarness, self)._get_results( + num_iters=num_iters, keff=keff, fluxes=fluxes, + num_fsrs=num_fsrs, num_segments=num_segments, + num_tracks=num_tracks, hash_output=hash_output) + + +if __name__ == '__main__': + harness = RingTestHarness() + harness.main() diff --git a/tests/test_sectors/results_true.dat b/tests/test_sectors/results_true.dat new file mode 100644 index 000000000..838e06d3f --- /dev/null +++ b/tests/test_sectors/results_true.dat @@ -0,0 +1,3 @@ +# FSRs: 8 +# tracks: 116 +# segments: 315 diff --git a/tests/test_sectors/test_sectors.py b/tests/test_sectors/test_sectors.py new file mode 100644 index 000000000..d3eb59612 --- /dev/null +++ b/tests/test_sectors/test_sectors.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput + + +class SectorTestHarness(TestHarness): + """Tests cell angular discretization.""" + + def __init__(self): + super(SectorTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _create_geometry(self): + """Discretize fuel and moderator into sectors.""" + + self.input_set.create_materials() + self.input_set.create_geometry() + + # Create different sectors for each Cell + cells = self.input_set.geometry.getAllMaterialCells() + for i, cell_id in enumerate(cells): + cells[cell_id].setNumSectors(i*2 + 3) + + self._create_trackgenerator() + self._generate_tracks() + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=True, num_segments=True, num_tracks=True, + hash_output=False): + """Digest info from geometry and return as a string.""" + + return super(SectorTestHarness, self)._get_results( + num_iters=num_iters, keff=keff, fluxes=fluxes, + num_fsrs=num_fsrs, num_segments=num_segments, + num_tracks=num_tracks, hash_output=hash_output) + + +if __name__ == '__main__': + harness = SectorTestHarness() + harness.main() diff --git a/tests/test_simulation_state/results_true.dat b/tests/test_simulation_state/results_true.dat new file mode 100644 index 000000000..0c891ae8e --- /dev/null +++ b/tests/test_simulation_state/results_true.dat @@ -0,0 +1 @@ +83f6bafec5a50daa037039be04f797132e74db3128f283b697381fc7f65787646846e05da3cfb4bedf6f74efe69437e62548bbad6e37fdcff1d72c36ef501a34 \ No newline at end of file diff --git a/tests/test_simulation_state/test_simulation_state.py b/tests/test_simulation_state/test_simulation_state.py new file mode 100644 index 000000000..da9084431 --- /dev/null +++ b/tests/test_simulation_state/test_simulation_state.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +import os +import sys +import hashlib +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import SimpleLatticeInput +import openmoc.process as process +import numpy as np + + +class SimulationStateTestHarness(TestHarness): + """An eigenvalue calculation with storage and retrieval of the simulation + state using the openmoc.process module.""" + + def __init__(self): + super(SimulationStateTestHarness, self).__init__() + self.input_set = SimpleLatticeInput() + + def _run_openmoc(self): + """Run an eigenvalue calculation and store the simulation state.""" + super(SimulationStateTestHarness, self)._run_openmoc() + + # Store the simulatiation state in HDF5 and pickled binary files + process.store_simulation_state(self.solver, append=False, fluxes=True, + sources=True, use_hdf5=True) + process.store_simulation_state(self.solver, append=False, fluxes=True, + sources=True, use_hdf5=False) + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=True, num_tracks=True, num_segments=True, + hash_output=True): + """Digest info in the simulation states and return hash as a string.""" + + # Restore simulation state from pickled binary file + pkl_state = \ + process.restore_simulation_state(filename='simulation-state.pkl') + hdf5_state = \ + process.restore_simulation_state(filename='simulation-state.h5') + + # Add key, value pairs from pickled simulation state to ouptut string + outstr = 'HDF5 Simulation State\n' + for key1 in sorted(hdf5_state): + for key2 in sorted(hdf5_state[key1]): + for key3 in sorted(hdf5_state[key1][key2]): + value = hdf5_state[key1][key2][key3] + + # Ignore runtime since it changes for each run + if 'time' in key3: + continue + # Ignore thread counts for sequential/parallel runs + if 'threads' in key3: + continue + + # Create a list of the floating point flux values + if isinstance(value, np.ndarray): + outstr += '{0}: '.format(key3) + values = \ + ['{0:12.6E}'.format(val) for val in value.ravel()] + outstr += '\n'.join(values) + '\n' + elif isinstance(value, float): + outstr += '{0}:\t{1:.10f}\n'.format(key3, value) + else: + outstr += '{0}:\t{1}\n'.format(key3, value) + + # Add key, value pairs from HDF5 simulation state to ouptut string + outstr += 'Pickle Simulation State\n' + for key1 in sorted(pkl_state): + for key2 in sorted(pkl_state[key1]): + for key3 in sorted(pkl_state[key1][key2]): + value = pkl_state[key1][key2][key3] + + # Ignore runtime since it changes for each run + if 'time' in key3: + continue + # Ignore thread counts for sequential/parallel runs + if 'threads' in key3: + continue + + # Create a list of the floating point flux values + if isinstance(value, np.ndarray): + outstr += '{0}: '.format(key3) + values = \ + ['{0:12.6E}'.format(val) for val in value.ravel()] + outstr += '\n'.join(values) + '\n' + elif isinstance(value, float): + outstr += '{0}:\t{1:.10f}\n'.format(key3, value) + else: + outstr += '{0}:\t{1}\n'.format(key3, value) + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + +if __name__ == '__main__': + harness = SimulationStateTestHarness() + harness.main() diff --git a/tests/test_split_segments/results_true.dat b/tests/test_split_segments/results_true.dat new file mode 100644 index 000000000..5c41e627a --- /dev/null +++ b/tests/test_split_segments/results_true.dat @@ -0,0 +1,2 @@ +# Iterations: 13 +# segments: 1560 diff --git a/tests/test_split_segments/test_split_segments.py b/tests/test_split_segments/test_split_segments.py new file mode 100644 index 000000000..32f55fbf5 --- /dev/null +++ b/tests/test_split_segments/test_split_segments.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput + + +class SplitSegmentsTestHarness(TestHarness): + """Test segment splitting based on max optical path length.""" + + def __init__(self): + super(SplitSegmentsTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _run_openmoc(self): + """Set a small max optical path length to ensure segments are split.""" + + # Set a small max optical path length so segments are split + self.solver.setMaxOpticalLength(0.5) + + super(SplitSegmentsTestHarness, self)._run_openmoc() + + def _get_results(self): + """Digest info in the results and return as a string.""" + return super(SplitSegmentsTestHarness, self).\ + _get_results(num_segments=True, fluxes=False, keff=False) + + +if __name__ == '__main__': + harness = SplitSegmentsTestHarness() + harness.main() diff --git a/tests/test_split_segments_cmfd/results_true.dat b/tests/test_split_segments_cmfd/results_true.dat new file mode 100644 index 000000000..5c48209c0 --- /dev/null +++ b/tests/test_split_segments_cmfd/results_true.dat @@ -0,0 +1,2 @@ +# Iterations: 25 +# segments: 1616 diff --git a/tests/test_split_segments_cmfd/test_split_segments_cmfd.py b/tests/test_split_segments_cmfd/test_split_segments_cmfd.py new file mode 100644 index 000000000..591a231a4 --- /dev/null +++ b/tests/test_split_segments_cmfd/test_split_segments_cmfd.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import os +import sys +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TestHarness +from input_set import PinCellInput +import openmoc + +class SplitSegmentsCMFDTestHarness(TestHarness): + """Test segment splitting based on max optical path length with + CMFD turned on.""" + + def __init__(self): + super(SplitSegmentsCMFDTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _setup(self): + """Build materials, geometry, CMFD, and perform ray tracing.""" + self._create_geometry() + self._create_trackgenerator() + + # Overlay simple CMFD mesh + cmfd = openmoc.Cmfd() + cmfd.setLatticeStructure(2, 2) + self.input_set.geometry.setCmfd(cmfd) + + self._generate_tracks() + self._create_solver() + + def _run_openmoc(self): + """Set a small max optical path length to ensure segments are split.""" + + # Set a small max optical path length so segments are split + self.solver.setMaxOpticalLength(0.5) + + super(SplitSegmentsCMFDTestHarness, self)._run_openmoc() + + def _get_results(self): + """Digest info in the results and return as a string.""" + return super(SplitSegmentsCMFDTestHarness, self).\ + _get_results(num_segments=True, fluxes=False, keff=False) + + +if __name__ == '__main__': + harness = SplitSegmentsCMFDTestHarness() + harness.main() diff --git a/tests/test_tracking_grid/results_true.dat b/tests/test_tracking_grid/results_true.dat new file mode 100644 index 000000000..5d7d065a9 --- /dev/null +++ b/tests/test_tracking_grid/results_true.dat @@ -0,0 +1,22 @@ +Diagonal Track 3 +0: 2.82842712, 0, -1, -1, Water, 10083 +1: 2.82842712, 1, -1, -1, UO2, 49930 +2: 2.82842712, 2, -1, -1, Water, 10083 +Nudged Diagonal Track 5 +0: 2.82841298, 0, -1, -1, Water, 10083 +1: 1.414e-05, 3, -1, -1, Water, 10083 +2: 2.82841298, 1, -1, -1, UO2, 49930 +3: 1.414e-05, 4, -1, -1, Water, 10083 +4: 2.82841298, 2, -1, -1, Water, 10083 +Horizontal Track 3 +0: 2.0, 5, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 2.0, 4, -1, -1, Water, 10083 +Vertical Track 3 +0: 2.0, 3, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 2.0, 6, -1, -1, Water, 10083 +Reverse Diagonal Track 3 +0: 2.82842712, 2, -1, -1, Water, 10083 +1: 2.82842712, 1, -1, -1, UO2, 49930 +2: 2.82842712, 0, -1, -1, Water, 10083 diff --git a/tests/test_tracking_grid/test_tracking_grid.py b/tests/test_tracking_grid/test_tracking_grid.py new file mode 100644 index 000000000..3b3f03ab4 --- /dev/null +++ b/tests/test_tracking_grid/test_tracking_grid.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import GridInput + +import openmoc + +class TrackingGridTestHarness(TrackingTestHarness): + """Tests tracking over a grid geometry.""" + + def __init__(self): + super(TrackingGridTestHarness, self).__init__() + self.input_set = GridInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks.""" + super(TrackingGridTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Nudged Diagonal Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-3, -3, 0, 3, 3, 0,\ + math.atan(1)) + nudge = 1e-5 + self.tracks['Nudged Diagonal Track'].setValues(-3+nudge, -3, 0, 3,\ + 3-nudge, 0,\ + math.atan(1)) + self.tracks['Horizontal Track'].setValues(-3, 0, 0, 3, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -3, 0, 0, 3, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(3, 3, 0, -3, -3, 0,\ + math.pi + math.atan(1)) + +if __name__ == '__main__': + harness = TrackingGridTestHarness() + harness.main() diff --git a/tests/test_tracking_grid_cmfd/results_true.dat b/tests/test_tracking_grid_cmfd/results_true.dat new file mode 100644 index 000000000..895a0ad7f --- /dev/null +++ b/tests/test_tracking_grid_cmfd/results_true.dat @@ -0,0 +1,334 @@ +3 x 3 CMFD mesh +Diagonal Track 3 +0: 2.82842712, 0, 6, 4, Water, 10083 +1: 2.82842712, 1, 38, 36, UO2, 49930 +2: 2.82842712, 2, 70, 68, Water, 10083 +Nudged Diagonal Track 5 +0: 2.82841298, 0, 2, 1, Water, 10083 +1: 1.414e-05, 3, 11, 8, Water, 10083 +2: 2.82841298, 1, 34, 33, UO2, 49930 +3: 1.414e-05, 4, 43, 40, Water, 10083 +4: 2.82841298, 2, 66, 65, Water, 10083 +Horizontal Track 3 +0: 2.0, 5, 26, 24, Water, 10083 +1: 2.0, 1, 34, 32, UO2, 49930 +2: 2.0, 4, 42, 40, Water, 10083 +Vertical Track 3 +0: 2.0, 3, 11, 9, Water, 10083 +1: 2.0, 1, 35, 33, UO2, 49930 +2: 2.0, 6, 59, 57, Water, 10083 +Reverse Diagonal Track 3 +0: 2.82842712, 2, 68, 70, Water, 10083 +1: 2.82842712, 1, 36, 38, UO2, 49930 +2: 2.82842712, 0, 4, 6, Water, 10083 +51 x 51 CMFD mesh +Diagonal Track 51 +0: 0.16637807, 0, 6, 4, Water, 10083 +1: 0.16637807, 7, 422, 420, Water, 10083 +2: 0.16637807, 8, 838, 836, Water, 10083 +3: 0.16637807, 9, 1254, 1252, Water, 10083 +4: 0.16637807, 10, 1670, 1668, Water, 10083 +5: 0.16637807, 11, 2086, 2084, Water, 10083 +6: 0.16637807, 12, 2502, 2500, Water, 10083 +7: 0.16637807, 13, 2918, 2916, Water, 10083 +8: 0.16637807, 14, 3334, 3332, Water, 10083 +9: 0.16637807, 15, 3750, 3748, Water, 10083 +10: 0.16637807, 16, 4166, 4164, Water, 10083 +11: 0.16637807, 17, 4582, 4580, Water, 10083 +12: 0.16637807, 18, 4998, 4996, Water, 10083 +13: 0.16637807, 19, 5414, 5412, Water, 10083 +14: 0.16637807, 20, 5830, 5828, Water, 10083 +15: 0.16637807, 21, 6246, 6244, Water, 10083 +16: 0.16637807, 22, 6662, 6660, Water, 10083 +17: 0.16637807, 23, 7078, 7076, UO2, 49930 +18: 0.16637807, 24, 7494, 7492, UO2, 49930 +19: 0.16637807, 25, 7910, 7908, UO2, 49930 +20: 0.16637807, 26, 8326, 8324, UO2, 49930 +21: 0.16637807, 27, 8742, 8740, UO2, 49930 +22: 0.16637807, 28, 9158, 9156, UO2, 49930 +23: 0.16637807, 29, 9574, 9572, UO2, 49930 +24: 0.16637807, 30, 9990, 9988, UO2, 49930 +25: 0.16637807, 31, 10406, 10404, UO2, 49930 +26: 0.16637807, 32, 10822, 10820, UO2, 49930 +27: 0.16637807, 33, 11238, 11236, UO2, 49930 +28: 0.16637807, 34, 11654, 11652, UO2, 49930 +29: 0.16637807, 35, 12070, 12068, UO2, 49930 +30: 0.16637807, 36, 12486, 12484, UO2, 49930 +31: 0.16637807, 37, 12902, 12900, UO2, 49930 +32: 0.16637807, 38, 13318, 13316, UO2, 49930 +33: 0.16637807, 39, 13734, 13732, UO2, 49930 +34: 0.16637807, 40, 14150, 14148, Water, 10083 +35: 0.16637807, 41, 14566, 14564, Water, 10083 +36: 0.16637807, 42, 14982, 14980, Water, 10083 +37: 0.16637807, 43, 15398, 15396, Water, 10083 +38: 0.16637807, 44, 15814, 15812, Water, 10083 +39: 0.16637807, 45, 16230, 16228, Water, 10083 +40: 0.16637807, 46, 16646, 16644, Water, 10083 +41: 0.16637807, 47, 17062, 17060, Water, 10083 +42: 0.16637807, 48, 17478, 17476, Water, 10083 +43: 0.16637807, 49, 17894, 17892, Water, 10083 +44: 0.16637807, 50, 18310, 18308, Water, 10083 +45: 0.16637807, 51, 18726, 18724, Water, 10083 +46: 0.16637807, 52, 19142, 19140, Water, 10083 +47: 0.16637807, 53, 19558, 19556, Water, 10083 +48: 0.16637807, 54, 19974, 19972, Water, 10083 +49: 0.16637807, 55, 20390, 20388, Water, 10083 +50: 0.16637807, 56, 20806, 20804, Water, 10083 +Nudged Diagonal Track 101 +0: 0.16636392, 0, 2, 1, Water, 10083 +1: 1.414e-05, 57, 11, 8, Water, 10083 +2: 0.16636392, 7, 418, 417, Water, 10083 +3: 1.414e-05, 58, 427, 424, Water, 10083 +4: 0.16636392, 8, 834, 833, Water, 10083 +5: 1.414e-05, 59, 843, 840, Water, 10083 +6: 0.16636392, 9, 1250, 1249, Water, 10083 +7: 1.414e-05, 60, 1259, 1256, Water, 10083 +8: 0.16636392, 10, 1666, 1665, Water, 10083 +9: 1.414e-05, 61, 1675, 1672, Water, 10083 +10: 0.16636392, 11, 2082, 2081, Water, 10083 +11: 1.414e-05, 62, 2091, 2088, Water, 10083 +12: 0.16636392, 12, 2498, 2497, Water, 10083 +13: 1.414e-05, 63, 2507, 2504, Water, 10083 +14: 0.16636392, 13, 2914, 2913, Water, 10083 +15: 1.414e-05, 64, 2923, 2920, Water, 10083 +16: 0.16636392, 14, 3330, 3329, Water, 10083 +17: 1.414e-05, 65, 3339, 3336, Water, 10083 +18: 0.16636392, 15, 3746, 3745, Water, 10083 +19: 1.414e-05, 66, 3755, 3752, Water, 10083 +20: 0.16636392, 16, 4162, 4161, Water, 10083 +21: 1.414e-05, 67, 4171, 4168, Water, 10083 +22: 0.16636392, 17, 4578, 4577, Water, 10083 +23: 1.414e-05, 68, 4587, 4584, Water, 10083 +24: 0.16636392, 18, 4994, 4993, Water, 10083 +25: 1.414e-05, 69, 5003, 5000, Water, 10083 +26: 0.16636392, 19, 5410, 5409, Water, 10083 +27: 1.414e-05, 70, 5419, 5416, Water, 10083 +28: 0.16636392, 20, 5826, 5825, Water, 10083 +29: 1.414e-05, 71, 5835, 5832, Water, 10083 +30: 0.16636392, 21, 6242, 6241, Water, 10083 +31: 1.414e-05, 72, 6251, 6248, Water, 10083 +32: 0.16636392, 22, 6658, 6657, Water, 10083 +33: 1.414e-05, 73, 6667, 6664, Water, 10083 +34: 0.16636392, 23, 7074, 7073, UO2, 49930 +35: 1.414e-05, 74, 7083, 7080, UO2, 49930 +36: 0.16636392, 24, 7490, 7489, UO2, 49930 +37: 1.414e-05, 75, 7499, 7496, UO2, 49930 +38: 0.16636392, 25, 7906, 7905, UO2, 49930 +39: 1.414e-05, 76, 7915, 7912, UO2, 49930 +40: 0.16636392, 26, 8322, 8321, UO2, 49930 +41: 1.414e-05, 77, 8331, 8328, UO2, 49930 +42: 0.16636392, 27, 8738, 8737, UO2, 49930 +43: 1.414e-05, 78, 8747, 8744, UO2, 49930 +44: 0.16636392, 28, 9154, 9153, UO2, 49930 +45: 1.414e-05, 79, 9163, 9160, UO2, 49930 +46: 0.16636392, 29, 9570, 9569, UO2, 49930 +47: 1.414e-05, 80, 9579, 9576, UO2, 49930 +48: 0.16636392, 30, 9986, 9985, UO2, 49930 +49: 1.414e-05, 81, 9995, 9992, UO2, 49930 +50: 0.16636392, 31, 10402, 10401, UO2, 49930 +51: 1.414e-05, 82, 10411, 10408, UO2, 49930 +52: 0.16636392, 32, 10818, 10817, UO2, 49930 +53: 1.414e-05, 83, 10827, 10824, UO2, 49930 +54: 0.16636392, 33, 11234, 11233, UO2, 49930 +55: 1.414e-05, 84, 11243, 11240, UO2, 49930 +56: 0.16636392, 34, 11650, 11649, UO2, 49930 +57: 1.414e-05, 85, 11659, 11656, UO2, 49930 +58: 0.16636392, 35, 12066, 12065, UO2, 49930 +59: 1.414e-05, 86, 12075, 12072, UO2, 49930 +60: 0.16636392, 36, 12482, 12481, UO2, 49930 +61: 1.414e-05, 87, 12491, 12488, UO2, 49930 +62: 0.16636392, 37, 12898, 12897, UO2, 49930 +63: 1.414e-05, 88, 12907, 12904, UO2, 49930 +64: 0.16636392, 38, 13314, 13313, UO2, 49930 +65: 1.414e-05, 89, 13323, 13320, UO2, 49930 +66: 0.16636392, 39, 13730, 13729, UO2, 49930 +67: 1.414e-05, 90, 13739, 13736, Water, 10083 +68: 0.16636392, 40, 14146, 14145, Water, 10083 +69: 1.414e-05, 91, 14155, 14152, Water, 10083 +70: 0.16636392, 41, 14562, 14561, Water, 10083 +71: 1.414e-05, 92, 14571, 14568, Water, 10083 +72: 0.16636392, 42, 14978, 14977, Water, 10083 +73: 1.414e-05, 93, 14987, 14984, Water, 10083 +74: 0.16636392, 43, 15394, 15393, Water, 10083 +75: 1.414e-05, 94, 15403, 15400, Water, 10083 +76: 0.16636392, 44, 15810, 15809, Water, 10083 +77: 1.414e-05, 95, 15819, 15816, Water, 10083 +78: 0.16636392, 45, 16226, 16225, Water, 10083 +79: 1.414e-05, 96, 16235, 16232, Water, 10083 +80: 0.16636392, 46, 16642, 16641, Water, 10083 +81: 1.414e-05, 97, 16651, 16648, Water, 10083 +82: 0.16636392, 47, 17058, 17057, Water, 10083 +83: 1.414e-05, 98, 17067, 17064, Water, 10083 +84: 0.16636392, 48, 17474, 17473, Water, 10083 +85: 1.414e-05, 99, 17483, 17480, Water, 10083 +86: 0.16636392, 49, 17890, 17889, Water, 10083 +87: 1.414e-05, 100, 17899, 17896, Water, 10083 +88: 0.16636392, 50, 18306, 18305, Water, 10083 +89: 1.414e-05, 101, 18315, 18312, Water, 10083 +90: 0.16636392, 51, 18722, 18721, Water, 10083 +91: 1.414e-05, 102, 18731, 18728, Water, 10083 +92: 0.16636392, 52, 19138, 19137, Water, 10083 +93: 1.414e-05, 103, 19147, 19144, Water, 10083 +94: 0.16636392, 53, 19554, 19553, Water, 10083 +95: 1.414e-05, 104, 19563, 19560, Water, 10083 +96: 0.16636392, 54, 19970, 19969, Water, 10083 +97: 1.414e-05, 105, 19979, 19976, Water, 10083 +98: 0.16636392, 55, 20386, 20385, Water, 10083 +99: 1.414e-05, 106, 20395, 20392, Water, 10083 +100: 0.16636392, 56, 20802, 20801, Water, 10083 +Horizontal Track 51 +0: 0.11764706, 107, 10202, 10200, Water, 10083 +1: 0.11764706, 108, 10210, 10208, Water, 10083 +2: 0.11764706, 109, 10218, 10216, Water, 10083 +3: 0.11764706, 110, 10226, 10224, Water, 10083 +4: 0.11764706, 111, 10234, 10232, Water, 10083 +5: 0.11764706, 112, 10242, 10240, Water, 10083 +6: 0.11764706, 113, 10250, 10248, Water, 10083 +7: 0.11764706, 114, 10258, 10256, Water, 10083 +8: 0.11764706, 115, 10266, 10264, Water, 10083 +9: 0.11764706, 116, 10274, 10272, Water, 10083 +10: 0.11764706, 117, 10282, 10280, Water, 10083 +11: 0.11764706, 118, 10290, 10288, Water, 10083 +12: 0.11764706, 119, 10298, 10296, Water, 10083 +13: 0.11764706, 120, 10306, 10304, Water, 10083 +14: 0.11764706, 121, 10314, 10312, Water, 10083 +15: 0.11764706, 122, 10322, 10320, Water, 10083 +16: 0.11764706, 123, 10330, 10328, Water, 10083 +17: 0.11764706, 124, 10338, 10336, UO2, 49930 +18: 0.11764706, 125, 10346, 10344, UO2, 49930 +19: 0.11764706, 126, 10354, 10352, UO2, 49930 +20: 0.11764706, 127, 10362, 10360, UO2, 49930 +21: 0.11764706, 128, 10370, 10368, UO2, 49930 +22: 0.11764706, 129, 10378, 10376, UO2, 49930 +23: 0.11764706, 130, 10386, 10384, UO2, 49930 +24: 0.11764706, 131, 10394, 10392, UO2, 49930 +25: 0.11764706, 31, 10402, 10400, UO2, 49930 +26: 0.11764706, 82, 10410, 10408, UO2, 49930 +27: 0.11764706, 132, 10418, 10416, UO2, 49930 +28: 0.11764706, 133, 10426, 10424, UO2, 49930 +29: 0.11764706, 134, 10434, 10432, UO2, 49930 +30: 0.11764706, 135, 10442, 10440, UO2, 49930 +31: 0.11764706, 136, 10450, 10448, UO2, 49930 +32: 0.11764706, 137, 10458, 10456, UO2, 49930 +33: 0.11764706, 138, 10466, 10464, UO2, 49930 +34: 0.11764706, 139, 10474, 10472, Water, 10083 +35: 0.11764706, 140, 10482, 10480, Water, 10083 +36: 0.11764706, 141, 10490, 10488, Water, 10083 +37: 0.11764706, 142, 10498, 10496, Water, 10083 +38: 0.11764706, 143, 10506, 10504, Water, 10083 +39: 0.11764706, 144, 10514, 10512, Water, 10083 +40: 0.11764706, 145, 10522, 10520, Water, 10083 +41: 0.11764706, 146, 10530, 10528, Water, 10083 +42: 0.11764706, 147, 10538, 10536, Water, 10083 +43: 0.11764706, 148, 10546, 10544, Water, 10083 +44: 0.11764706, 149, 10554, 10552, Water, 10083 +45: 0.11764706, 150, 10562, 10560, Water, 10083 +46: 0.11764706, 151, 10570, 10568, Water, 10083 +47: 0.11764706, 152, 10578, 10576, Water, 10083 +48: 0.11764706, 153, 10586, 10584, Water, 10083 +49: 0.11764706, 154, 10594, 10592, Water, 10083 +50: 0.11764706, 155, 10602, 10600, Water, 10083 +Vertical Track 51 +0: 0.11764706, 156, 203, 201, Water, 10083 +1: 0.11764706, 157, 611, 609, Water, 10083 +2: 0.11764706, 158, 1019, 1017, Water, 10083 +3: 0.11764706, 159, 1427, 1425, Water, 10083 +4: 0.11764706, 160, 1835, 1833, Water, 10083 +5: 0.11764706, 161, 2243, 2241, Water, 10083 +6: 0.11764706, 162, 2651, 2649, Water, 10083 +7: 0.11764706, 163, 3059, 3057, Water, 10083 +8: 0.11764706, 164, 3467, 3465, Water, 10083 +9: 0.11764706, 165, 3875, 3873, Water, 10083 +10: 0.11764706, 166, 4283, 4281, Water, 10083 +11: 0.11764706, 167, 4691, 4689, Water, 10083 +12: 0.11764706, 168, 5099, 5097, Water, 10083 +13: 0.11764706, 169, 5507, 5505, Water, 10083 +14: 0.11764706, 170, 5915, 5913, Water, 10083 +15: 0.11764706, 171, 6323, 6321, Water, 10083 +16: 0.11764706, 172, 6731, 6729, Water, 10083 +17: 0.11764706, 173, 7139, 7137, UO2, 49930 +18: 0.11764706, 174, 7547, 7545, UO2, 49930 +19: 0.11764706, 175, 7955, 7953, UO2, 49930 +20: 0.11764706, 176, 8363, 8361, UO2, 49930 +21: 0.11764706, 177, 8771, 8769, UO2, 49930 +22: 0.11764706, 178, 9179, 9177, UO2, 49930 +23: 0.11764706, 179, 9587, 9585, UO2, 49930 +24: 0.11764706, 81, 9995, 9993, UO2, 49930 +25: 0.11764706, 31, 10403, 10401, UO2, 49930 +26: 0.11764706, 180, 10811, 10809, UO2, 49930 +27: 0.11764706, 181, 11219, 11217, UO2, 49930 +28: 0.11764706, 182, 11627, 11625, UO2, 49930 +29: 0.11764706, 183, 12035, 12033, UO2, 49930 +30: 0.11764706, 184, 12443, 12441, UO2, 49930 +31: 0.11764706, 185, 12851, 12849, UO2, 49930 +32: 0.11764706, 186, 13259, 13257, UO2, 49930 +33: 0.11764706, 187, 13667, 13665, UO2, 49930 +34: 0.11764706, 188, 14075, 14073, Water, 10083 +35: 0.11764706, 189, 14483, 14481, Water, 10083 +36: 0.11764706, 190, 14891, 14889, Water, 10083 +37: 0.11764706, 191, 15299, 15297, Water, 10083 +38: 0.11764706, 192, 15707, 15705, Water, 10083 +39: 0.11764706, 193, 16115, 16113, Water, 10083 +40: 0.11764706, 194, 16523, 16521, Water, 10083 +41: 0.11764706, 195, 16931, 16929, Water, 10083 +42: 0.11764706, 196, 17339, 17337, Water, 10083 +43: 0.11764706, 197, 17747, 17745, Water, 10083 +44: 0.11764706, 198, 18155, 18153, Water, 10083 +45: 0.11764706, 199, 18563, 18561, Water, 10083 +46: 0.11764706, 200, 18971, 18969, Water, 10083 +47: 0.11764706, 201, 19379, 19377, Water, 10083 +48: 0.11764706, 202, 19787, 19785, Water, 10083 +49: 0.11764706, 203, 20195, 20193, Water, 10083 +50: 0.11764706, 204, 20603, 20601, Water, 10083 +Reverse Diagonal Track 51 +0: 0.16637807, 56, 20804, 20806, Water, 10083 +1: 0.16637807, 55, 20388, 20390, Water, 10083 +2: 0.16637807, 54, 19972, 19974, Water, 10083 +3: 0.16637807, 53, 19556, 19558, Water, 10083 +4: 0.16637807, 52, 19140, 19142, Water, 10083 +5: 0.16637807, 51, 18724, 18726, Water, 10083 +6: 0.16637807, 50, 18308, 18310, Water, 10083 +7: 0.16637807, 49, 17892, 17894, Water, 10083 +8: 0.16637807, 48, 17476, 17478, Water, 10083 +9: 0.16637807, 47, 17060, 17062, Water, 10083 +10: 0.16637807, 46, 16644, 16646, Water, 10083 +11: 0.16637807, 45, 16228, 16230, Water, 10083 +12: 0.16637807, 44, 15812, 15814, Water, 10083 +13: 0.16637807, 43, 15396, 15398, Water, 10083 +14: 0.16637807, 42, 14980, 14982, Water, 10083 +15: 0.16637807, 41, 14564, 14566, Water, 10083 +16: 0.16637807, 40, 14148, 14150, Water, 10083 +17: 0.16637807, 39, 13732, 13734, UO2, 49930 +18: 0.16637807, 38, 13316, 13318, UO2, 49930 +19: 0.16637807, 37, 12900, 12902, UO2, 49930 +20: 0.16637807, 36, 12484, 12486, UO2, 49930 +21: 0.16637807, 35, 12068, 12070, UO2, 49930 +22: 0.16637807, 34, 11652, 11654, UO2, 49930 +23: 0.16637807, 33, 11236, 11238, UO2, 49930 +24: 0.16637807, 32, 10820, 10822, UO2, 49930 +25: 0.16637807, 31, 10404, 10406, UO2, 49930 +26: 0.16637807, 30, 9988, 9990, UO2, 49930 +27: 0.16637807, 29, 9572, 9574, UO2, 49930 +28: 0.16637807, 28, 9156, 9158, UO2, 49930 +29: 0.16637807, 27, 8740, 8742, UO2, 49930 +30: 0.16637807, 26, 8324, 8326, UO2, 49930 +31: 0.16637807, 25, 7908, 7910, UO2, 49930 +32: 0.16637807, 24, 7492, 7494, UO2, 49930 +33: 0.16637807, 23, 7076, 7078, UO2, 49930 +34: 0.16637807, 22, 6660, 6662, Water, 10083 +35: 0.16637807, 21, 6244, 6246, Water, 10083 +36: 0.16637807, 20, 5828, 5830, Water, 10083 +37: 0.16637807, 19, 5412, 5414, Water, 10083 +38: 0.16637807, 18, 4996, 4998, Water, 10083 +39: 0.16637807, 17, 4580, 4582, Water, 10083 +40: 0.16637807, 16, 4164, 4166, Water, 10083 +41: 0.16637807, 15, 3748, 3750, Water, 10083 +42: 0.16637807, 14, 3332, 3334, Water, 10083 +43: 0.16637807, 13, 2916, 2918, Water, 10083 +44: 0.16637807, 12, 2500, 2502, Water, 10083 +45: 0.16637807, 11, 2084, 2086, Water, 10083 +46: 0.16637807, 10, 1668, 1670, Water, 10083 +47: 0.16637807, 9, 1252, 1254, Water, 10083 +48: 0.16637807, 8, 836, 838, Water, 10083 +49: 0.16637807, 7, 420, 422, Water, 10083 +50: 0.16637807, 0, 4, 6, Water, 10083 diff --git a/tests/test_tracking_grid_cmfd/test_tracking_grid_cmfd.py b/tests/test_tracking_grid_cmfd/test_tracking_grid_cmfd.py new file mode 100644 index 000000000..dce3af67e --- /dev/null +++ b/tests/test_tracking_grid_cmfd/test_tracking_grid_cmfd.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import GridInput + +import openmoc + +class TrackingGridCMFDTestHarness(TrackingTestHarness): + """Tests tracking over a grid geometry with an overlaid CMFD mesh.""" + + def __init__(self): + super(TrackingGridCMFDTestHarness, self).__init__() + self.input_set = GridInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks""" + super(TrackingGridCMFDTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Nudged Diagonal Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-3, -3, 0, 3, 3, 0,\ + math.atan(1)) + nudge = 1e-5 + self.tracks['Nudged Diagonal Track'].setValues(-3+nudge, -3, 0, 3,\ + 3-nudge, 0,\ + math.atan(1)) + self.tracks['Horizontal Track'].setValues(-3, 0, 0, 3, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -3, 0, 0, 3, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(3, 3, 0, -3, -3, 0,\ + math.pi + math.atan(1)) + + def _run_openmoc(self): + """Segment tracks over the geometry and save the result to a string""" + + # Segmentize over the geometry with a fine and coarse cmfd mesh + for m in [3, 51]: + + # Overlay simple CMFD mesh + self._result += '{0} x {0} CMFD mesh\n'.format(m) + geometry = self.input_set.geometry + cmfd = openmoc.Cmfd() + cmfd.setLatticeStructure(m, m) + geometry.setCmfd(cmfd) + geometry.initializeCmfd() + + # Track over the composite geometry + super(TrackingGridCMFDTestHarness, self)._run_openmoc() + +if __name__ == '__main__': + harness = TrackingGridCMFDTestHarness() + harness.main() diff --git a/tests/test_tracking_lattice/results_true.dat b/tests/test_tracking_lattice/results_true.dat new file mode 100644 index 000000000..5d7d065a9 --- /dev/null +++ b/tests/test_tracking_lattice/results_true.dat @@ -0,0 +1,22 @@ +Diagonal Track 3 +0: 2.82842712, 0, -1, -1, Water, 10083 +1: 2.82842712, 1, -1, -1, UO2, 49930 +2: 2.82842712, 2, -1, -1, Water, 10083 +Nudged Diagonal Track 5 +0: 2.82841298, 0, -1, -1, Water, 10083 +1: 1.414e-05, 3, -1, -1, Water, 10083 +2: 2.82841298, 1, -1, -1, UO2, 49930 +3: 1.414e-05, 4, -1, -1, Water, 10083 +4: 2.82841298, 2, -1, -1, Water, 10083 +Horizontal Track 3 +0: 2.0, 5, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 2.0, 4, -1, -1, Water, 10083 +Vertical Track 3 +0: 2.0, 3, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 2.0, 6, -1, -1, Water, 10083 +Reverse Diagonal Track 3 +0: 2.82842712, 2, -1, -1, Water, 10083 +1: 2.82842712, 1, -1, -1, UO2, 49930 +2: 2.82842712, 0, -1, -1, Water, 10083 diff --git a/tests/test_tracking_lattice/test_tracking_lattice.py b/tests/test_tracking_lattice/test_tracking_lattice.py new file mode 100644 index 000000000..8b8f7bfd0 --- /dev/null +++ b/tests/test_tracking_lattice/test_tracking_lattice.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import LatticeGridInput + +import openmoc + +class TrackingLatticeGridTestHarness(TrackingTestHarness): + """Tests tracking over a lattice geometry.""" + + def __init__(self): + super(TrackingLatticeGridTestHarness, self).__init__() + self.input_set = LatticeGridInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks.""" + super(TrackingLatticeGridTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Nudged Diagonal Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-3, -3, 0, 3, 3, 0,\ + math.atan(1)) + nudge = 1e-5 + self.tracks['Nudged Diagonal Track'].setValues(-3+nudge, -3, 0, 3,\ + 3-nudge, 0,\ + math.atan(1)) + self.tracks['Horizontal Track'].setValues(-3, 0, 0, 3, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -3, 0, 0, 3, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(3, 3, 0, -3, -3, 0,\ + math.pi + math.atan(1)) + +if __name__ == '__main__': + harness = TrackingLatticeGridTestHarness() + harness.main() diff --git a/tests/test_tracking_lattice_cmfd/results_true.dat b/tests/test_tracking_lattice_cmfd/results_true.dat new file mode 100644 index 000000000..895a0ad7f --- /dev/null +++ b/tests/test_tracking_lattice_cmfd/results_true.dat @@ -0,0 +1,334 @@ +3 x 3 CMFD mesh +Diagonal Track 3 +0: 2.82842712, 0, 6, 4, Water, 10083 +1: 2.82842712, 1, 38, 36, UO2, 49930 +2: 2.82842712, 2, 70, 68, Water, 10083 +Nudged Diagonal Track 5 +0: 2.82841298, 0, 2, 1, Water, 10083 +1: 1.414e-05, 3, 11, 8, Water, 10083 +2: 2.82841298, 1, 34, 33, UO2, 49930 +3: 1.414e-05, 4, 43, 40, Water, 10083 +4: 2.82841298, 2, 66, 65, Water, 10083 +Horizontal Track 3 +0: 2.0, 5, 26, 24, Water, 10083 +1: 2.0, 1, 34, 32, UO2, 49930 +2: 2.0, 4, 42, 40, Water, 10083 +Vertical Track 3 +0: 2.0, 3, 11, 9, Water, 10083 +1: 2.0, 1, 35, 33, UO2, 49930 +2: 2.0, 6, 59, 57, Water, 10083 +Reverse Diagonal Track 3 +0: 2.82842712, 2, 68, 70, Water, 10083 +1: 2.82842712, 1, 36, 38, UO2, 49930 +2: 2.82842712, 0, 4, 6, Water, 10083 +51 x 51 CMFD mesh +Diagonal Track 51 +0: 0.16637807, 0, 6, 4, Water, 10083 +1: 0.16637807, 7, 422, 420, Water, 10083 +2: 0.16637807, 8, 838, 836, Water, 10083 +3: 0.16637807, 9, 1254, 1252, Water, 10083 +4: 0.16637807, 10, 1670, 1668, Water, 10083 +5: 0.16637807, 11, 2086, 2084, Water, 10083 +6: 0.16637807, 12, 2502, 2500, Water, 10083 +7: 0.16637807, 13, 2918, 2916, Water, 10083 +8: 0.16637807, 14, 3334, 3332, Water, 10083 +9: 0.16637807, 15, 3750, 3748, Water, 10083 +10: 0.16637807, 16, 4166, 4164, Water, 10083 +11: 0.16637807, 17, 4582, 4580, Water, 10083 +12: 0.16637807, 18, 4998, 4996, Water, 10083 +13: 0.16637807, 19, 5414, 5412, Water, 10083 +14: 0.16637807, 20, 5830, 5828, Water, 10083 +15: 0.16637807, 21, 6246, 6244, Water, 10083 +16: 0.16637807, 22, 6662, 6660, Water, 10083 +17: 0.16637807, 23, 7078, 7076, UO2, 49930 +18: 0.16637807, 24, 7494, 7492, UO2, 49930 +19: 0.16637807, 25, 7910, 7908, UO2, 49930 +20: 0.16637807, 26, 8326, 8324, UO2, 49930 +21: 0.16637807, 27, 8742, 8740, UO2, 49930 +22: 0.16637807, 28, 9158, 9156, UO2, 49930 +23: 0.16637807, 29, 9574, 9572, UO2, 49930 +24: 0.16637807, 30, 9990, 9988, UO2, 49930 +25: 0.16637807, 31, 10406, 10404, UO2, 49930 +26: 0.16637807, 32, 10822, 10820, UO2, 49930 +27: 0.16637807, 33, 11238, 11236, UO2, 49930 +28: 0.16637807, 34, 11654, 11652, UO2, 49930 +29: 0.16637807, 35, 12070, 12068, UO2, 49930 +30: 0.16637807, 36, 12486, 12484, UO2, 49930 +31: 0.16637807, 37, 12902, 12900, UO2, 49930 +32: 0.16637807, 38, 13318, 13316, UO2, 49930 +33: 0.16637807, 39, 13734, 13732, UO2, 49930 +34: 0.16637807, 40, 14150, 14148, Water, 10083 +35: 0.16637807, 41, 14566, 14564, Water, 10083 +36: 0.16637807, 42, 14982, 14980, Water, 10083 +37: 0.16637807, 43, 15398, 15396, Water, 10083 +38: 0.16637807, 44, 15814, 15812, Water, 10083 +39: 0.16637807, 45, 16230, 16228, Water, 10083 +40: 0.16637807, 46, 16646, 16644, Water, 10083 +41: 0.16637807, 47, 17062, 17060, Water, 10083 +42: 0.16637807, 48, 17478, 17476, Water, 10083 +43: 0.16637807, 49, 17894, 17892, Water, 10083 +44: 0.16637807, 50, 18310, 18308, Water, 10083 +45: 0.16637807, 51, 18726, 18724, Water, 10083 +46: 0.16637807, 52, 19142, 19140, Water, 10083 +47: 0.16637807, 53, 19558, 19556, Water, 10083 +48: 0.16637807, 54, 19974, 19972, Water, 10083 +49: 0.16637807, 55, 20390, 20388, Water, 10083 +50: 0.16637807, 56, 20806, 20804, Water, 10083 +Nudged Diagonal Track 101 +0: 0.16636392, 0, 2, 1, Water, 10083 +1: 1.414e-05, 57, 11, 8, Water, 10083 +2: 0.16636392, 7, 418, 417, Water, 10083 +3: 1.414e-05, 58, 427, 424, Water, 10083 +4: 0.16636392, 8, 834, 833, Water, 10083 +5: 1.414e-05, 59, 843, 840, Water, 10083 +6: 0.16636392, 9, 1250, 1249, Water, 10083 +7: 1.414e-05, 60, 1259, 1256, Water, 10083 +8: 0.16636392, 10, 1666, 1665, Water, 10083 +9: 1.414e-05, 61, 1675, 1672, Water, 10083 +10: 0.16636392, 11, 2082, 2081, Water, 10083 +11: 1.414e-05, 62, 2091, 2088, Water, 10083 +12: 0.16636392, 12, 2498, 2497, Water, 10083 +13: 1.414e-05, 63, 2507, 2504, Water, 10083 +14: 0.16636392, 13, 2914, 2913, Water, 10083 +15: 1.414e-05, 64, 2923, 2920, Water, 10083 +16: 0.16636392, 14, 3330, 3329, Water, 10083 +17: 1.414e-05, 65, 3339, 3336, Water, 10083 +18: 0.16636392, 15, 3746, 3745, Water, 10083 +19: 1.414e-05, 66, 3755, 3752, Water, 10083 +20: 0.16636392, 16, 4162, 4161, Water, 10083 +21: 1.414e-05, 67, 4171, 4168, Water, 10083 +22: 0.16636392, 17, 4578, 4577, Water, 10083 +23: 1.414e-05, 68, 4587, 4584, Water, 10083 +24: 0.16636392, 18, 4994, 4993, Water, 10083 +25: 1.414e-05, 69, 5003, 5000, Water, 10083 +26: 0.16636392, 19, 5410, 5409, Water, 10083 +27: 1.414e-05, 70, 5419, 5416, Water, 10083 +28: 0.16636392, 20, 5826, 5825, Water, 10083 +29: 1.414e-05, 71, 5835, 5832, Water, 10083 +30: 0.16636392, 21, 6242, 6241, Water, 10083 +31: 1.414e-05, 72, 6251, 6248, Water, 10083 +32: 0.16636392, 22, 6658, 6657, Water, 10083 +33: 1.414e-05, 73, 6667, 6664, Water, 10083 +34: 0.16636392, 23, 7074, 7073, UO2, 49930 +35: 1.414e-05, 74, 7083, 7080, UO2, 49930 +36: 0.16636392, 24, 7490, 7489, UO2, 49930 +37: 1.414e-05, 75, 7499, 7496, UO2, 49930 +38: 0.16636392, 25, 7906, 7905, UO2, 49930 +39: 1.414e-05, 76, 7915, 7912, UO2, 49930 +40: 0.16636392, 26, 8322, 8321, UO2, 49930 +41: 1.414e-05, 77, 8331, 8328, UO2, 49930 +42: 0.16636392, 27, 8738, 8737, UO2, 49930 +43: 1.414e-05, 78, 8747, 8744, UO2, 49930 +44: 0.16636392, 28, 9154, 9153, UO2, 49930 +45: 1.414e-05, 79, 9163, 9160, UO2, 49930 +46: 0.16636392, 29, 9570, 9569, UO2, 49930 +47: 1.414e-05, 80, 9579, 9576, UO2, 49930 +48: 0.16636392, 30, 9986, 9985, UO2, 49930 +49: 1.414e-05, 81, 9995, 9992, UO2, 49930 +50: 0.16636392, 31, 10402, 10401, UO2, 49930 +51: 1.414e-05, 82, 10411, 10408, UO2, 49930 +52: 0.16636392, 32, 10818, 10817, UO2, 49930 +53: 1.414e-05, 83, 10827, 10824, UO2, 49930 +54: 0.16636392, 33, 11234, 11233, UO2, 49930 +55: 1.414e-05, 84, 11243, 11240, UO2, 49930 +56: 0.16636392, 34, 11650, 11649, UO2, 49930 +57: 1.414e-05, 85, 11659, 11656, UO2, 49930 +58: 0.16636392, 35, 12066, 12065, UO2, 49930 +59: 1.414e-05, 86, 12075, 12072, UO2, 49930 +60: 0.16636392, 36, 12482, 12481, UO2, 49930 +61: 1.414e-05, 87, 12491, 12488, UO2, 49930 +62: 0.16636392, 37, 12898, 12897, UO2, 49930 +63: 1.414e-05, 88, 12907, 12904, UO2, 49930 +64: 0.16636392, 38, 13314, 13313, UO2, 49930 +65: 1.414e-05, 89, 13323, 13320, UO2, 49930 +66: 0.16636392, 39, 13730, 13729, UO2, 49930 +67: 1.414e-05, 90, 13739, 13736, Water, 10083 +68: 0.16636392, 40, 14146, 14145, Water, 10083 +69: 1.414e-05, 91, 14155, 14152, Water, 10083 +70: 0.16636392, 41, 14562, 14561, Water, 10083 +71: 1.414e-05, 92, 14571, 14568, Water, 10083 +72: 0.16636392, 42, 14978, 14977, Water, 10083 +73: 1.414e-05, 93, 14987, 14984, Water, 10083 +74: 0.16636392, 43, 15394, 15393, Water, 10083 +75: 1.414e-05, 94, 15403, 15400, Water, 10083 +76: 0.16636392, 44, 15810, 15809, Water, 10083 +77: 1.414e-05, 95, 15819, 15816, Water, 10083 +78: 0.16636392, 45, 16226, 16225, Water, 10083 +79: 1.414e-05, 96, 16235, 16232, Water, 10083 +80: 0.16636392, 46, 16642, 16641, Water, 10083 +81: 1.414e-05, 97, 16651, 16648, Water, 10083 +82: 0.16636392, 47, 17058, 17057, Water, 10083 +83: 1.414e-05, 98, 17067, 17064, Water, 10083 +84: 0.16636392, 48, 17474, 17473, Water, 10083 +85: 1.414e-05, 99, 17483, 17480, Water, 10083 +86: 0.16636392, 49, 17890, 17889, Water, 10083 +87: 1.414e-05, 100, 17899, 17896, Water, 10083 +88: 0.16636392, 50, 18306, 18305, Water, 10083 +89: 1.414e-05, 101, 18315, 18312, Water, 10083 +90: 0.16636392, 51, 18722, 18721, Water, 10083 +91: 1.414e-05, 102, 18731, 18728, Water, 10083 +92: 0.16636392, 52, 19138, 19137, Water, 10083 +93: 1.414e-05, 103, 19147, 19144, Water, 10083 +94: 0.16636392, 53, 19554, 19553, Water, 10083 +95: 1.414e-05, 104, 19563, 19560, Water, 10083 +96: 0.16636392, 54, 19970, 19969, Water, 10083 +97: 1.414e-05, 105, 19979, 19976, Water, 10083 +98: 0.16636392, 55, 20386, 20385, Water, 10083 +99: 1.414e-05, 106, 20395, 20392, Water, 10083 +100: 0.16636392, 56, 20802, 20801, Water, 10083 +Horizontal Track 51 +0: 0.11764706, 107, 10202, 10200, Water, 10083 +1: 0.11764706, 108, 10210, 10208, Water, 10083 +2: 0.11764706, 109, 10218, 10216, Water, 10083 +3: 0.11764706, 110, 10226, 10224, Water, 10083 +4: 0.11764706, 111, 10234, 10232, Water, 10083 +5: 0.11764706, 112, 10242, 10240, Water, 10083 +6: 0.11764706, 113, 10250, 10248, Water, 10083 +7: 0.11764706, 114, 10258, 10256, Water, 10083 +8: 0.11764706, 115, 10266, 10264, Water, 10083 +9: 0.11764706, 116, 10274, 10272, Water, 10083 +10: 0.11764706, 117, 10282, 10280, Water, 10083 +11: 0.11764706, 118, 10290, 10288, Water, 10083 +12: 0.11764706, 119, 10298, 10296, Water, 10083 +13: 0.11764706, 120, 10306, 10304, Water, 10083 +14: 0.11764706, 121, 10314, 10312, Water, 10083 +15: 0.11764706, 122, 10322, 10320, Water, 10083 +16: 0.11764706, 123, 10330, 10328, Water, 10083 +17: 0.11764706, 124, 10338, 10336, UO2, 49930 +18: 0.11764706, 125, 10346, 10344, UO2, 49930 +19: 0.11764706, 126, 10354, 10352, UO2, 49930 +20: 0.11764706, 127, 10362, 10360, UO2, 49930 +21: 0.11764706, 128, 10370, 10368, UO2, 49930 +22: 0.11764706, 129, 10378, 10376, UO2, 49930 +23: 0.11764706, 130, 10386, 10384, UO2, 49930 +24: 0.11764706, 131, 10394, 10392, UO2, 49930 +25: 0.11764706, 31, 10402, 10400, UO2, 49930 +26: 0.11764706, 82, 10410, 10408, UO2, 49930 +27: 0.11764706, 132, 10418, 10416, UO2, 49930 +28: 0.11764706, 133, 10426, 10424, UO2, 49930 +29: 0.11764706, 134, 10434, 10432, UO2, 49930 +30: 0.11764706, 135, 10442, 10440, UO2, 49930 +31: 0.11764706, 136, 10450, 10448, UO2, 49930 +32: 0.11764706, 137, 10458, 10456, UO2, 49930 +33: 0.11764706, 138, 10466, 10464, UO2, 49930 +34: 0.11764706, 139, 10474, 10472, Water, 10083 +35: 0.11764706, 140, 10482, 10480, Water, 10083 +36: 0.11764706, 141, 10490, 10488, Water, 10083 +37: 0.11764706, 142, 10498, 10496, Water, 10083 +38: 0.11764706, 143, 10506, 10504, Water, 10083 +39: 0.11764706, 144, 10514, 10512, Water, 10083 +40: 0.11764706, 145, 10522, 10520, Water, 10083 +41: 0.11764706, 146, 10530, 10528, Water, 10083 +42: 0.11764706, 147, 10538, 10536, Water, 10083 +43: 0.11764706, 148, 10546, 10544, Water, 10083 +44: 0.11764706, 149, 10554, 10552, Water, 10083 +45: 0.11764706, 150, 10562, 10560, Water, 10083 +46: 0.11764706, 151, 10570, 10568, Water, 10083 +47: 0.11764706, 152, 10578, 10576, Water, 10083 +48: 0.11764706, 153, 10586, 10584, Water, 10083 +49: 0.11764706, 154, 10594, 10592, Water, 10083 +50: 0.11764706, 155, 10602, 10600, Water, 10083 +Vertical Track 51 +0: 0.11764706, 156, 203, 201, Water, 10083 +1: 0.11764706, 157, 611, 609, Water, 10083 +2: 0.11764706, 158, 1019, 1017, Water, 10083 +3: 0.11764706, 159, 1427, 1425, Water, 10083 +4: 0.11764706, 160, 1835, 1833, Water, 10083 +5: 0.11764706, 161, 2243, 2241, Water, 10083 +6: 0.11764706, 162, 2651, 2649, Water, 10083 +7: 0.11764706, 163, 3059, 3057, Water, 10083 +8: 0.11764706, 164, 3467, 3465, Water, 10083 +9: 0.11764706, 165, 3875, 3873, Water, 10083 +10: 0.11764706, 166, 4283, 4281, Water, 10083 +11: 0.11764706, 167, 4691, 4689, Water, 10083 +12: 0.11764706, 168, 5099, 5097, Water, 10083 +13: 0.11764706, 169, 5507, 5505, Water, 10083 +14: 0.11764706, 170, 5915, 5913, Water, 10083 +15: 0.11764706, 171, 6323, 6321, Water, 10083 +16: 0.11764706, 172, 6731, 6729, Water, 10083 +17: 0.11764706, 173, 7139, 7137, UO2, 49930 +18: 0.11764706, 174, 7547, 7545, UO2, 49930 +19: 0.11764706, 175, 7955, 7953, UO2, 49930 +20: 0.11764706, 176, 8363, 8361, UO2, 49930 +21: 0.11764706, 177, 8771, 8769, UO2, 49930 +22: 0.11764706, 178, 9179, 9177, UO2, 49930 +23: 0.11764706, 179, 9587, 9585, UO2, 49930 +24: 0.11764706, 81, 9995, 9993, UO2, 49930 +25: 0.11764706, 31, 10403, 10401, UO2, 49930 +26: 0.11764706, 180, 10811, 10809, UO2, 49930 +27: 0.11764706, 181, 11219, 11217, UO2, 49930 +28: 0.11764706, 182, 11627, 11625, UO2, 49930 +29: 0.11764706, 183, 12035, 12033, UO2, 49930 +30: 0.11764706, 184, 12443, 12441, UO2, 49930 +31: 0.11764706, 185, 12851, 12849, UO2, 49930 +32: 0.11764706, 186, 13259, 13257, UO2, 49930 +33: 0.11764706, 187, 13667, 13665, UO2, 49930 +34: 0.11764706, 188, 14075, 14073, Water, 10083 +35: 0.11764706, 189, 14483, 14481, Water, 10083 +36: 0.11764706, 190, 14891, 14889, Water, 10083 +37: 0.11764706, 191, 15299, 15297, Water, 10083 +38: 0.11764706, 192, 15707, 15705, Water, 10083 +39: 0.11764706, 193, 16115, 16113, Water, 10083 +40: 0.11764706, 194, 16523, 16521, Water, 10083 +41: 0.11764706, 195, 16931, 16929, Water, 10083 +42: 0.11764706, 196, 17339, 17337, Water, 10083 +43: 0.11764706, 197, 17747, 17745, Water, 10083 +44: 0.11764706, 198, 18155, 18153, Water, 10083 +45: 0.11764706, 199, 18563, 18561, Water, 10083 +46: 0.11764706, 200, 18971, 18969, Water, 10083 +47: 0.11764706, 201, 19379, 19377, Water, 10083 +48: 0.11764706, 202, 19787, 19785, Water, 10083 +49: 0.11764706, 203, 20195, 20193, Water, 10083 +50: 0.11764706, 204, 20603, 20601, Water, 10083 +Reverse Diagonal Track 51 +0: 0.16637807, 56, 20804, 20806, Water, 10083 +1: 0.16637807, 55, 20388, 20390, Water, 10083 +2: 0.16637807, 54, 19972, 19974, Water, 10083 +3: 0.16637807, 53, 19556, 19558, Water, 10083 +4: 0.16637807, 52, 19140, 19142, Water, 10083 +5: 0.16637807, 51, 18724, 18726, Water, 10083 +6: 0.16637807, 50, 18308, 18310, Water, 10083 +7: 0.16637807, 49, 17892, 17894, Water, 10083 +8: 0.16637807, 48, 17476, 17478, Water, 10083 +9: 0.16637807, 47, 17060, 17062, Water, 10083 +10: 0.16637807, 46, 16644, 16646, Water, 10083 +11: 0.16637807, 45, 16228, 16230, Water, 10083 +12: 0.16637807, 44, 15812, 15814, Water, 10083 +13: 0.16637807, 43, 15396, 15398, Water, 10083 +14: 0.16637807, 42, 14980, 14982, Water, 10083 +15: 0.16637807, 41, 14564, 14566, Water, 10083 +16: 0.16637807, 40, 14148, 14150, Water, 10083 +17: 0.16637807, 39, 13732, 13734, UO2, 49930 +18: 0.16637807, 38, 13316, 13318, UO2, 49930 +19: 0.16637807, 37, 12900, 12902, UO2, 49930 +20: 0.16637807, 36, 12484, 12486, UO2, 49930 +21: 0.16637807, 35, 12068, 12070, UO2, 49930 +22: 0.16637807, 34, 11652, 11654, UO2, 49930 +23: 0.16637807, 33, 11236, 11238, UO2, 49930 +24: 0.16637807, 32, 10820, 10822, UO2, 49930 +25: 0.16637807, 31, 10404, 10406, UO2, 49930 +26: 0.16637807, 30, 9988, 9990, UO2, 49930 +27: 0.16637807, 29, 9572, 9574, UO2, 49930 +28: 0.16637807, 28, 9156, 9158, UO2, 49930 +29: 0.16637807, 27, 8740, 8742, UO2, 49930 +30: 0.16637807, 26, 8324, 8326, UO2, 49930 +31: 0.16637807, 25, 7908, 7910, UO2, 49930 +32: 0.16637807, 24, 7492, 7494, UO2, 49930 +33: 0.16637807, 23, 7076, 7078, UO2, 49930 +34: 0.16637807, 22, 6660, 6662, Water, 10083 +35: 0.16637807, 21, 6244, 6246, Water, 10083 +36: 0.16637807, 20, 5828, 5830, Water, 10083 +37: 0.16637807, 19, 5412, 5414, Water, 10083 +38: 0.16637807, 18, 4996, 4998, Water, 10083 +39: 0.16637807, 17, 4580, 4582, Water, 10083 +40: 0.16637807, 16, 4164, 4166, Water, 10083 +41: 0.16637807, 15, 3748, 3750, Water, 10083 +42: 0.16637807, 14, 3332, 3334, Water, 10083 +43: 0.16637807, 13, 2916, 2918, Water, 10083 +44: 0.16637807, 12, 2500, 2502, Water, 10083 +45: 0.16637807, 11, 2084, 2086, Water, 10083 +46: 0.16637807, 10, 1668, 1670, Water, 10083 +47: 0.16637807, 9, 1252, 1254, Water, 10083 +48: 0.16637807, 8, 836, 838, Water, 10083 +49: 0.16637807, 7, 420, 422, Water, 10083 +50: 0.16637807, 0, 4, 6, Water, 10083 diff --git a/tests/test_tracking_lattice_cmfd/test_tracking_lattice_cmfd.py b/tests/test_tracking_lattice_cmfd/test_tracking_lattice_cmfd.py new file mode 100644 index 000000000..3772b5da7 --- /dev/null +++ b/tests/test_tracking_lattice_cmfd/test_tracking_lattice_cmfd.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import LatticeGridInput + +import openmoc + +class TrackingLatticeGridCMFDTestHarness(TrackingTestHarness): + """Tests tracking over a lattice geometry with an overlaid CMFD mesh.""" + + def __init__(self): + super(TrackingLatticeGridCMFDTestHarness, self).__init__() + self.input_set = LatticeGridInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks""" + super(TrackingLatticeGridCMFDTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Nudged Diagonal Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-3, -3, 0, 3, 3, 0,\ + math.atan(1)) + nudge = 1e-5 + self.tracks['Nudged Diagonal Track'].setValues(-3+nudge, -3, 0, 3,\ + 3-nudge, 0,\ + math.atan(1)) + self.tracks['Horizontal Track'].setValues(-3, 0, 0, 3, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -3, 0, 0, 3, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(3, 3, 0, -3, -3, 0,\ + math.pi + math.atan(1)) + + def _run_openmoc(self): + """Segment tracks over the geometry and save the result to a string""" + + # Segmentize over the geometry with a fine and coarse cmfd mesh + for m in [3, 51]: + + # Overlay simple CMFD mesh + self._result += '{0} x {0} CMFD mesh\n'.format(m) + geometry = self.input_set.geometry + cmfd = openmoc.Cmfd() + cmfd.setLatticeStructure(m, m) + geometry.setCmfd(cmfd) + geometry.initializeCmfd() + + # Track over the composite geometry + super(TrackingLatticeGridCMFDTestHarness, self)._run_openmoc() + +if __name__ == '__main__': + harness = TrackingLatticeGridCMFDTestHarness() + harness.main() diff --git a/tests/test_tracking_pin_cell/results_true.dat b/tests/test_tracking_pin_cell/results_true.dat new file mode 100644 index 000000000..a50c22935 --- /dev/null +++ b/tests/test_tracking_pin_cell/results_true.dat @@ -0,0 +1,22 @@ +Diagonal Track 3 +0: 1.82842712, 0, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 1.82842712, 0, -1, -1, Water, 10083 +Tangent Track 1 +0: 3.65685425, 0, -1, -1, Water, 10083 +Nudged Tangent Track 3 +0: 1.82723862, 0, -1, -1, Water, 10083 +1: 0.00237841, 1, -1, -1, UO2, 49930 +2: 1.82723862, 0, -1, -1, Water, 10083 +Horizontal Track 3 +0: 1.0, 0, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 1.0, 0, -1, -1, Water, 10083 +Vertical Track 3 +0: 1.0, 0, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 1.0, 0, -1, -1, Water, 10083 +Reverse Diagonal Track 3 +0: 1.82842712, 0, -1, -1, Water, 10083 +1: 2.0, 1, -1, -1, UO2, 49930 +2: 1.82842712, 0, -1, -1, Water, 10083 diff --git a/tests/test_tracking_pin_cell/test_tracking_pin_cell.py b/tests/test_tracking_pin_cell/test_tracking_pin_cell.py new file mode 100644 index 000000000..e87daa1c2 --- /dev/null +++ b/tests/test_tracking_pin_cell/test_tracking_pin_cell.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import PinCellInput + +import openmoc + +class TrackingPinCellTestHarness(TrackingTestHarness): + """Tests tracking over a pin cell geometry.""" + + def __init__(self): + super(TrackingPinCellTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks.""" + super(TrackingPinCellTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Tangent Track'] = openmoc.Track() + self.tracks['Nudged Tangent Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-2, -2, 0, 2, 2, 0,\ + math.atan(1)) + offset = math.sqrt(2) - 2 + self.tracks['Tangent Track'].setValues(offset, -2, 0, 2, -offset,\ + 0, math.atan(1)) + offset -= 1e-6 + self.tracks['Nudged Tangent Track'].setValues(offset, -2, 0, 2,\ + -offset, 0, math.atan(1)) + self.tracks['Horizontal Track'].setValues(-2, 0, 0, 2, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -2, 0, 0, 2, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(2, 2, 0, -2, -2, 0,\ + math.pi + math.atan(1)) + +if __name__ == '__main__': + harness = TrackingPinCellTestHarness() + harness.main() diff --git a/tests/test_tracking_pin_cell_cmfd/results_true.dat b/tests/test_tracking_pin_cell_cmfd/results_true.dat new file mode 100644 index 000000000..89a248aa5 --- /dev/null +++ b/tests/test_tracking_pin_cell_cmfd/results_true.dat @@ -0,0 +1,388 @@ +3 x 3 CMFD mesh +Diagonal Track 5 +0: 1.82842712, 0, -1, 4, Water, 10083 +1: 0.05719096, 1, 6, -1, UO2, 49930 +2: 1.88561808, 2, 38, 36, UO2, 49930 +3: 0.05719096, 3, -1, 68, UO2, 49930 +4: 1.82842712, 4, 70, -1, Water, 10083 +Tangent Track 3 +0: 1.77123617, 5, 10, 9, Water, 10083 +1: 0.11438192, 6, 19, 16, Water, 10083 +2: 1.77123617, 7, 42, 41, Water, 10083 +Nudged Tangent Track 5 +0: 1.77123758, 5, 10, 9, Water, 10083 +1: 0.05600104, 6, -1, 16, Water, 10083 +2: 0.00237841, 8, -1, -1, UO2, 49930 +3: 0.05600104, 6, 19, -1, Water, 10083 +4: 1.77123758, 7, 42, 41, Water, 10083 +Horizontal Track 5 +0: 1.0, 9, -1, 24, Water, 10083 +1: 0.33333333, 10, 26, -1, UO2, 49930 +2: 1.33333333, 2, 34, 32, UO2, 49930 +3: 0.33333333, 11, -1, 40, UO2, 49930 +4: 1.0, 7, 42, -1, Water, 10083 +Vertical Track 5 +0: 1.0, 5, -1, 9, Water, 10083 +1: 0.33333333, 12, 11, -1, UO2, 49930 +2: 1.33333333, 2, 35, 33, UO2, 49930 +3: 0.33333333, 13, -1, 57, UO2, 49930 +4: 1.0, 14, 59, -1, Water, 10083 +Reverse Diagonal Track 5 +0: 1.82842712, 4, -1, 70, Water, 10083 +1: 0.05719096, 3, 68, -1, UO2, 49930 +2: 1.88561808, 2, 36, 38, UO2, 49930 +3: 0.05719096, 1, -1, 6, UO2, 49930 +4: 1.82842712, 0, 4, -1, Water, 10083 +51 x 51 CMFD mesh +Diagonal Track 53 +0: 0.11091871, 0, 6, 4, Water, 10083 +1: 0.11091871, 15, 422, 420, Water, 10083 +2: 0.11091871, 4, 838, 836, Water, 10083 +3: 0.11091871, 16, 1254, 1252, Water, 10083 +4: 0.11091871, 17, 1670, 1668, Water, 10083 +5: 0.11091871, 18, 2086, 2084, Water, 10083 +6: 0.11091871, 19, 2502, 2500, Water, 10083 +7: 0.11091871, 20, 2918, 2916, Water, 10083 +8: 0.11091871, 21, 3334, 3332, Water, 10083 +9: 0.11091871, 22, 3750, 3748, Water, 10083 +10: 0.11091871, 23, 4166, 4164, Water, 10083 +11: 0.11091871, 24, 4582, 4580, Water, 10083 +12: 0.11091871, 25, 4998, 4996, Water, 10083 +13: 0.11091871, 26, 5414, 5412, Water, 10083 +14: 0.11091871, 27, 5830, 5828, Water, 10083 +15: 0.11091871, 28, 6246, 6244, Water, 10083 +16: 0.05372775, 29, -1, 6660, Water, 10083 +17: 0.05719096, 30, 6662, -1, UO2, 49930 +18: 0.11091871, 31, 7078, 7076, UO2, 49930 +19: 0.11091871, 32, 7494, 7492, UO2, 49930 +20: 0.11091871, 33, 7910, 7908, UO2, 49930 +21: 0.11091871, 34, 8326, 8324, UO2, 49930 +22: 0.11091871, 35, 8742, 8740, UO2, 49930 +23: 0.11091871, 36, 9158, 9156, UO2, 49930 +24: 0.11091871, 37, 9574, 9572, UO2, 49930 +25: 0.11091871, 38, 9990, 9988, UO2, 49930 +26: 0.11091871, 39, 10406, 10404, UO2, 49930 +27: 0.11091871, 40, 10822, 10820, UO2, 49930 +28: 0.11091871, 41, 11238, 11236, UO2, 49930 +29: 0.11091871, 42, 11654, 11652, UO2, 49930 +30: 0.11091871, 43, 12070, 12068, UO2, 49930 +31: 0.11091871, 44, 12486, 12484, UO2, 49930 +32: 0.11091871, 45, 12902, 12900, UO2, 49930 +33: 0.11091871, 46, 13318, 13316, UO2, 49930 +34: 0.11091871, 47, 13734, 13732, UO2, 49930 +35: 0.05719096, 48, -1, 14148, UO2, 49930 +36: 0.05372775, 49, 14150, -1, Water, 10083 +37: 0.11091871, 50, 14566, 14564, Water, 10083 +38: 0.11091871, 51, 14982, 14980, Water, 10083 +39: 0.11091871, 52, 15398, 15396, Water, 10083 +40: 0.11091871, 53, 15814, 15812, Water, 10083 +41: 0.11091871, 54, 16230, 16228, Water, 10083 +42: 0.11091871, 55, 16646, 16644, Water, 10083 +43: 0.11091871, 56, 17062, 17060, Water, 10083 +44: 0.11091871, 57, 17478, 17476, Water, 10083 +45: 0.11091871, 58, 17894, 17892, Water, 10083 +46: 0.11091871, 59, 18310, 18308, Water, 10083 +47: 0.11091871, 60, 18726, 18724, Water, 10083 +48: 0.11091871, 61, 19142, 19140, Water, 10083 +49: 0.11091871, 62, 19558, 19556, Water, 10083 +50: 0.11091871, 63, 19974, 19972, Water, 10083 +51: 0.11091871, 64, 20390, 20388, Water, 10083 +52: 0.11091871, 65, 20806, 20804, Water, 10083 +Tangent Track 67 +0: 0.1074555, 66, 146, 145, Water, 10083 +1: 0.00346321, 67, 155, 152, Water, 10083 +2: 0.1074555, 68, 562, 561, Water, 10083 +3: 0.00346321, 69, 571, 568, Water, 10083 +4: 0.1074555, 70, 978, 977, Water, 10083 +5: 0.00346321, 71, 987, 984, Water, 10083 +6: 0.1074555, 72, 1394, 1393, Water, 10083 +7: 0.00346321, 73, 1403, 1400, Water, 10083 +8: 0.1074555, 74, 1810, 1809, Water, 10083 +9: 0.00346321, 75, 1819, 1816, Water, 10083 +10: 0.1074555, 76, 2226, 2225, Water, 10083 +11: 0.00346321, 77, 2235, 2232, Water, 10083 +12: 0.1074555, 78, 2642, 2641, Water, 10083 +13: 0.00346321, 79, 2651, 2648, Water, 10083 +14: 0.1074555, 80, 3058, 3057, Water, 10083 +15: 0.00346321, 81, 3067, 3064, Water, 10083 +16: 0.1074555, 82, 3474, 3473, Water, 10083 +17: 0.00346321, 83, 3483, 3480, Water, 10083 +18: 0.1074555, 84, 3890, 3889, Water, 10083 +19: 0.00346321, 85, 3899, 3896, Water, 10083 +20: 0.1074555, 86, 4306, 4305, Water, 10083 +21: 0.00346321, 87, 4315, 4312, Water, 10083 +22: 0.1074555, 88, 4722, 4721, Water, 10083 +23: 0.00346321, 89, 4731, 4728, Water, 10083 +24: 0.1074555, 90, 5138, 5137, Water, 10083 +25: 0.00346321, 91, 5147, 5144, Water, 10083 +26: 0.1074555, 92, 5554, 5553, Water, 10083 +27: 0.00346321, 93, 5563, 5560, Water, 10083 +28: 0.1074555, 94, 5970, 5969, Water, 10083 +29: 0.00346321, 95, 5979, 5976, Water, 10083 +30: 0.1074555, 96, 6386, 6385, Water, 10083 +31: 0.00346321, 97, 6395, 6392, Water, 10083 +32: 0.05372772, 98, -1, 6801, Water, 10083 +33: 7e-08, 99, -1, -1, UO2, 49930 +34: 0.05372772, 99, 6802, -1, UO2, 49930 +35: 0.00346321, 100, 6811, 6808, Water, 10083 +36: 0.1074555, 101, 7218, 7217, Water, 10083 +37: 0.00346321, 102, 7227, 7224, Water, 10083 +38: 0.1074555, 103, 7634, 7633, Water, 10083 +39: 0.00346321, 104, 7643, 7640, Water, 10083 +40: 0.1074555, 105, 8050, 8049, Water, 10083 +41: 0.00346321, 106, 8059, 8056, Water, 10083 +42: 0.1074555, 107, 8466, 8465, Water, 10083 +43: 0.00346321, 108, 8475, 8472, Water, 10083 +44: 0.1074555, 109, 8882, 8881, Water, 10083 +45: 0.00346321, 110, 8891, 8888, Water, 10083 +46: 0.1074555, 111, 9298, 9297, Water, 10083 +47: 0.00346321, 112, 9307, 9304, Water, 10083 +48: 0.1074555, 113, 9714, 9713, Water, 10083 +49: 0.00346321, 114, 9723, 9720, Water, 10083 +50: 0.1074555, 115, 10130, 10129, Water, 10083 +51: 0.00346321, 116, 10139, 10136, Water, 10083 +52: 0.1074555, 117, 10546, 10545, Water, 10083 +53: 0.00346321, 118, 10555, 10552, Water, 10083 +54: 0.1074555, 119, 10962, 10961, Water, 10083 +55: 0.00346321, 120, 10971, 10968, Water, 10083 +56: 0.1074555, 121, 11378, 11377, Water, 10083 +57: 0.00346321, 122, 11387, 11384, Water, 10083 +58: 0.1074555, 123, 11794, 11793, Water, 10083 +59: 0.00346321, 124, 11803, 11800, Water, 10083 +60: 0.1074555, 125, 12210, 12209, Water, 10083 +61: 0.00346321, 126, 12219, 12216, Water, 10083 +62: 0.1074555, 127, 12626, 12625, Water, 10083 +63: 0.00346321, 128, 12635, 12632, Water, 10083 +64: 0.1074555, 129, 13042, 13041, Water, 10083 +65: 0.00346321, 130, 13051, 13048, Water, 10083 +66: 0.1074555, 131, 13458, 13457, Water, 10083 +Nudged Tangent Track 67 +0: 0.10745692, 66, 146, 145, Water, 10083 +1: 0.00346179, 67, 155, 152, Water, 10083 +2: 0.10745692, 68, 562, 561, Water, 10083 +3: 0.00346179, 69, 571, 568, Water, 10083 +4: 0.10745692, 70, 978, 977, Water, 10083 +5: 0.00346179, 71, 987, 984, Water, 10083 +6: 0.10745692, 72, 1394, 1393, Water, 10083 +7: 0.00346179, 73, 1403, 1400, Water, 10083 +8: 0.10745692, 74, 1810, 1809, Water, 10083 +9: 0.00346179, 75, 1819, 1816, Water, 10083 +10: 0.10745692, 76, 2226, 2225, Water, 10083 +11: 0.00346179, 77, 2235, 2232, Water, 10083 +12: 0.10745692, 78, 2642, 2641, Water, 10083 +13: 0.00346179, 79, 2651, 2648, Water, 10083 +14: 0.10745692, 80, 3058, 3057, Water, 10083 +15: 0.00346179, 81, 3067, 3064, Water, 10083 +16: 0.10745692, 82, 3474, 3473, Water, 10083 +17: 0.00346179, 83, 3483, 3480, Water, 10083 +18: 0.10745692, 84, 3890, 3889, Water, 10083 +19: 0.00346179, 85, 3899, 3896, Water, 10083 +20: 0.10745692, 86, 4306, 4305, Water, 10083 +21: 0.00346179, 87, 4315, 4312, Water, 10083 +22: 0.10745692, 88, 4722, 4721, Water, 10083 +23: 0.00346179, 89, 4731, 4728, Water, 10083 +24: 0.10745692, 90, 5138, 5137, Water, 10083 +25: 0.00346179, 91, 5147, 5144, Water, 10083 +26: 0.10745692, 92, 5554, 5553, Water, 10083 +27: 0.00346179, 93, 5563, 5560, Water, 10083 +28: 0.10745692, 94, 5970, 5969, Water, 10083 +29: 0.00346179, 95, 5979, 5976, Water, 10083 +30: 0.10745692, 96, 6386, 6385, Water, 10083 +31: 0.00346179, 97, 6395, 6392, Water, 10083 +32: 0.05253925, 98, -1, 6801, Water, 10083 +33: 0.00237841, 99, -1, -1, UO2, 49930 +34: 0.05253925, 98, 6802, -1, Water, 10083 +35: 0.00346179, 100, 6811, 6808, Water, 10083 +36: 0.10745692, 101, 7218, 7217, Water, 10083 +37: 0.00346179, 102, 7227, 7224, Water, 10083 +38: 0.10745692, 103, 7634, 7633, Water, 10083 +39: 0.00346179, 104, 7643, 7640, Water, 10083 +40: 0.10745692, 105, 8050, 8049, Water, 10083 +41: 0.00346179, 106, 8059, 8056, Water, 10083 +42: 0.10745692, 107, 8466, 8465, Water, 10083 +43: 0.00346179, 108, 8475, 8472, Water, 10083 +44: 0.10745692, 109, 8882, 8881, Water, 10083 +45: 0.00346179, 110, 8891, 8888, Water, 10083 +46: 0.10745692, 111, 9298, 9297, Water, 10083 +47: 0.00346179, 112, 9307, 9304, Water, 10083 +48: 0.10745692, 113, 9714, 9713, Water, 10083 +49: 0.00346179, 114, 9723, 9720, Water, 10083 +50: 0.10745692, 115, 10130, 10129, Water, 10083 +51: 0.00346179, 116, 10139, 10136, Water, 10083 +52: 0.10745692, 117, 10546, 10545, Water, 10083 +53: 0.00346179, 118, 10555, 10552, Water, 10083 +54: 0.10745692, 119, 10962, 10961, Water, 10083 +55: 0.00346179, 120, 10971, 10968, Water, 10083 +56: 0.10745692, 121, 11378, 11377, Water, 10083 +57: 0.00346179, 122, 11387, 11384, Water, 10083 +58: 0.10745692, 123, 11794, 11793, Water, 10083 +59: 0.00346179, 124, 11803, 11800, Water, 10083 +60: 0.10745692, 125, 12210, 12209, Water, 10083 +61: 0.00346179, 126, 12219, 12216, Water, 10083 +62: 0.10745692, 127, 12626, 12625, Water, 10083 +63: 0.00346179, 128, 12635, 12632, Water, 10083 +64: 0.10745692, 129, 13042, 13041, Water, 10083 +65: 0.00346179, 130, 13051, 13048, Water, 10083 +66: 0.10745692, 131, 13458, 13457, Water, 10083 +Horizontal Track 53 +0: 0.07843137, 132, 10202, 10200, Water, 10083 +1: 0.07843137, 133, 10210, 10208, Water, 10083 +2: 0.07843137, 134, 10218, 10216, Water, 10083 +3: 0.07843137, 135, 10226, 10224, Water, 10083 +4: 0.07843137, 136, 10234, 10232, Water, 10083 +5: 0.07843137, 137, 10242, 10240, Water, 10083 +6: 0.07843137, 138, 10250, 10248, Water, 10083 +7: 0.07843137, 139, 10258, 10256, Water, 10083 +8: 0.07843137, 140, 10266, 10264, Water, 10083 +9: 0.07843137, 141, 10274, 10272, Water, 10083 +10: 0.07843137, 142, 10282, 10280, Water, 10083 +11: 0.07843137, 143, 10290, 10288, Water, 10083 +12: 0.05882353, 144, -1, 10296, Water, 10083 +13: 0.01960784, 145, 10298, -1, UO2, 49930 +14: 0.07843137, 146, 10306, 10304, UO2, 49930 +15: 0.07843137, 147, 10314, 10312, UO2, 49930 +16: 0.07843137, 148, 10322, 10320, UO2, 49930 +17: 0.07843137, 149, 10330, 10328, UO2, 49930 +18: 0.07843137, 150, 10338, 10336, UO2, 49930 +19: 0.07843137, 151, 10346, 10344, UO2, 49930 +20: 0.07843137, 152, 10354, 10352, UO2, 49930 +21: 0.07843137, 153, 10362, 10360, UO2, 49930 +22: 0.07843137, 154, 10370, 10368, UO2, 49930 +23: 0.07843137, 155, 10378, 10376, UO2, 49930 +24: 0.07843137, 156, 10386, 10384, UO2, 49930 +25: 0.07843137, 157, 10394, 10392, UO2, 49930 +26: 0.07843137, 39, 10402, 10400, UO2, 49930 +27: 0.07843137, 158, 10410, 10408, UO2, 49930 +28: 0.07843137, 159, 10418, 10416, UO2, 49930 +29: 0.07843137, 160, 10426, 10424, UO2, 49930 +30: 0.07843137, 161, 10434, 10432, UO2, 49930 +31: 0.07843137, 162, 10442, 10440, UO2, 49930 +32: 0.07843137, 163, 10450, 10448, UO2, 49930 +33: 0.07843137, 164, 10458, 10456, UO2, 49930 +34: 0.07843137, 165, 10466, 10464, UO2, 49930 +35: 0.07843137, 166, 10474, 10472, UO2, 49930 +36: 0.07843137, 167, 10482, 10480, UO2, 49930 +37: 0.07843137, 168, 10490, 10488, UO2, 49930 +38: 0.07843137, 169, 10498, 10496, UO2, 49930 +39: 0.01960784, 170, -1, 10504, UO2, 49930 +40: 0.05882353, 171, 10506, -1, Water, 10083 +41: 0.07843137, 172, 10514, 10512, Water, 10083 +42: 0.07843137, 173, 10522, 10520, Water, 10083 +43: 0.07843137, 174, 10530, 10528, Water, 10083 +44: 0.07843137, 175, 10538, 10536, Water, 10083 +45: 0.07843137, 117, 10546, 10544, Water, 10083 +46: 0.07843137, 118, 10554, 10552, Water, 10083 +47: 0.07843137, 176, 10562, 10560, Water, 10083 +48: 0.07843137, 177, 10570, 10568, Water, 10083 +49: 0.07843137, 178, 10578, 10576, Water, 10083 +50: 0.07843137, 179, 10586, 10584, Water, 10083 +51: 0.07843137, 180, 10594, 10592, Water, 10083 +52: 0.07843137, 181, 10602, 10600, Water, 10083 +Vertical Track 53 +0: 0.07843137, 182, 203, 201, Water, 10083 +1: 0.07843137, 183, 611, 609, Water, 10083 +2: 0.07843137, 184, 1019, 1017, Water, 10083 +3: 0.07843137, 185, 1427, 1425, Water, 10083 +4: 0.07843137, 186, 1835, 1833, Water, 10083 +5: 0.07843137, 187, 2243, 2241, Water, 10083 +6: 0.07843137, 79, 2651, 2649, Water, 10083 +7: 0.07843137, 80, 3059, 3057, Water, 10083 +8: 0.07843137, 188, 3467, 3465, Water, 10083 +9: 0.07843137, 189, 3875, 3873, Water, 10083 +10: 0.07843137, 190, 4283, 4281, Water, 10083 +11: 0.07843137, 191, 4691, 4689, Water, 10083 +12: 0.05882353, 192, -1, 5097, Water, 10083 +13: 0.01960784, 193, 5099, -1, UO2, 49930 +14: 0.07843137, 194, 5507, 5505, UO2, 49930 +15: 0.07843137, 195, 5915, 5913, UO2, 49930 +16: 0.07843137, 196, 6323, 6321, UO2, 49930 +17: 0.07843137, 197, 6731, 6729, UO2, 49930 +18: 0.07843137, 198, 7139, 7137, UO2, 49930 +19: 0.07843137, 199, 7547, 7545, UO2, 49930 +20: 0.07843137, 200, 7955, 7953, UO2, 49930 +21: 0.07843137, 201, 8363, 8361, UO2, 49930 +22: 0.07843137, 202, 8771, 8769, UO2, 49930 +23: 0.07843137, 203, 9179, 9177, UO2, 49930 +24: 0.07843137, 204, 9587, 9585, UO2, 49930 +25: 0.07843137, 205, 9995, 9993, UO2, 49930 +26: 0.07843137, 39, 10403, 10401, UO2, 49930 +27: 0.07843137, 206, 10811, 10809, UO2, 49930 +28: 0.07843137, 207, 11219, 11217, UO2, 49930 +29: 0.07843137, 208, 11627, 11625, UO2, 49930 +30: 0.07843137, 209, 12035, 12033, UO2, 49930 +31: 0.07843137, 210, 12443, 12441, UO2, 49930 +32: 0.07843137, 211, 12851, 12849, UO2, 49930 +33: 0.07843137, 212, 13259, 13257, UO2, 49930 +34: 0.07843137, 213, 13667, 13665, UO2, 49930 +35: 0.07843137, 214, 14075, 14073, UO2, 49930 +36: 0.07843137, 215, 14483, 14481, UO2, 49930 +37: 0.07843137, 216, 14891, 14889, UO2, 49930 +38: 0.07843137, 217, 15299, 15297, UO2, 49930 +39: 0.01960784, 218, -1, 15705, UO2, 49930 +40: 0.05882353, 219, 15707, -1, Water, 10083 +41: 0.07843137, 220, 16115, 16113, Water, 10083 +42: 0.07843137, 221, 16523, 16521, Water, 10083 +43: 0.07843137, 222, 16931, 16929, Water, 10083 +44: 0.07843137, 223, 17339, 17337, Water, 10083 +45: 0.07843137, 224, 17747, 17745, Water, 10083 +46: 0.07843137, 225, 18155, 18153, Water, 10083 +47: 0.07843137, 226, 18563, 18561, Water, 10083 +48: 0.07843137, 227, 18971, 18969, Water, 10083 +49: 0.07843137, 228, 19379, 19377, Water, 10083 +50: 0.07843137, 229, 19787, 19785, Water, 10083 +51: 0.07843137, 230, 20195, 20193, Water, 10083 +52: 0.07843137, 231, 20603, 20601, Water, 10083 +Reverse Diagonal Track 53 +0: 0.11091871, 65, 20804, 20806, Water, 10083 +1: 0.11091871, 64, 20388, 20390, Water, 10083 +2: 0.11091871, 63, 19972, 19974, Water, 10083 +3: 0.11091871, 62, 19556, 19558, Water, 10083 +4: 0.11091871, 61, 19140, 19142, Water, 10083 +5: 0.11091871, 60, 18724, 18726, Water, 10083 +6: 0.11091871, 59, 18308, 18310, Water, 10083 +7: 0.11091871, 58, 17892, 17894, Water, 10083 +8: 0.11091871, 57, 17476, 17478, Water, 10083 +9: 0.11091871, 56, 17060, 17062, Water, 10083 +10: 0.11091871, 55, 16644, 16646, Water, 10083 +11: 0.11091871, 54, 16228, 16230, Water, 10083 +12: 0.11091871, 53, 15812, 15814, Water, 10083 +13: 0.11091871, 52, 15396, 15398, Water, 10083 +14: 0.11091871, 51, 14980, 14982, Water, 10083 +15: 0.11091871, 50, 14564, 14566, Water, 10083 +16: 0.05372775, 49, -1, 14150, Water, 10083 +17: 0.05719096, 48, 14148, -1, UO2, 49930 +18: 0.11091871, 47, 13732, 13734, UO2, 49930 +19: 0.11091871, 46, 13316, 13318, UO2, 49930 +20: 0.11091871, 45, 12900, 12902, UO2, 49930 +21: 0.11091871, 44, 12484, 12486, UO2, 49930 +22: 0.11091871, 43, 12068, 12070, UO2, 49930 +23: 0.11091871, 42, 11652, 11654, UO2, 49930 +24: 0.11091871, 41, 11236, 11238, UO2, 49930 +25: 0.11091871, 40, 10820, 10822, UO2, 49930 +26: 0.11091871, 39, 10404, 10406, UO2, 49930 +27: 0.11091871, 38, 9988, 9990, UO2, 49930 +28: 0.11091871, 37, 9572, 9574, UO2, 49930 +29: 0.11091871, 36, 9156, 9158, UO2, 49930 +30: 0.11091871, 35, 8740, 8742, UO2, 49930 +31: 0.11091871, 34, 8324, 8326, UO2, 49930 +32: 0.11091871, 33, 7908, 7910, UO2, 49930 +33: 0.11091871, 32, 7492, 7494, UO2, 49930 +34: 0.11091871, 31, 7076, 7078, UO2, 49930 +35: 0.05719096, 30, -1, 6662, UO2, 49930 +36: 0.05372775, 29, 6660, -1, Water, 10083 +37: 0.11091871, 28, 6244, 6246, Water, 10083 +38: 0.11091871, 27, 5828, 5830, Water, 10083 +39: 0.11091871, 26, 5412, 5414, Water, 10083 +40: 0.11091871, 25, 4996, 4998, Water, 10083 +41: 0.11091871, 24, 4580, 4582, Water, 10083 +42: 0.11091871, 23, 4164, 4166, Water, 10083 +43: 0.11091871, 22, 3748, 3750, Water, 10083 +44: 0.11091871, 21, 3332, 3334, Water, 10083 +45: 0.11091871, 20, 2916, 2918, Water, 10083 +46: 0.11091871, 19, 2500, 2502, Water, 10083 +47: 0.11091871, 18, 2084, 2086, Water, 10083 +48: 0.11091871, 17, 1668, 1670, Water, 10083 +49: 0.11091871, 16, 1252, 1254, Water, 10083 +50: 0.11091871, 4, 836, 838, Water, 10083 +51: 0.11091871, 15, 420, 422, Water, 10083 +52: 0.11091871, 0, 4, 6, Water, 10083 diff --git a/tests/test_tracking_pin_cell_cmfd/test_tracking_pin_cell_cmfd.py b/tests/test_tracking_pin_cell_cmfd/test_tracking_pin_cell_cmfd.py new file mode 100644 index 000000000..471ca6a6b --- /dev/null +++ b/tests/test_tracking_pin_cell_cmfd/test_tracking_pin_cell_cmfd.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import os +import sys +import math +sys.path.insert(0, os.pardir) +sys.path.insert(0, os.path.join(os.pardir, 'openmoc')) +from testing_harness import TrackingTestHarness +from input_set import PinCellInput + +import openmoc + +class TrackingPinCellCMFDTestHarness(TrackingTestHarness): + """Tests tracking over a pin cell geometry with an overlaid CMFD mesh.""" + + def __init__(self): + super(TrackingPinCellCMFDTestHarness, self).__init__() + self.input_set = PinCellInput() + + def _setup(self): + """Initialize the materials, geometry, and tracks.""" + super(TrackingPinCellCMFDTestHarness, self)._create_geometry() + + # Initialize track objects + self.tracks['Diagonal Track'] = openmoc.Track() + self.tracks['Tangent Track'] = openmoc.Track() + self.tracks['Nudged Tangent Track'] = openmoc.Track() + self.tracks['Horizontal Track'] = openmoc.Track() + self.tracks['Vertical Track'] = openmoc.Track() + self.tracks['Reverse Diagonal Track'] = openmoc.Track() + + # Set track trajectories and locations + self.tracks['Diagonal Track'].setValues(-2, -2, 0, 2, 2, 0,\ + math.atan(1)) + offset = math.sqrt(2) - 2 + self.tracks['Tangent Track'].setValues(offset, -2, 0, 2, -offset,\ + 0, math.atan(1)) + offset -= 1e-6 + self.tracks['Nudged Tangent Track'].setValues(offset, -2, 0, 2,\ + -offset, 0, math.atan(1)) + self.tracks['Horizontal Track'].setValues(-2, 0, 0, 2, 0, 0, 0) + self.tracks['Vertical Track'].setValues(0, -2, 0, 0, 2, 0, math.pi/2) + self.tracks['Reverse Diagonal Track'].setValues(2, 2, 0, -2, -2, 0,\ + math.pi + math.atan(1)) + + def _run_openmoc(self): + """Segment tracks over the geometry and save the result to a string""" + + # Segmentize over the geometry with a fine and coarse cmfd mesh + for m in [3, 51]: + + # Overlay simple CMFD mesh + self._result += '{0} x {0} CMFD mesh\n'.format(m) + geometry = self.input_set.geometry + cmfd = openmoc.Cmfd() + cmfd.setLatticeStructure(m, m) + geometry.setCmfd(cmfd) + geometry.initializeCmfd() + + # Track over the composite geometry + super(TrackingPinCellCMFDTestHarness, self)._run_openmoc() + +if __name__ == '__main__': + harness = TrackingPinCellCMFDTestHarness() + harness.main() diff --git a/tests/testing_harness.py b/tests/testing_harness.py new file mode 100644 index 000000000..ca52bb7a9 --- /dev/null +++ b/tests/testing_harness.py @@ -0,0 +1,396 @@ +from __future__ import print_function + +import filecmp +import hashlib +import os +import shutil +import sys +import glob +import pickle +from collections import OrderedDict +from optparse import OptionParser +from PIL import Image, ImageOps + +sys.path.insert(0, 'openmoc') +import openmoc +import openmoc.plotter +import openmoc.process + +import numpy as np +import matplotlib +import matplotlib.pyplot as plt + + +class TestHarness(object): + """General class for running OpenMOC regression tests.""" + def __init__(self): + + openmoc.log.set_log_level('NORMAL') + + # Define default simulation parameters + self.spacing = 0.1 + self.num_azim = 4 + self.max_iters = 500 + self.tolerance = 1E-5 + + # Define threads based on OMP_NUM_THREADS env var set by run_tests.py + if 'OMP_NUM_THREADS' in os.environ: + self.num_threads = int(os.environ['OMP_NUM_THREADS']) + else: + self.num_threads = 1 + + self.input_set = None + self.track_generator = None + self.solver = None + self.solution_type = 'eigenvalue' + self.calculation_mode = openmoc.FORWARD + self.res_type = openmoc.FISSION_SOURCE + + self.parser = OptionParser() + self.parser.add_option('--update', dest='update', + action='store_true', default=False) + + self._opts = None + self._args = None + + + def _create_geometry(self): + """Initialize the materials and geometry in the InputSet.""" + self.input_set.create_materials() + self.input_set.create_geometry() + + def _create_trackgenerator(self): + """Instantiate a TrackGenerator.""" + geometry = self.input_set.geometry + self.track_generator = \ + openmoc.TrackGenerator(geometry, self.num_azim, self.spacing) + + def _create_solver(self): + """Instantiate a CPUSolver.""" + self.solver = openmoc.CPUSolver(self.track_generator) + self.solver.setNumThreads(self.num_threads) + self.solver.setConvergenceThreshold(self.tolerance) + + def _generate_tracks(self): + """Generate Tracks and segments.""" + # Always use 1 thread for FSR reproducibility + self.track_generator.setNumThreads(1) + self.track_generator.generateTracks() + + def _setup(self): + """Build materials, geometry and perform ray tracing.""" + self._create_geometry() + self._create_trackgenerator() + self._generate_tracks() + self._create_solver() + + + def main(self): + """Accept commandline arguments and either run or update tests.""" + (self._opts, self._args) = self.parser.parse_args() + if self._opts.update: + self._update_results() + else: + self._execute_test() + + def _execute_test(self): + """Build geometry, ray trace, run calculation, and verify results.""" + try: + self._setup() + self._run_openmoc() + results = self._get_results() + self._write_results(results) + self._compare_results() + finally: + self._cleanup() + + def _update_results(self): + """Update the results_true using the current version of OpenMOC.""" + try: + self._setup() + self._run_openmoc() + results = self._get_results() + self._write_results(results) + self._overwrite_results() + finally: + self._cleanup() + + def _run_openmoc(self): + """Run an OpenMOC eigenvalue or fixed source calculation.""" + + if self.solution_type == 'eigenvalue': + self.solver.computeEigenvalue(self.max_iters, res_type=self.res_type, + mode=self.calculation_mode) + elif self.solution_type == 'flux': + self.solver.computeFlux(self.max_iters) + elif self.solution_type == 'source': + self.solver.computeSource(self.max_iters, res_type=self.res_type, + mode=self.calculation_mode) + else: + msg = 'Unable to run OpenMOC in mode {0}'.format(self.solution_type) + raise ValueError(msg) + + def _get_results(self, num_iters=True, keff=True, fluxes=True, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=False): + """Digest info in the solver and return as a string.""" + + outstr = '' + + # Write out the number of iterations + if num_iters: + num_iters = self.solver.getNumIterations() + outstr += '# Iterations: {0}\n'.format(num_iters) + + # Write out the eigenvalue + if keff and self.solution_type == 'eigenvalue': + keff = self.solver.getKeff() + outstr += 'keff: {0:12.5E}\n'.format(keff) + + if fluxes: + # Get the fluxes for each FSR and energy group + fluxes = openmoc.process.get_scalar_fluxes(self.solver) + + # Create a list of the floating point flux values + fluxes = ['{0:12.6E}'.format(flux) for flux in fluxes.ravel()] + + # Add the fluxes to the output string + outstr += 'fluxes:\n' + outstr += '\n'.join(fluxes) + '\n' + + # Write out the number of FSRs + if num_fsrs: + num_fsrs = self.input_set.geometry.getNumFSRs() + outstr += '# FSRs: {0}\n'.format(num_fsrs) + + # Write out the number of tracks + if num_tracks: + num_tracks = self.track_generator.getNumTracks() + outstr += '# tracks: {0}\n'.format(num_tracks) + + # Write out the number of segments + if num_segments: + num_segments = self.track_generator.getNumSegments() + outstr += '# segments: {0}\n'.format(num_segments) + + # Hash the results if necessary. + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + def _write_results(self, results_string): + """Write the results to an ASCII file.""" + with open('results_test.dat', 'w') as fh: + fh.write(results_string) + + def _overwrite_results(self): + """Overwrite the results_true with the results_test.""" + shutil.copyfile('results_test.dat', 'results_true.dat') + + def _compare_results(self): + """Make sure the current results agree with the _true standard.""" + compare = filecmp.cmp('results_test.dat', 'results_true.dat') + if not compare: + os.rename('results_test.dat', 'results_error.dat') + assert compare, 'Results do not agree.' + + def _cleanup(self): + """Delete track, plot, etc. directories and test files.""" + + # Create list of directories and/or files to remove + outputs = [os.path.join(os.getcwd(), 'tracks')] + outputs.append(os.path.join(os.getcwd(), 'log')) + outputs.append(os.path.join(os.getcwd(), 'plots')) + outputs.append(os.path.join(os.getcwd(), 'simulation-states')) + outputs.append(os.path.join(os.getcwd(), 'fission-rates')) + outputs.append(os.path.join(os.getcwd(), 'results_test.dat')) + + # Remove each file / directory if it exists + for output in outputs: + if os.path.isfile(output): + os.remove(output) + elif os.path.isdir(output): + shutil.rmtree(output) + + +class HashedTestHarness(TestHarness): + """Specialized TestHarness that hashes the results.""" + + def _get_results(self): + """Digest info in the results and return as a string.""" + return super(HashedTestHarness, self)._get_results(hash_output=True) + + +class TrackingTestHarness(TestHarness): + """Specialized TestHarness for testing tracking.""" + + def __init__(self): + super(TrackingTestHarness, self).__init__() + self.tracks = OrderedDict() + self._result = '' + + def _segment_track(self, track, geometry): + """Segments a given track over a given geometry and records the + resulting segment information to a string""" + + # Segmentize a track in a geometry, recording the segments in a string + geometry.segmentize(track) + num_segments = track.getNumSegments() + info = ' ' + str(num_segments) + '\n' + for i in range(num_segments): + info += str(i) + ': ' + segment = track.getSegment(i) + info += str(round(segment._length, 8)) + ', ' + info += str(segment._region_id) + ', ' + info += str(segment._cmfd_surface_fwd) + ', ' + info += str(segment._cmfd_surface_bwd) + ', ' + info += str(segment._material.getName()) + ', ' + info += str(segment._material.getId()) + '\n' + track.clearSegments() + return info + + def _run_openmoc(self): + """Segment tracks over the geometry and save the result to a string""" + + # Segmentize tracks over the geometry + for track_name in self.tracks: + self._result += track_name + self._result += self._segment_track(self.tracks[track_name], + self.input_set.geometry) + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=True, num_segments=True, num_tracks=True, + hash_output=False): + """Return the result string""" + return self._result + + +class PlottingTestHarness(TestHarness): + """Specialized TestHarness for testing plotting.""" + + def __init__(self): + super(PlottingTestHarness, self).__init__() + self.figures = [] + + # Use standardized default matplotlib rcparams + rcparams = pickle.load(open('../rcparams.pkl', 'rb')) + openmoc.plotter.matplotlib_rcparams = rcparams + + def _get_results(self, num_iters=False, keff=False, fluxes=False, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=False): + + # Store each each Matplotlib figure / PIL Image + for i, fig in enumerate(self.figures): + test_filename = 'test-{0}.png'.format(i) + + # Save the figure to a file + if isinstance(fig, matplotlib.figure.Figure): + fig.set_size_inches(4., 4.) + fig.savefig(test_filename, bbox_inches='tight', dpi=100) + plt.close(fig) + else: + fig.save(test_filename) + + return '' + + def _write_results(self, results_string): + """Do nothing since the plots are created in _run_openmoce() method.""" + return + + def _overwrite_results(self): + """Overwrite the reference images with the test images.""" + + # Find all plot files + outputs = glob.glob(os.path.join(os.getcwd(), 'test-*.png')) + + # Copy each test plot as a new reference plot + for i in range(len(outputs)): + shutil.copyfile('test-{0}.png'.format(i), 'true-{0}.png'.format(i)) + + def _compare_results(self, max_distance=1.): + """Make sure the current results agree with the true standard.""" + + # Loop over each Matplotlib figure / PIL Image and + # compare to reference using Matplotlib fuzzy comparison + for i, fig in enumerate(self.figures): + + # Open test image and resize to that of the true image with PIL + img1 = Image.open('test-{0}.png'.format(i)) + img2 = Image.open('true-{0}.png'.format(i)) + img1 = ImageOps.fit(img1, img2.size, Image.ANTIALIAS) + + # Compute distance between each image in RGB space + distance = self._compare_images(img1, img2) + assert distance < max_distance, 'Results do not agree.' + + def _cleanup(self): + """Delete plot PNG files.""" + + # Find all test plot files + outputs = glob.glob(os.path.join(os.getcwd(), 'test-*.png')) + + # Remove each plot file if it exists + for i in range(len(outputs)): + output = 'test-{0}.png'.format(i) + if os.path.isfile(output): + os.remove(output) + elif os.path.isdir(output): + shutil.rmtree(output) + + super(PlottingTestHarness, self)._cleanup() + + def _compare_images(self, img1, img2): + """Compare two PIL images using in RGB space with pixel histograms.""" + + # Extract RGBA data from each PIL Image + rgba1 = np.array(img1) + rgba2 = np.array(img2) + + # Compute histograms of each images pixels + hr1, bins1 = np.histogram(rgba1[...,0], bins=256, normed=True) + hg1, bins1 = np.histogram(rgba1[...,1], bins=256, normed=True) + hb1, bins1 = np.histogram(rgba1[...,2], bins=256, normed=True) + hr2, bins2 = np.histogram(rgba2[...,0], bins=256, normed=True) + hg2, bins2 = np.histogram(rgba2[...,1], bins=256, normed=True) + hb2, bins2 = np.histogram(rgba2[...,2], bins=256, normed=True) + hist1 = np.array([hr1, hg1, hb1]).ravel() + hist2 = np.array([hr2, hg2, hb2]).ravel() + + # Compute cartesian distance between histograms in RGB space + diff = hist1 - hist2 + distance = np.sqrt(np.dot(diff, diff)) + return distance + + +class MultiSimTestHarness(TestHarness): + """Specialized TestHarness for testing multi-simulation capabilities.""" + + def __init__(self): + super(MultiSimTestHarness, self).__init__() + self.num_simulations = 3 + self.num_iters = [] + self.keffs = [] + + def _run_openmoc(self): + """Run multiple OpenMOC eigenvalue calculations.""" + + for i in range(self.num_simulations): + super(MultiSimTestHarness, self)._run_openmoc() + self.num_iters.append(self.solver.getNumIterations()) + self.keffs.append(self.solver.getKeff()) + + def _get_results(self, num_iterations=True, keff=True, fluxes=False, + num_fsrs=False, num_tracks=False, num_segments=False, + hash_output=False): + """Return eigenvalues from each simulation into a string.""" + + # Write out the iteration count and eigenvalues from each simulation + outstr = '' + for num_iters, keff in zip(self.num_iters, self.keffs): + outstr += 'Iters: {0}\tkeff: {1:12.5E}\n'.format(num_iters, keff) + + return outstr diff --git a/tests/travis.sh b/tests/travis.sh new file mode 100755 index 000000000..1a23dd33e --- /dev/null +++ b/tests/travis.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -ev + +# Run all debug tests +if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + ./run_tests.py +fi diff --git a/tests/update_results.py b/tests/update_results.py new file mode 100755 index 000000000..0d840161e --- /dev/null +++ b/tests/update_results.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import sys +import re +import subprocess +import shutil +from glob import glob +from optparse import OptionParser + +parser = OptionParser() +parser.add_option('-R', '--tests-regex', dest='regex_tests', + help="Run tests matching regular expression. \ + Test names are the directories present in tests folder.\ + This uses standard regex syntax to select tests.") +(opts, args) = parser.parse_args() +cwd = os.getcwd() + +# Terminal color configurations +OKGREEN = '\033[92m' +FAIL = '\033[91m' +ENDC = '\033[0m' +BOLD = '\033[1m' + +# Go into main OpenMOC directory +os.chdir('..') + +# Setup shell command to install OpenMOC with distutils +setup_cmd = [sys.executable, 'setup.py', 'install'] +setup_cmd += ['--install-purelib=tests/openmoc'] +setup_cmd += ['--fp=double', '--cc=gcc'] + +# Run setup.py to install openmoc +rc = subprocess.call(setup_cmd) +rc = subprocess.call(setup_cmd) + +# Check for error code +if rc != 0: + exit('Failed on setup.py') + +# Return to tests directory +os.chdir('tests') + +# Get a list of all test folders +folders = glob('test_*') + +# Check to see if a subset of tests is specified on command line +if opts.regex_tests is not None: + folders = [item for item in folders if re.search(opts.regex_tests, item)] + +# Loop around directories +for adir in sorted(folders): + + # Go into that directory + os.chdir(adir) + + # Print status to screen + print(adir, end="") + sz = len(adir) + for i in range(35 - sz): + print('.', end="") + + # Find the test executable + test_exec = glob('test_*.py') + assert len(test_exec) == 1, \ + 'There must be only one test executable per test directory' + + # Update the test results + proc = subprocess.Popen([sys.executable, test_exec[0], '--update']) + returncode = proc.wait() + if returncode == 0: + print(BOLD + OKGREEN + "[OK]" + ENDC) + else: + print(BOLD + FAIL + "[FAILED]" + ENDC) + + # Go back a directory + os.chdir('..') + +# Clear build directories for OpenMOC +shutil.rmtree('build', ignore_errors=True) +shutil.rmtree('openmoc', ignore_errors=True)