pax_global_header00006660000000000000000000000064131331442710014511gustar00rootroot0000000000000052 comment=f8a59094e7d13330f6e8ad4a335beedcf59188bf dune-istl-2.5.1/000077500000000000000000000000001313314427100134225ustar00rootroot00000000000000dune-istl-2.5.1/.gitignore000066400000000000000000000000141313314427100154050ustar00rootroot00000000000000*~ /build*/ dune-istl-2.5.1/.gitlab-ci.yml000066400000000000000000000012501313314427100160540ustar00rootroot00000000000000--- variables: DUNECI_BRANCH: releases/2.5 before_script: - duneci-install-module https://gitlab.dune-project.org/core/dune-common.git debian:9--gcc: image: duneci/base:9 script: duneci-standard-test debian:9--clang: image: duneci/base:9 script: duneci-standard-test --opts=/duneci/opts.clang debian:8--gcc: image: duneci/base:8 script: duneci-standard-test debian:8-backports--clang: image: duneci/base:8-backports script: duneci-standard-test --opts=/duneci/opts.clang ubuntu:16.04--gcc: image: duneci/base:16.04 script: duneci-standard-test ubuntu:16.04--clang: image: duneci/base:16.04 script: duneci-standard-test --opts=/duneci/opts.clang dune-istl-2.5.1/CMakeLists.txt000066400000000000000000000015211313314427100161610ustar00rootroot00000000000000# set up project project(dune-istl C CXX) # general stuff cmake_minimum_required(VERSION 2.8.12) # guess build tree of dune-common if(NOT (dune-common_DIR OR dune-common_ROOT OR "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) string(REPLACE ${CMAKE_PROJECT_NAME} dune-common dune-common_DIR ${PROJECT_BINARY_DIR}) endif() #find dune-common and set the module path find_package(dune-common REQUIRED) list(APPEND CMAKE_MODULE_PATH ${dune-common_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/modules") #include the dune macros include(DuneMacros) # start a dune project with information from dune.module dune_project() add_subdirectory(cmake/modules) add_subdirectory(dune) add_subdirectory(doc) add_subdirectory(lib) # finalize the dune project, e.g. generating config.h etc. finalize_dune_project(GENERATE_CONFIG_H_CMAKE) dune-istl-2.5.1/COPYING000077700000000000000000000000001313314427100160542LICENSE.mdustar00rootroot00000000000000dune-istl-2.5.1/INSTALL000066400000000000000000000046661313314427100144670ustar00rootroot00000000000000Installation Instructions ========================= For a full explanation of the DUNE installation process please read the installation notes [0]. The following introduction is meant for the impatient. Getting started --------------- Suppose you have downloaded all DUNE modules of interest to your computer and extracted then in one common directory. See [1] for a list of available modules. To compile the modules Dune has to check several components of your system and whether prerequisites within the modules are met. For the ease of users we have designed a custom build system on top of CMake. Run ./dune-common/bin/dunecontrol all to commence those tests and build all modules you have downloaded. Don't worry about messages telling you that libraries are missing: they are only needed for grid-self-checks we need for developing. You can customize the build to your specific needs by using an options file (see below) ./dune-common/bin/dunecontrol --opts=/path_to/file.opts If you did not tell dunecontrol to install with an options file you need to run ./dune-common/bin/dunecontrol make install to install Dune (you may need root-permissions for the install part depending on the prefix set) A more comprehensive introduction to the build system can be found in [0]. Passing options to the build process ------------------------------------ Using the dunecontrol script the following atomic commands can be executed: - configure (runs the CMake configuration tests for each module) - exec (executes a command in each module source directory) - bexec (executes a command in each module build directory) - make (builds each module) - update (updates the Git or Subversion version) The composite command all simply runs configure and make for each module. As it is often not convenient to specify the desired options after the duncontroll call, one can pass the options via a file specified by the --opts= option. Specify the options via the variable CMAKE_FLAGS= An example of an options file is # use a special compiler (g++ version 5.0), # install to a custom directory, default is /usr/local/bin, # disable the external library SuperLU, # and use Ninja-build instead of make as the build-tool CMAKE_FLAGS="-DCMAKE_CXX_COMPILER=g++-5 -DCMAKE_INSTALL_PREFIX='/tmp/HuHu' -DCMAKE_DISABLE_FIND_PACKAGE_SuperLU=true -GNinja" Links ----- 0. https://www.dune-project.org/doc/installation 1. https://www.dune-project.org/releases dune-istl-2.5.1/LICENSE.md000066400000000000000000000475151313314427100150420ustar00rootroot00000000000000Copyright holders: 2014--2016 Marco Agnese 2003--2013 Peter Bastian 2004--2016 Markus Blatt 2014--2016 Ansgar Burchardt 2004--2005 Adrian Burri 2008--2015 Andreas Dedner 2003--2016 Christian Engwer 2005--2016 Jorrit Fahlke 2008--2015 Bernd Flemisch 2005--2016 Carsten Gräser 2015--2016 Felix Gruber 2012--2016 Christoph Grüninger 2016 René Heß 2016 Stephan Hilb 2012--2013 Olaf Ippisch 2013--2016 Dominic Kempf 2015 Emmanouil Kiagias 2004--2016 Robert Klöfkorn 2016 Timo Koch 2007 Sreejith Pulloor Kuttanikkad 2013--2016 Arne Morten Kvarving (SINTEF) 2009--2013 Andreas Lauser 2012--2016 Tobias Malkmus 2007--2009 Sven Marnach 2013 René Milk 2013--2016 Steffen Müthing 2016 Maikel Nadolski 2003--2005 Thimo Neubauer 2010--2012 Rebecca Neumann 2008--2014 Martin Nolte 2012--2015 Andreas Nüßing 2013--2014 Marian Piatkowski 2011--2016 Elias Pipping 2013 Jurgis Pods 2009 Atgeirr Rasmussen 2008--2013 Uli Sack 2004--2016 Oliver Sander 2013 Bård Skaflestad 2006--2010 Martin Weiser 2015 Sebastian Westerheide 2011--2012 Matthias Wohlmuth 2014--2016 Jonathan Youett The DUNE library and headers are licensed under version 2 of the GNU General Public License (see below), with a special exception for linking and compiling against DUNE, the so-called "runtime exception." The license is intended to be similar to the GNU Lesser General Public License, which by itself isn't suitable for a template library. The exact wording of the exception reads as follows: As a special exception, you may use the DUNE source files as part of a software library or application without restriction. Specifically, if other files instantiate templates or use macros or inline functions from one or more of the DUNE source files, or you compile one or more of the DUNE source files and link them with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dune-istl-2.5.1/README.md000066400000000000000000000016451313314427100147070ustar00rootroot00000000000000DUNE-library ============ DUNE, the Distributed and Unified Numerics Environment is a modular toolbox for solving partial differential equations with grid-based methods. The main intention is to create slim interfaces allowing an efficient use of legacy and/or new libraries. Using C++ techniques DUNE allows to use very different implementation of the same concept (i.e. grid, solver, ...) under a common interface with a very low overhead. DUNE was designed with flexibility in mind. It supports easy discretization using methods, like Finite Elements, Finite Volume and also Finite Differences. Through separation of data structures DUNE allows fast Linear Algebra like provided in the ISTL module, or usage of external libraries like blas. This package contains the basic DUNE istl classes. More information ---------------- Check dune-common for more details concerning dependencies, known bugs, license and installation. dune-istl-2.5.1/cmake/000077500000000000000000000000001313314427100145025ustar00rootroot00000000000000dune-istl-2.5.1/cmake/modules/000077500000000000000000000000001313314427100161525ustar00rootroot00000000000000dune-istl-2.5.1/cmake/modules/AddARPACKPPFlags.cmake000066400000000000000000000013131313314427100217410ustar00rootroot00000000000000# Defines the functions to use ARPACKPP # # .. cmake_function:: add_dune_arpackpp_flags # # .. cmake_param:: targets # :positional: # :single: # :required: # # A list of targets to use ARPACKPP with. # function(add_dune_arpackpp_flags _targets) if(ARPACKPP_FOUND) foreach(_target ${_targets}) target_link_libraries(${_target} ${ARPACKPP_DUNE_LIBRARIES}) get_target_property(_props ${_target} COMPILE_FLAGS) string(REPLACE "_props-NOTFOUND" "" _props "${_props}") set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "${_props} ${ARPACKPP_DUNE_COMPILE_FLAGS} -DENABLE_ARPACKPP=1") endforeach() endif() endfunction(add_dune_arpackpp_flags) dune-istl-2.5.1/cmake/modules/AddSuperLUFlags.cmake000066400000000000000000000015171313314427100221050ustar00rootroot00000000000000# Defines the functions to use SuperLU # # .. cmake_function:: add_dune_superlu_flags # # .. cmake_param:: targets # :positional: # :single: # :required: # # A list of targets to use SuperLU with. # function(add_dune_superlu_flags) if(SUPERLU_FOUND) cmake_parse_arguments(_add_superlu "OBJECT" "" "" ${ARGN}) foreach(_target ${_add_superlu_UNPARSED_ARGUMENTS}) if(NOT _add_superlu_OBJECT) target_link_libraries(${_target} ${SUPERLU_DUNE_LIBRARIES}) endif() get_target_property(_props ${_target} COMPILE_FLAGS) string(REPLACE "_props-NOTFOUND" "" _props "${_props}") set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "${_props} ${SUPERLU_DUNE_COMPILE_FLAGS} -DENABLE_SUPERLU=1") endforeach() endif(SUPERLU_FOUND) endfunction(add_dune_superlu_flags) dune-istl-2.5.1/cmake/modules/CMakeLists.txt000066400000000000000000000003241313314427100207110ustar00rootroot00000000000000set(modules AddARPACKPPFlags.cmake AddSuperLUFlags.cmake DuneIstlMacros.cmake FindARPACK.cmake FindARPACKPP.cmake FindSuperLU.cmake) install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR}) dune-istl-2.5.1/cmake/modules/DuneIstlMacros.cmake000066400000000000000000000005621313314427100220530ustar00rootroot00000000000000# .. cmake_module:: # # This modules content is executed whenever a module required or suggests dune-istl! # find_package(METIS) find_package(ParMETIS) include(AddParMETISFlags) find_package(SuperLU) include(AddSuperLUFlags) find_package(ARPACKPP) include(AddARPACKPPFlags) find_package(SuiteSparse OPTIONAL_COMPONENTS LDL SPQR UMFPACK) include(AddSuiteSparseFlags) dune-istl-2.5.1/cmake/modules/FindARPACK.cmake000066400000000000000000000053401313314427100207200ustar00rootroot00000000000000# .. cmake_module:: # # Module that checks whether ARPACK is available and usable. # # Variables used by this module which you may want to set: # # :ref:`ARPACK_ROOT` # Path list to search for ARPACK. # # Sets the following variables: # # :code:`ARPACK_FOUND` # True if ARPACK available. # # :code:`ARPACK_LIBRARIES` # Link against these libraries to use ARPACK. # # .. cmake_variable:: ARPACK_ROOT # # You may set this variable to have :ref:`FindARPACK` look # for the ARPACK package in the given path before inspecting # system paths. # # check for Fortran support which is required by ARPACK if(NOT(Fortran_Works)) message(WARNING "Fortran doesn't seem to be supported, skipping search for ARPACK.") # log errornous result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determing location of ARPACK failed:\n" "Fortran support is required but could not be detected\n\n") return() endif() # look for library, only at positions given by the user find_library(ARPACK_LIBRARY NAMES "arpack" PATHS ${ARPACK_PREFIX} ${ARPACK_ROOT} PATH_SUFFIXES "lib" "lib32" "lib64" NO_DEFAULT_PATH ) # look for library files, including default paths find_library(ARPACK_LIBRARY NAMES "arpack" PATH_SUFFIXES "lib" "lib32" "lib64" ) # check header usability include(CMakePushCheckState) cmake_push_check_state() # we need if clauses here because variable is set variable-NOTFOUND if the # searches above were not successful; without them CMake print errors like: # "CMake Error: The following variables are used in this project, but they # are set to NOTFOUND. Please set them or make sure they are set and tested # correctly in the CMake files." if(ARPACK_LIBRARY) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ARPACK_LIBRARY}) endif() # end of header usability check cmake_pop_check_state() # behave like a CMake module is supposed to behave include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "ARPACK" DEFAULT_MSG ARPACK_LIBRARY ) # hide the introduced cmake cached variables in cmake GUIs mark_as_advanced(ARPACK_LIBRARY) # if headers are found, store results if(ARPACK_FOUND) set(ARPACK_LIBRARIES ${ARPACK_LIBRARY}) # log result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determing location of ARPACK succeeded:\n" "Libraries to link against: ${ARPACK_LIBRARIES}\n\n") set(ARPACK_DUNE_LIBRARIES ${ARPACK_LIBRARIES} CACHE STRING "Libraries used by DUNE when linking ARPACK programs") else() # log errornous result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determing location of ARPACK failed:\n" "Libraries to link against: ${ARPACK_LIBRARIES}\n\n") endif() dune-istl-2.5.1/cmake/modules/FindARPACKPP.cmake000066400000000000000000000100171313314427100211550ustar00rootroot00000000000000# .. cmake_module:: # # Module that checks whether ARPACK++ is available and usable. # # Variables used by this module which you may want to set: # # :ref:`ARPACKPP_ROOT` # Path list to search for ARPACK++. # # Sets the following variables: # # :code:`ARPACKPP_FOUND` # True if ARPACK++ available. # # :code:`ARPACKPP_INCLUDE_DIRS` # Path to the ARPACK++ include directories. # # :code:`ARPACKPP_LIBRARIES` # Link against these libraries to use ARPACK++. # # .. cmake_variable:: ARPACKPP_ROOT # # You may set this variable to have :ref:`FindARPACKPP` look # for the ARPACKPP package in the given path before inspecting # system paths. # # find ARPACK which is required by ARPACK++ find_package(ARPACK) # look for header files, only at positions given by the user find_path(ARPACKPP_INCLUDE_DIR NAMES "arssym.h" PATHS ${ARPACKPP_PREFIX} ${ARPACKPP_ROOT} PATH_SUFFIXES "include" "include/arpack++" NO_DEFAULT_PATH ) # look for header files, including default paths find_path(ARPACKPP_INCLUDE_DIR NAMES "arssym.h" PATH_SUFFIXES "include" "include/arpack++" ) # The arpack++ package in Debian also includes a shared library that we have # to link to. Other versions of arpack++ are header-only. # Thus we will later use the arpack++ shared library if found and just ignore # it if it was not found. find_library(ARPACKPP_LIBRARY NAMES "arpack++" PATH_SUFFIXES "lib" "lib32" "lib64" ) # check header usability include(CMakePushCheckState) cmake_push_check_state() # we need if clauses here because variable is set variable-NOTFOUND if the # searches above were not successful; without them CMake print errors like: # "CMake Error: The following variables are used in this project, but they # are set to NOTFOUND. Please set them or make sure they are set and tested # correctly in the CMake files." if(ARPACKPP_INCLUDE_DIR) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARPACKPP_INCLUDE_DIR}) if(ARPACKPP_LIBRARY) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ARPACK_LIBRARIES} ${ARPACKPP_LIBRARY}) else() set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ARPACK_LIBRARIES}) endif() endif() # end of header usability check cmake_pop_check_state() # behave like a CMake module is supposed to behave include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "ARPACKPP" DEFAULT_MSG ARPACK_FOUND ARPACKPP_INCLUDE_DIR ) # hide the introduced cmake cached variables in cmake GUIs mark_as_advanced(ARPACKPP_INCLUDE_DIR ARPACKPP_LIBRARY) # if headers are found, store results if(ARPACKPP_FOUND) set(ARPACKPP_INCLUDE_DIRS ${ARPACKPP_INCLUDE_DIR}) if(ARPACKPP_LIBRARY) set(ARPACKPP_LIBRARIES ${ARPACKPP_LIBRARY} ${ARPACK_LIBRARIES}) else(ARPACKPP_LIBRARY) set(ARPACKPP_LIBRARIES ${ARPACK_LIBRARIES}) endif(ARPACKPP_LIBRARY) # log result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determing location of ARPACK++ succeeded:\n" "Include directory: ${ARPACKPP_INCLUDE_DIRS}\n" "Libraries to link against: ${ARPACKPP_LIBRARIES}\n\n") set(ARPACKPP_DUNE_COMPILE_FLAGS "-I${ARPACKPP_INCLUDE_DIRS}" CACHE STRING "Compile flags used by DUNE when compiling ARPACK++ programs") set(ARPACKPP_DUNE_LIBRARIES ${ARPACKPP_LIBRARIES} CACHE STRING "Libraries used by DUNE when linking ARPACK++ programs") else() # log errornous result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determing location of ARPACK++ failed:\n" "Include directory: ${ARPACKPP_INCLUDE_DIRS}\n" "Libraries to link against: ${ARPACKPP_LIBRARIES}\n\n") endif() # set HAVE_ARPACKPP for config.h set(HAVE_ARPACKPP ${ARPACKPP_FOUND}) # register all ARPACK++ related flags if(ARPACKPP_FOUND) dune_register_package_flags(COMPILE_DEFINITIONS "ENABLE_ARPACKPP=1" LIBRARIES "${ARPACKPP_LIBRARIES}" INCLUDE_DIRS "${ARPACKPP_INCLUDE_DIRS}") endif() dune-istl-2.5.1/cmake/modules/FindSuperLU.cmake000066400000000000000000000135001313314427100213130ustar00rootroot00000000000000# .. cmake_module:: # # Module that checks whether SuperLU is available and usable. # SuperLU must be 4.0 or newer. # # Variables used by this module which you may want to set: # # :ref:`SUPERLU_ROOT` # Path list to search for SuperLU # # Sets the follwing variables: # # :code:`SUPERLU_FOUND` # True if SuperLU available and usable. # # :code:`SUPERLU_MIN_VERSION_4` # True if SuperLU version >= 4.0. # # :code:`SUPERLU_MIN_VERSION_4_3` # True if SuperLU version >= 4.3. # # :code:`SUPERLU_MIN_VERSION_5` # True if SuperLU version >= 5.0. # # :code:`SUPERLU_WITH_VERSION` # Human readable string containing version information. # # :code:`SUPERLU_INCLUDE_DIRS` # Path to the SuperLU include dirs. # # :code:`SUPERLU_LIBRARIES` # Name to the SuperLU library. # # .. cmake_variable:: SUPERLU_ROOT # # You may set this variable to have :ref:`FindSuperLU` look # for the SuperLU package in the given path before inspecting # system paths. # find_package(BLAS QUIET) # look for header files, only at positions given by the user find_path(SUPERLU_INCLUDE_DIR NAMES supermatrix.h PATHS ${SUPERLU_PREFIX} ${SUPERLU_ROOT} PATH_SUFFIXES "superlu" "SuperLU" "include/superlu" "include" "SRC" NO_DEFAULT_PATH ) # look for header files, including default paths find_path(SUPERLU_INCLUDE_DIR NAMES supermatrix.h PATH_SUFFIXES "superlu" "SuperLU" "include/superlu" "include" "SRC" ) # look for library, only at positions given by the user find_library(SUPERLU_LIBRARY NAMES "superlu" "superlu_5.2.1" "superlu_5.2" "superlu_5.1.1" "superlu_5.1" "superlu_5.0" "superlu_4.3" "superlu_4.2" "superlu_4.1" "superlu_4.0" PATHS ${SUPERLU_PREFIX} ${SUPERLU_ROOT} PATH_SUFFIXES "lib" "lib32" "lib64" NO_DEFAULT_PATH ) # look for library files, including default paths find_library(SUPERLU_LIBRARY NAMES "superlu" "superlu_5.2.1" "superlu_5.2" "superlu_5.1.1" "superlu_5.1" "superlu_5.0" "superlu_4.3" "superlu_4.2" "superlu_4.1" "superlu_4.0" PATH_SUFFIXES "lib" "lib32" "lib64" ) # check version specific macros include(CheckCSourceCompiles) include(CMakePushCheckState) cmake_push_check_state() # we need if clauses here because variable is set variable-NOTFOUND # if the searches above were not successful # Without them CMake print errors like: # "CMake Error: The following variables are used in this project, but they are set to NOTFOUND. # Please set them or make sure they are set and tested correctly in the CMake files:" # if(SUPERLU_INCLUDE_DIR) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${SUPERLU_INCLUDE_DIR}) endif(SUPERLU_INCLUDE_DIR) if(SUPERLU_LIBRARY) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${SUPERLU_LIBRARY}) endif(SUPERLU_LIBRARY) if(BLAS_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${BLAS_LIBRARIES}) endif(BLAS_LIBRARIES) # check wether version is new enough >= 4.0 check_c_source_compiles(" typedef int int_t; #include #include int main() { SuperLUStat_t stat; stat.expansions=8; return 0; }" SUPERLU_MIN_VERSION_4) # check whether version is at least 4.3 check_c_source_compiles(" #include int main(void) { return SLU_DOUBLE; }" SUPERLU_MIN_VERSION_4_3) # check whether version is at least 5.0 check_c_source_compiles(" typedef int int_t; #include #include int main(void) { GlobalLU_t glu; return 0; }" SUPERLU_MIN_VERSION_5) cmake_pop_check_state() if(NOT SUPERLU_MIN_VERSION_4) set(SUPERLU_WITH_VERSION "SuperLU < 4.0" CACHE STRING "Human readable string containing SuperLU version information.") else() if(SUPERLU_MIN_VERSION_5) set(SUPERLU_WITH_VERSION "SuperLU >= 5.0" CACHE STRING "Human readable string containing SuperLU version information.") elseif(SUPERLU_MIN_VERSION_4_3) set(SUPERLU_WITH_VERSION "SuperLU >= 4.3" CACHE STRING "Human readable string containing SuperLU version information.") else() set(SUPERLU_WITH_VERSION "SuperLU <= 4.2 and >= 4.0" CACHE STRING "Human readable string containing SuperLU version information.") endif() endif() # behave like a CMake module is supposed to behave include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "SuperLU" DEFAULT_MSG BLAS_FOUND SUPERLU_INCLUDE_DIR SUPERLU_LIBRARY SUPERLU_MIN_VERSION_4 ) mark_as_advanced(SUPERLU_INCLUDE_DIR SUPERLU_LIBRARY) set_package_info("SuperLU" "Direct linear solver library") # if both headers and library are found, store results if(SUPERLU_FOUND) set(SUPERLU_INCLUDE_DIRS ${SUPERLU_INCLUDE_DIR}) set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARY}) # log result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining location of ${SUPERLU_WITH_VERSION} succeeded:\n" "Include directory: ${SUPERLU_INCLUDE_DIRS}\n" "Library directory: ${SUPERLU_LIBRARIES}\n\n") set(SUPERLU_DUNE_COMPILE_FLAGS "-I${SUPERLU_INCLUDE_DIRS}" CACHE STRING "Compile flags used by DUNE when compiling SuperLU programs") set(SUPERLU_DUNE_LIBRARIES ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES} CACHE STRING "Libraries used by DUNE when linking SuperLU programs") else(SUPERLU_FOUND) # log errornous result file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining location of SuperLU failed:\n" "Include directory: ${SUPERLU_INCLUDE_DIRS}\n" "Library directory: ${SUPERLU_LIBRARIES}\n" "Found unsupported version: ${SUPERLU_WITH_VERSION}\n\n") endif(SUPERLU_FOUND) # set HAVE_SUPERLU for config.h set(HAVE_SUPERLU ${SUPERLU_FOUND}) # register all superlu related flags if(SUPERLU_FOUND) dune_register_package_flags(COMPILE_DEFINITIONS "ENABLE_SUPERLU=1" LIBRARIES "${SUPERLU_DUNE_LIBRARIES}" INCLUDE_DIRS "${SUPERLU_INCLUDE_DIRS}") endif() dune-istl-2.5.1/config.h.cmake000066400000000000000000000036031313314427100161210ustar00rootroot00000000000000/* begin dune-istl put the definitions for config.h specific to your project here. Everything above will be overwritten */ /* begin private */ /* Name of package */ #define PACKAGE "@DUNE_MOD_NAME@" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@" /* Define to the full name of this package. */ #define PACKAGE_NAME "@DUNE_MOD_NAME@" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "@DUNE_MOD_NAME@" /* Define to the home page for this package. */ #define PACKAGE_URL "@DUNE_MOD_URL@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@DUNE_MOD_VERSION@" /* end private */ /* Define to ENABLE_SUPERLU if the SuperLU library is available */ #cmakedefine HAVE_SUPERLU ENABLE_SUPERLU /* Define to ENABLE_ARPACKPP if the ARPACK++ library is available */ #cmakedefine HAVE_ARPACKPP ENABLE_ARPACKPP /* Define to 0 as all versions since SuperLu 4.0 do no longer provide it that way. */ #define HAVE_MEM_USAGE_T_EXPANSIONS 1 /* define to 1 if SuperLU header slu_ddefs.h contains SLU_DOUBLE */ #cmakedefine SUPERLU_MIN_VERSION_4_3 @SUPERLU_MIN_VERSION_4_3@ /* define to 1 if SuperLU dgssvx takes a GlobalLU_t parameter */ #cmakedefine SUPERLU_MIN_VERSION_5 @SUPERLU_MIN_VERSION_5@ /* Define to the version of dune-istl */ #define DUNE_ISTL_VERSION "${DUNE_ISTL_VERSION}" /* Define to the major version of dune-istl */ #define DUNE_ISTL_VERSION_MAJOR ${DUNE_ISTL_VERSION_MAJOR} /* Define to the minor version of dune-istl */ #define DUNE_ISTL_VERSION_MINOR ${DUNE_ISTL_VERSION_MINOR} /* Define to the revision of dune-istl */ #define DUNE_ISTL_VERSION_REVISION ${DUNE_ISTL_VERSION_REVISION} /* end dune-istl Everything below here will be overwritten */ dune-istl-2.5.1/doc/000077500000000000000000000000001313314427100141675ustar00rootroot00000000000000dune-istl-2.5.1/doc/CMakeLists.txt000066400000000000000000000002751313314427100167330ustar00rootroot00000000000000add_subdirectory(doxygen) dune_add_latex_document(istl.tex FORCE_DVI BIBFILES istl.bib IMAGES blockstructure.eps) create_doc_install(istl.pdf ${CMAKE_INSTALL_DOCDIR} istl_safepdf) dune-istl-2.5.1/doc/blockstructure.eps000066400000000000000000032156221313314427100177660ustar00rootroot00000000000000%!PS-Adobe-3.0 EPSF-3.0 %%Creator: (ImageMagick) %%Title: (blockstructure.eps) %%CreationDate: (Mon Sep 11 15:40:16 2006) %%BoundingBox: 0 0 712 197 %%HiResBoundingBox: 0 0 712 197 %%DocumentData: Clean7Bit %%LanguageLevel: 1 %%Pages: 1 %%EndComments %%BeginDefaults %%EndDefaults %%BeginProlog % % Display a color image. The image is displayed in color on % Postscript viewers or printers that support color, otherwise % it is displayed as grayscale. % /DirectClassPacket { % % Get a DirectClass packet. % % Parameters: % red. % green. % blue. % length: number of pixels minus one of this color (optional). % currentfile color_packet readhexstring pop pop compression 0 eq { /number_pixels 3 def } { currentfile byte readhexstring pop 0 get /number_pixels exch 1 add 3 mul def } ifelse 0 3 number_pixels 1 sub { pixels exch color_packet putinterval } for pixels 0 number_pixels getinterval } bind def /DirectClassImage { % % Display a DirectClass image. % systemdict /colorimage known { columns rows 8 [ columns 0 0 rows neg 0 rows ] { DirectClassPacket } false 3 colorimage } { % % No colorimage operator; convert to grayscale. % columns rows 8 [ columns 0 0 rows neg 0 rows ] { GrayDirectClassPacket } image } ifelse } bind def /GrayDirectClassPacket { % % Get a DirectClass packet; convert to grayscale. % % Parameters: % red % green % blue % length: number of pixels minus one of this color (optional). % currentfile color_packet readhexstring pop pop color_packet 0 get 0.299 mul color_packet 1 get 0.587 mul add color_packet 2 get 0.114 mul add cvi /gray_packet exch def compression 0 eq { /number_pixels 1 def } { currentfile byte readhexstring pop 0 get /number_pixels exch 1 add def } ifelse 0 1 number_pixels 1 sub { pixels exch gray_packet put } for pixels 0 number_pixels getinterval } bind def /GrayPseudoClassPacket { % % Get a PseudoClass packet; convert to grayscale. % % Parameters: % index: index into the colormap. % length: number of pixels minus one of this color (optional). % currentfile byte readhexstring pop 0 get /offset exch 3 mul def /color_packet colormap offset 3 getinterval def color_packet 0 get 0.299 mul color_packet 1 get 0.587 mul add color_packet 2 get 0.114 mul add cvi /gray_packet exch def compression 0 eq { /number_pixels 1 def } { currentfile byte readhexstring pop 0 get /number_pixels exch 1 add def } ifelse 0 1 number_pixels 1 sub { pixels exch gray_packet put } for pixels 0 number_pixels getinterval } bind def /PseudoClassPacket { % % Get a PseudoClass packet. % % Parameters: % index: index into the colormap. % length: number of pixels minus one of this color (optional). % currentfile byte readhexstring pop 0 get /offset exch 3 mul def /color_packet colormap offset 3 getinterval def compression 0 eq { /number_pixels 3 def } { currentfile byte readhexstring pop 0 get /number_pixels exch 1 add 3 mul def } ifelse 0 3 number_pixels 1 sub { pixels exch color_packet putinterval } for pixels 0 number_pixels getinterval } bind def /PseudoClassImage { % % Display a PseudoClass image. % % Parameters: % class: 0-PseudoClass or 1-Grayscale. % currentfile buffer readline pop token pop /class exch def pop class 0 gt { currentfile buffer readline pop token pop /depth exch def pop /grays columns 8 add depth sub depth mul 8 idiv string def columns rows depth [ columns 0 0 rows neg 0 rows ] { currentfile grays readhexstring pop } image } { % % Parameters: % colors: number of colors in the colormap. % colormap: red, green, blue color packets. % currentfile buffer readline pop token pop /colors exch def pop /colors colors 3 mul def /colormap colors string def currentfile colormap readhexstring pop pop systemdict /colorimage known { columns rows 8 [ columns 0 0 rows neg 0 rows ] { PseudoClassPacket } false 3 colorimage } { % % No colorimage operator; convert to grayscale. % columns rows 8 [ columns 0 0 rows neg 0 rows ] { GrayPseudoClassPacket } image } ifelse } ifelse } bind def /DisplayImage { % % Display a DirectClass or PseudoClass image. % % Parameters: % x & y translation. % x & y scale. % label pointsize. % image label. % image columns & rows. % class: 0-DirectClass or 1-PseudoClass. % compression: 0-none or 1-RunlengthEncoded. % hex color packets. % gsave /buffer 512 string def /byte 1 string def /color_packet 3 string def /pixels 768 string def currentfile buffer readline pop token pop /x exch def token pop /y exch def pop x y translate currentfile buffer readline pop token pop /x exch def token pop /y exch def pop currentfile buffer readline pop token pop /pointsize exch def pop /Times-Roman findfont pointsize scalefont setfont x y scale currentfile buffer readline pop token pop /columns exch def token pop /rows exch def pop currentfile buffer readline pop token pop /class exch def pop currentfile buffer readline pop token pop /compression exch def pop class 0 gt { PseudoClassImage } { DirectClassImage } ifelse grestore } bind def %%EndProlog %%Page: 1 1 %%PageBoundingBox: 0 0 712 197 userdict begin DisplayImage 0 0 712 197 12.000000 712 197 0 0 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3535352E2D2E2E2D2E2E2D2E 2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E1615162E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E 2E2D2E2E2D2E2E2D2E2E2D2E1615162E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E 1D1D1D3E3E3E777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777383838777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777777777777777777777777777777777777777777777777777771919192E2D2E2E2D2E 2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E1615162E2D2E2E2D2E2E2D2E2E2D2E2E2D2E 2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E1615162E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E 2E2D2E2E2D2E191919777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777383838777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777444444FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2E615F61615F61615F61615F61 615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61 403F40777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777373637615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F61535253414141777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777383838777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777666666FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A1616162E2D2E2E2D2E2E2D2E2E2D2E2E2D2E 1A1A1A3838383838383838383838383838381B1B1B383838383838383838383838383838 3838383838381B1B1B3838383838383838383838383838383838381B1B1B383838383838 3838383838383838383838381B1B1B383838383838383838383838383838383838383838 171717777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777585858585858777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777770E0E0E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2727271F1F1F383838383838383838 3838383838381B1B1B3838383838383838383838383838383838383838381B1B1B383838 3838383838383838383838383838381B1B1B383838383838383838383838383838383838 1B1B1B3838383838383838383838383838383838382929298A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1010102E2D2E2E2D2E2E2D2E2E2D2E 2221222221222E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E151515777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777585858585858777777777777777777777777777777777777777777 777777777777777777777777777777777777383838777777777777777777777777777777 7777777777777777777777777777777777777777777777770E0E0E2E2D2E2E2D2E2E2D2E 2E2D2E2221222221222E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E2E2D2E151515777777 777777777777777777777777777777777777777777777777777777777777777777414141 0000000404042E2D2E2E2D2E2E2D2E2E2D2E181818777777777777777777777777585858 585858777777777777777777777777383838777777777777777777777777777777383838 777777777777777777777777585858585858777777777777777777777777383838777777 777777777777777777777777383838777777777777777777777777585858585858777777 777777777777777777383838777777777777777777777777777777666666FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF787878232223555455555455555455555455555455 2F2E2F5858585858585858585858585858582A2A2A777777777777777777777777777777 777777777777353535585858585858585858585858585858585858313131777777777777 777777777777777777777777383838777777777777777777777777777777777777777777 2A2A2AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF191919555455555455555455555455555455464546393939585858585858585858 5858585858583131317777777777777777777777777777777777777777772D2D2D585858 585858585858585858585858585858353535777777777777777777777777777777777777 3838387777777777777777777777777777777777774141418A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777535253989598989598989598989598494849FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6968696E6D6E989598989598989598989598 9895984D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5A5A5A989598989598989598989598989598434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4D9895989895989895989895989895986E6D6E585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF2E2E2E615F61615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61353435727272FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2E2E615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F612E2E2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF333333615F61615F61615F61615F61615F61615F61615F612E2D2E 615F61615F61615F61615F61615F61615F61615F61615F61393939FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF393939615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F614746478A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCE CECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598 CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61615F61474647474647615F61 615F61615F61615F61615F61615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000070707615F61615F61 615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777615F61CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE555455FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5A5A5ACECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCE CECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598 CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF818181666666BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 4D4D4D3A3A3A4443444443444443444443442A2A2A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A4544454F4E4F5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3F3F3FBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF313131BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A424142444344444344444344 4443444443442F2F2F8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A3232325E5D5E 5E5D5E5E5D5E5E5D5E5E5D5E505050414141BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB6666668A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF818181666666BBBBBB BBBBBBBBBBBBBBBBBBBBBBBB3838389895989895989895989895989895983434346E6D6E 9895989895989895989895989895989895986E6D6E8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB BBBBBB5252525050505E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3F3F3FBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313131BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 4B4A4B9895989895989895989895986E6D6E424142989598989598989598989598989598 989598989598464646BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3636365E5D5E5E5D5E 5E5D5E5E5D5E5E5D5E505050414141BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB666666 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A0000000F0F0FCECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF2020203232323232323232323232322C2C2C2C2C2C323232323232 3232323232323232323232323232321111113130313130313130313130313130311D1D1D 3130313130313130313130313130313130313130310E0E0E777777777777777777777777 7777777777777777777777777777777777777777777777777777771A1A1A313031313031 3130313130313130311D1D1D3130313130313130313130313130313130313130311F1F1F 414141777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 7777777777777777777777771919193232323232323232323232322C2C2C2C2C2C323232 323232323232323232323232323232323232212121777777777777777777777777777777 777777777777777777777777777777777777777777414141000000040404323232323232 3232323232320C0C0C3130313130313130313130311F1E1F414141777777777777777777 777777383838777777777777777777777777777777383838777777777777777777777777 585858585858777777777777777777777777383838777777777777777777777777777777 383838777777777777777777777777585858585858777777777777777777777777383838 777777777777777777777777777777585858FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCE CECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598 CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF2E2E2E4342434342434342434342434342434342434342433B3A3B 434243434243434243434243434243434243434243434243252425555455555455555455 555455555455555455555455333333555455555455555455555455555455555455555455 555455555455555455555455333333555455555455555455555455555455555455555455 5554555554555554552C2C2C434243434243434243434243434243434243434243434243 4342434342433B3A3B434243434243434243434243434243434243434243434243434243 4342434342433B3A3B434243434243434243434243434243434243434243434243434243 4342433B3A3B434243434243434243434243434243434243434243434243434243434243 3B3A3B434243434243434243434243434243434243434243434243434243434243434243 4342434342433838384D4D4D777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777383838777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCE CECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 323232989598989598989598989598989598989598989598989598484648989598989598 989598989598989598989598989598989598989598989598484648989598989598989598 9895989895989895989895985351537B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232989598989598989598989598989598989598989598989598484648989598 989598989598989598989598989598989598989598989598989598484648989598989598 989598989598989598989598989598989598323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598 CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF323232989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598989598989598 4846489895989895989895989895989895989895989895985351537B7B7BFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF818181666666BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3E3E3E5C5B5C5C5B5C5C5B5C 5C5B5C5C5B5C2D2D2D5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5251526F6F6F 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A4B4A4B5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E 515151BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313131BBBBBBBBBBBB BBBBBBBBBBBBBBBBBB8A8A8A4242425C5B5C5C5B5C5C5B5C5C5B5C5C5B5C3B3A3B5E5D5E 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3C3C3C8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A3C3C3C5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E474747BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB6666668A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF818181292929615F61615F61615F61615F61615F61 3C3C3CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858535253989598989598989598989598989598464546BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB585858363536615F61615F61615F61615F61615F61535253 2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF1D1D1D615F61615F61615F61615F61615F61535253666666BBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB464646989598 989598989598989598989598989598383838BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 383838615F61615F61615F61615F61615F61615F612525258A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE CECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF252525615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61 615F61615F61615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2E2E615F61615F61615F61615F61615F612E2D2E 615F61615F61615F61615F61615F61615F61615F613534358A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61 615F61615F61615F613534358A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61 CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF333333615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61393939 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE CECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61 CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8181813737375E5D5E5E5D5E5E5D5E5E5D5E5E5D5E 3737378A8A8A8A8A8A8A8A8A8A8A8A8A8A8A4D4D4DBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB5858585050505E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3C3C3CBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB5858584F4E4F5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E 2F2F2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF2323235E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5857585252528A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB5151515E5D5E 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E434343BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 4343435E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3433348A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 3D3D3D323232323232323232323232323232323232323232323232252525323232323232 323232323232323232323232323232323232323232323232252525323232323232323232 3232323232323232323232321E1E1E212121323232323232323232323232323232323232 323232252525323232323232323232323232323232323232323232323232323232323232 2C2C2C2C2C2C323232323232323232323232323232323232323232191919777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777212121323232323232323232323232323232323232323232323232252525323232 323232323232323232323232323232323232323232323232323232252525323232323232 323232323232323232323232323232323232212121777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777191919323232 3232323232323232323232323232323232322C2C2C2C2C2C323232323232323232323232 323232323232323232323232323232323232252525323232323232323232323232323232 323232323232151515FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF818181666666BBBBBB BBBBBBBBBBBBBBBBBBBBBBBB383838989598989598989598989598989598383838BBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB383838615F61615F61615F61615F61615F61615F612F2E2FBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313131BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 4B4A4B989598989598989598989598505050585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB2F2E2F615F61615F61 615F61615F61615F61615F61383838BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB666666 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848 777777777777777777777777777777777777777777777777777777777777777777777777 777777191919323232323232323232323232323232252525323232323232323232323232 323232323232323232111111323232323232323232323232323232252525323232323232 3232323232323232323232323232320F0E0F323232323232323232323232323232252525 323232323232323232323232323232323232323232252525474747777777777777777777 777777777777777777777777777777777777777777777777777777777777151515323232 323232323232323232252525323232323232323232323232323232323232323232323232 212121777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 777777777777777777414141000000090909777777777777777777777777151515323232 3232323232323232321E1E1E222222323232323232323232323232151515777777777777 777777777777777777151515323232323232323232323232252525464646777777777777 777777777777383838777777777777777777777777777777383838777777777777777777 777777585858585858777777777777777777777777383838777777777777777777777777 777777585858FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE 555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE 555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF403F40676667676667676667676667676667403F40FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF403F406766676766676766676766676766676766672C2C2CFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 3534356766676766676766676766673E3D3E777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C676667676667 676667676667676667676667403F40FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF787878414141777777777777777777777777777777383838777777777777777777 7777777777772A2A2A494849555455555455555455555455555455555455373637777777 777777777777777777777777777777383838777777777777777777777777777777777777 3838382C2C2C555455555455555455555455555455494849272727FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A2A2A777777777777 7777777777777777775858585858587777777777777777777777777777772F2E2F555455 5554555554555554555554555554554948492A2A2A777777777777777777777777777777 777777383838777777777777777777777777777777777777292829555455555455555455 5554555554555554551E1E1E8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A535153989598989598989598989598989598989598989598484648989598989598 989598989598989598989598989598989598989598989598706E70706E70989598989598 9895989895989895989895989895982C2C2CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C989598989598989598989598989598 989598989598706E70706E70989598989598989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598222122FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 444444989598989598989598989598989598989598989598484648989598989598989598 989598989598989598989598989598989598989598989598484648989598989598989598 989598989598989598989598989598989598989598434343FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C 989598989598989598989598989598484648989598989598989598989598989598989598 989598222122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF222122989598989598989598989598484648 9895989895989895989895989895989895989895989895982C2C2CFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 535153989598989598989598989598272727FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF272727 9895989895989895989895985351538A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A535153989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598989598989598 706E70706E709895989895989895989895989895989895989895982C2C2CFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C989598 989598989598989598989598989598989598706E70706E70989598989598989598989598 989598989598989598989598989598989598484648989598989598989598989598989598 989598989598222122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF444444989598989598989598989598989598989598989598 484648989598989598989598989598989598989598989598989598989598989598989598 484648989598989598989598989598989598989598989598989598989598989598434343 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598 CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF2C2C2C989598989598989598989598989598484648989598989598 989598989598989598989598989598222122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF222122989598 989598989598989598484648989598989598989598989598989598989598989598989598 2C2C2CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A535153989598989598989598989598272727FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF2727279895989895989895989895985351538A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598 CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFF5858586E6D6E9895989895989895989895989895989895984D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D989598 9895989895989895989895989895986E6D6E585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF787878232323383838383838383838383838383838 2222223838383838383838383838383838382020202A2A2A2A2A2A2A2A2A2A2A2A2A2A2A 2A2A2A2A2A2A1E1E1E383838383838383838383838383838383838222222383838383838 3838383838383838383838382222221D1D1D242424242424242424242424242424242424 0D0D0D201F20201F20201F20201F20201F201E1E1E2E2E2E383838383838383838383838 383838313131383838383838383838383838383838383838383838313131383838383838 383838383838383838383838313131383838383838383838383838383838383838313131 3838383838383838383838383838383838382A2A2A4D4D4D777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777771717173838383838383838383838383838382D2D2D2D2D2D383838383838383838 3838383838381C1C1C2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A202020383838 383838383838383838383838383838222222383838383838383838383838383838383838 1A1A1A2424242424242424242424242424242424241514158A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF212121353535353535353535353535 323232323232353535353535353535353535353535353535353535212121777777777777 777777777777777777777777777777777777777777777777777777777777777777191919 3130313130313130313130313130311D1D1D313031313031313031313031313031313031 3130310C0C0C3535353535353535353535353535352E2E2E353535353535353535353535 3535353535353535352727274D4D4D777777777777777777777777777777777777777777 7777777777777777777777777777777777770E0E0E3130313130313130313130311D1D1D 313031313031313031313031313031313031313031313031191919777777777777777777 777777777777777777777777777777777777777777777777777777777777383838777777 777777777777777777777777777777777777777777777777777777777777777777414141 000000090909777777777777777777777777383838777777777777777777777777414141 1F1E1F3130313130313130313130310C0C0C3535353535353535353535353535350C0C0C 3130313130313130313130311F1E1F414141777777777777777777777777383838777777 777777777777777777777777383838777777777777777777777777585858585858777777 777777777777777777383838777777777777777777777777777777585858FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A353435615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF252525615F61615F61615F61615F61615F61 615F61615F61474647474647615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61161516FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 2F2E2F4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3939394D4D4D4D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3939394D4D4D4D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D333333555455555455555455555455 555455555455555455555455555455555455333333555455555455555455555455555455 555455555455555455555455555455555455333333555455555455555455555455555455 555455555455555455555455555455333333555455555455555455555455555455555455 555455555455555455555455333333555455555455555455555455555455555455555455 555455555455555455555455555455555455525152474747777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777373637555455555455555455 555455555455555455555455444444444444555455555455555455555455555455555455 555455555455555455555455333333555455555455555455555455555455555455555455 4444444444445554555554555554555554555554555554555554553F3F3FFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF2525254D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4646463F3E3F 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D2E2D2E777777777777777777777777777777777777 7777772D2D2D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D2D2D2D777777777777777777 7777777777777777773838387777777777777777777777777777777777774141418A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61252525FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF2E2E2E615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61 615F61615F61615F613534358A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF2E2E2E615F61615F61615F61615F61615F61252525 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5C CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5C989598989598989598989598 989598434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE323232 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF222222777777777777777777777777777777585858343334 4646464646464646464646464646462827284D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D 4D4D4D2828284342434342434342434342434342434342432A2A2A434243434243434243 4342434342434342433838387777777777777777777777777777777777774141418A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF707070BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB5F5F5F3636365A585A5A585A 5A585A5A585A5A585A5A585A5A585A3332335A585A5A585A5A585A5A585A5A585A5A585A 5A585A5A585A5A585A5A585A4645464645465A585A5A585A5A585A5A585A5A585A5A585A 5A585A2121218383838383838383838383838383838383838383837B7B7B7B7B7B838383 838383838383838383838383838383838383838383838383838383727272838383838383 8383838383838383838383838383833F3E3FBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3E3E3E838383 838383838383838383838383838383838383727272838383838383838383838383838383 8383838383838383838383838383837B7B7B7B7B7B838383838383838383838383838383 838383838383212121706E70706E70706E70706E70706E70706E70706E70535153535153 706E70706E70706E70706E70706E70706E70706E70706E70706E70706E70353435706E70 706E70706E70706E70706E70706E70706E701D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434343989598989598989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598989598989598 484648989598989598989598989598989598989598989598989598989598989598989598 989598989598706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434343989598989598989598989598989598989598989598 706E70706E70989598989598989598989598989598989598989598989598989598989598 484648989598989598989598989598989598989598989598706E70706E70989598989598 989598989598989598989598989598434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF222122706E70706E70706E70706E70535153535153706E70706E70 706E70706E70706E70706E70706E70252525BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4B4B4B838383838383838383838383 838383727272838383838383838383838383838383838383838383242424706E70706E70 706E70706E70706E70353435706E70706E70706E70706E70706E70706E70706E70383738 4D4D4D838383838383838383838383727272838383838383838383838383838383838383 8383838383834C4C4CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB3F3E3F8383838383838383838383837B7B7B7B7B7B838383 838383838383838383838383838383838383454545BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBB BBBBBB272727706E70706E70706E70706E70706E70212121838383838383838383838383 616161818181BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 444444838383838383838383838383616161818181BBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF707070BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 5F5F5F3C3B3C706E70706E70706E70706E70706E70706E70706E70353435706E70706E70 706E70706E70706E70706E70706E70706E70706E70706E70535153535153706E70706E70 706E70706E70706E70706E70706E701D1D1D706E70706E70706E70706E70706E70706E70 706E70535153535153706E70706E70706E70706E70706E70706E70706E70706E70706E70 706E70353435706E70706E70706E70706E70706E70706E70706E701F1F1FBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB1D1D1D706E70706E70706E70706E70706E70706E70706E70353435706E70 706E70706E70706E70706E70706E70706E70706E70706E70706E70535153535153706E70 706E70706E70706E70706E70706E70706E701F1F1F8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A414141FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434343989598989598989598989598 989598989598989598989598989598989598484648989598989598989598989598989598 989598989598989598989598989598989598484648989598989598989598989598989598 989598989598989598989598989598484648989598989598989598989598989598989598 989598989598989598989598484648989598989598989598989598989598989598989598 989598989598989598989598989598989598706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434343989598989598989598 989598989598989598989598706E70706E70989598989598989598989598989598989598 989598989598989598989598484648989598989598989598989598989598989598989598 706E70706E70989598989598989598989598989598989598989598434343FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4747478A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A474747BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB252525 706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70706E70 706E701D1D1D8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A4B4B4B3C3B3C706E70706E70706E70706E70353435706E70706E70 706E70706E70706E70706E70706E70706E70272727BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1F1F1F706E70706E70706E70 706E70535153535153706E70706E70706E70706E70706E70706E70706E70252525BBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB666666 0000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB4D4D4D8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A1E1E1E 706E70706E70706E70706E703C3B3C666666BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBBBBBBBB242424706E70706E70706E70706E703C3B3C666666BBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5050509895989895989895989895986E6D6E464646989598989598 9895989895989895989895989895984D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4D989598989598989598989598989598535253777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 2525254D4D4D4D4D4D4D4D4D4D4D4D4D4D4D464646393939585858585858585858585858 5858583B3B3B6968696968696968696968696968696968696968693E3D3E4D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D363536696869696869696869696869696869696869383738 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3C3C3C8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A353435615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61171717615F61615F61615F61615F61615F61615F61615F61474647474647615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF161516615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61 615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF252525615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61161516FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 353435615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F612E2E2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61615F61474647474647615F61 615F61615F61615F61615F61615F61615F61252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61615F61 3534358A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 1D1D1D615F61615F61615F61615F613534358A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF393939615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F614746478A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF393939615F61615F61615F61615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 2424249895989895989895989895989895986E6D6E8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D989598989598 989598989598989598989598434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 9895989895989895989895989895989895984545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF252525696869696869696869696869696869585758353535 4D4D4D4D4D4D4D4D4D4D4D4D3E3D3E383838777777777777777777777777777777777777 7777774241426968696968696968696968696968696968693736374D4D4D4D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D3A383A6968696968696968696968696968696968694242428A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB4747478A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A1C1C1C706E70706E70706E70706E70706E70353435706E70706E70 706E70706E70706E70706E70706E701D1D1DBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB6666663C3B3C706E70706E70706E70 706E70353435706E70706E70706E70706E70706E70706E70706E70706E701D1D1D8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 1E1E1E706E70706E70706E70706E70535153535153706E70706E70706E70706E70706E70 706E70706E70252525BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBB8181816666668A8A8A8A8A8A8A8A8A8A8A8A414141BBBBBBBBBBBB BBBBBBBBBBBBBBBBBB1F1F1F706E70706E70706E70706E703837384B4B4B8A8A8A8A8A8A 8A8A8A8A8A8A414141BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB242424706E70706E70706E70 706E703C3B3C666666BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB BBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB252525706E70706E70706E70706E70706E70353435 706E70706E70706E70706E70706E70706E70706E701E1E1E8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A414141BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB818181 6666668A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A1D1D1D706E70706E70706E70706E70353435706E70706E70706E70706E70 706E70706E70706E70706E701C1C1C8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A474747BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB6666663C3B3C706E70706E70706E70 706E701F1F1FBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4141418A8A8A8A8A8A8A8A8A8A8A8A 4B4B4B3C3B3C706E70706E70706E70706E701F1F1FBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 4747478A8A8A8A8A8A8A8A8A8A8A8A666666818181BBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A353435615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61171717615F61615F61 615F61615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF161516615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61474647474647615F61615F61615F61615F61615F61615F61615F61252525FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF222222777777777777777777 777777777777585858343434434243434243434243434243403F402E2D2E434243434243 434243434243434243434243434243313131777777777777777777777777777777777777 2928294342434342434342434342434342434342432C2B2C434243434243434243434243 4342434342433232328A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF252525615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61 615F61615F61615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF161516615F61 615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61 252525FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A353435615F61615F61615F61615F611D1D1DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A353435615F61615F61 615F61615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF393939 615F61615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F61615F614746478A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 393939615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4342436B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B606060FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 9895989895989895989895989895989895984545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE313031FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 2F2F2F3130313130313130313130313130313130313130313130311D1D1D313031313031 3130313130313130313130313130313130313130313130311D1D1D313031313031313031 3130313130313130313130311D1D1D222222353535353535353535353535353535353535 3535352E2E2E353535353535353535353535353535353535353535353535353535353535 323232323232353535353535353535353535353535353535353535161516353535353535 353535353535353535353535353535323232323232353535353535353535353535353535 3535353535353535353535353535352E2E2E353535353535353535353535353535353535 3535350E0E0E3130313130313130313130313130313130313130313130311D1D1D313031 3130313130313130313130313130313130313130313130313130311D1D1D313031313031 3130313130313130313130313130313130310E0E0E353535353535353535353535353535 3535353535352E2E2E353535353535353535353535353535353535353535353535353535 353535323232323232353535353535353535353535353535353535353535212121777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3A3A3585858777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777777777777777777777770D0D0D2524252524252524252524252524251F1E1F0F0F0F 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B0E0E0E1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B 1B1B1B0E0E0E1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B0E0E0E1B1B1B1B1B1B1B1B1B 1B1B1B1B1B1B1B1B1B0D0D0D1414141414141414141414141414141414140B0B0B0D0C0D 282828282828282828282828282828181818383838383838383838383838383838222222 383838383838383838383838383838383838383838222222383838383838383838383838 3838383838382222223838383838383838383838383838383838382D2D2D2D2D2D383838 383838383838383838383838383838171717777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777585858 BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848 777777777777777777777777777777777777777777777777777777777777777777777777 7777772121213535353535353535353535353535352E2E2E353535353535353535353535 3535353535353535351A1A1A777777777777777777777777777777777777777777777777 7777777777777777777777777777771A1A1A3130313130313130313130313130311D1D1D 3130313130313130313130313130313130313130311F1F1F414141777777777777777777 777777777777777777777777777777777777777777777777777777777777191919353535 3535353535353535352E2E2E353535353535353535353535353535353535353535353535 0C0C0C313031313031313031313031272727272727313031313031313031313031313031 313031313031151515777777777777777777777777777777777777777777777777777777 777777777777777777414141000000090909777777777777777777777777383838777777 7777777777777777774D4D4D2727273535353535353535353535351A1A1A777777777777 7777777777777777773838387777777777777777777777774D4D4D272727353535353535 3535353535350E0E0E3130313130313130313130313130310E0E0E313031313031313031 3130311F1E1F414141777777777777777777777777383838777777777777777777777777 777777585858FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666353435CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE 282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666353435CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCE CECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666353435 CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666353435CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE 282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666353435CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCE CECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF201F20615F61615F61615F61615F61615F61535253393939 585858585858585858585858585858313131777777777777777777777777777777777777 7777772D2D2D585858585858585858585858585858585858353535777777777777777777 7777777777777777773838387777777777777777777777777777777777772A2A2A1F1F1F 615F61615F61615F61615F61615F613736375858585858585858585858585858582A2A2A 777777777777777777777777777777777777777777353535585858585858585858585858 5858585858582D2D2D777777777777777777777777777777777777585858585858777777 7777777777777777777777777777772A2A2AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5C5B5C989598989598989598989598989598434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D9895989895989895989895989895986E6D6E 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777535253989598 989598989598989598494849FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858 6E6D6E9895989895989895989895989895984D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE 282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF2E2E2E615F61615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61 353435727272FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2E2E615F61615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F612E2E2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777615F61CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF2E2E2E615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61 615F61615F61615F613534358A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D1D1D615F61615F61615F61 615F61474647474647615F61615F61615F61615F61615F61615F61615F61252525FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF2E2E2E615F61 615F61615F61615F61615F61171717615F61615F61615F61615F613534358A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5C CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE555455 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCE CECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858 989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE 282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF393939615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F61615F61615F614746478A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF393939615F61615F61615F61 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61393939FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5C5B5CCECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777615F61CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCE CECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF2D2D2DBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A454545 4443444443444443444443444443442F2F2F8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A3232325E5D5E5E5D5E5E5D5E5E5D5E5E5D5E505050414141BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4646464B4B4B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4D4D4D3A3A3A4443444443444443444443442A2A2A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A3030304F4E4F5E5D5E5E5D5E5E5D5E 5E5D5E5E5D5E363636BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCE CECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D2D2DBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB8A8A8A4B4A4B9895989895989895989895986E6D6E424142989598989598 989598989598989598989598989598464646BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 3636365E5D5E5E5D5E5E5D5E5E5D5E5E5D5E363536585858BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB4646464B4B4BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB383838989598989598 9895989895989895983434346E6D6E9895989895989895989895989895989895986E6D6E 8A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4141415050505E5D5E5E5D5E5E5D5E5E5D5E 5E5D5E4242428A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCE 282728CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCE CECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598 CECBCECECBCECECBCECECBCECECBCE5C5B5CBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A1A1A313031313031313031313031 272727272727313031313031313031313031313031313031313031191919777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777212121323232323232323232323232323232252525323232323232323232323232 323232323232323232252525474747777777777777777777777777777777777777777777 777777777777777777777777777777777777383838777777777777777777777777777777 777777777777777777777777777777777777777777777777151515323232323232323232 3232322C2C2C2C2C2C323232323232323232323232323232323232323232101010313031 3130313130313130313130311D1D1D3130313130313130313130313130313130311B1A1B 000000090909777777777777777777777777151515313031313031313031313031242324 464646777777777777777777777777383838777777777777777777777777777777383838 777777777777777777777777585858585858777777777777777777777777212121323232 3232323232323232323232321010103232323232323232323232321E1E1E222222313031 313031313031313031101010313031313031313031313031313031272727FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939 989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCE5C5B5CBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598 BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCE5C5B5CBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1D CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCE CECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598 CECBCECECBCECECBCECECBCECECBCE5C5B5CBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCE CECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939 989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCE5C5B5CBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFF323232989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598989598989598 4846489895989895989895989895989895989895989895985351537B7B7BFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCE615F61777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598 BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCE5C5B5CBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1D CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF323232989598989598989598 989598989598989598989598989598484648989598989598989598989598989598989598 989598989598989598989598484648989598989598989598989598989598989598989598 5351537B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232989598989598 989598989598989598989598989598989598484648989598989598989598989598989598 989598989598989598989598989598484648989598989598989598989598989598989598 989598989598323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 2D2D2DBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A4242425C5B5C5C5B5C5C5B5C5C5B5C 5C5B5C3232325E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E3433348A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A3433345E5D5E5E5D5E5E5D5E5E5D5E5E5D5E363536585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4646464B4B4BBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB3E3E3E5C5B5C5C5B5C5C5B5C5C5B5C5C5B5C2A2A2A5050505E5D5E5E5D5E5E5D5E 5E5D5E5E5D5E5E5D5E4645466666668A8A8A8A8A8A8A8A8A8A8A8A8A8A8A303030505050 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E4242428A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCE CECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF1F1F1F5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E4B4A4B666666 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB464646989598989598989598989598989598989598383838BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB3434345E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E2E2D2E1C1C1C 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E363636BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858535253989598989598989598 989598989598464546BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A2F2E2F5E5D5E 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E1C1C1CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB464646989598989598989598989598989598989598989598989598 989598989598474647989598989598989598989598989598989598989598989598989598 989598989598474647989598989598989598989598989598989598989598989598989598 989598474647989598989598989598989598989598989598989598989598989598989598 474647989598989598989598989598989598989598989598989598989598989598989598 9895989895986766675F5E5F8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D7B7B7B 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8484848484848D8D8D8D8D8D8D8D8D 8D8D8D8D8D8D8D8D8D8D8D8D474647989598989598989598989598989598989598989598 706E70706E70989598989598989598989598989598989598989598989598989598989598 474647989598989598989598989598989598989598989598706E70706E70989598989598 9895989895989895989895989895984A494AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE414041353435CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF272727989598989598989598989598706E70706E70989598989598 9895989895989895989895989895982C2C2CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C989598989598989598989598989598 484648989598989598989598989598989598989598535153000000131313FFFFFFFFFFFF FFFFFFFFFFFF2727279895989895989895989895985351538A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A535153989598989598989598989598181818 9895989895989895989895989895982C2C2CFFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4747478A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A4B4B4B6E6D6E989598989598989598989598 989598989598989598474647989598989598989598989598989598989598989598706E70 706E709895989895989895989895989895989895989895984342438A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A545454FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE414041353435CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCE CECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF272727989598989598989598989598 706E70706E709895989895989895989895989895989895989895982C2C2CFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C2C2C989598 989598989598989598989598484648989598989598989598989598989598989598535153 000000131313FFFFFFFFFFFFFFFFFFFFFFFF272727989598989598989598989598535153 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A535153989598 9895989895989895981818189895989895989895989895989895982C2C2CFFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE414041353435 CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCE CECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCE CECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF242424CECBCECECBCECECBCE CECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE414041353435CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFF FFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE1D1C1D CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF353535CECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 242424CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE414041353435CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCE CECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCE CECBCECECBCECECBCE1D1C1DCECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF 353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE706E70838383FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF1F1F1F5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E4B4A4B4B4B4B 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB3F3F3F5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E343434BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB3434345E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E2E2D2E1C1C1C 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E2F2F2F8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A4D4D4D BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB5858583635365E5D5E5E5D5E5E5D5E 5E5D5E5E5D5E282828BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A2F2E2F5E5D5E 5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E1C1C1CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E1D1E 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61181818777777777777777777777777777777777777777777777777777777777777 777777777777777777383838777777777777777777777777777777777777777777777777 777777777777777777777777777777383838777777777777777777777777777777777777 777777777777777777777777777777777777777777585858585858777777777777777777 777777777777777777777777777777777777777777777777777777777777383838777777 777777777777777777777777777777777777777777777777777777777777777777777777 383838777777777777777777777777777777777777777777777777777777777777777777 777777777777181818615F61615F61615F61615F61615F612E2D2E615F61615F61615F61 615F61615F61615F61353435000000090909777777777777777777777777171717615F61 615F61615F61615F61353435414141777777777777777777777777383838777777777777 777777777777777777383838777777777777777777777777585858585858777777777777 777777777777383838777777777777777777777777777777383838777777777777777777 777777414141353435615F61615F61615F61615F610E0E0E615F61615F61615F61615F61 615F61252525FFFFFFFFFFFF3D3C3D313031313031313031313031313031313031313031 3130311D1D1D313031313031313031313031313031313031313031313031313031313031 1D1D1D313031313031313031313031313031313031313031242324444444777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777151515232323232323232323232323232323232323 232323232323171617232323232323232323232323232323232323232323232323232323 2323231716172323232323232323232323232323232323232323232323230E0E0E323232 323232323232323232323232323232323232252525323232323232323232323232323232 3232323232323232323232323232322C2C2C2C2C2C323232323232323232323232323232 323232323232191919777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D2D2DBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB8A8A8A4B4A4B989598989598989598989598505050585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 2828285E5D5E5E5D5E5E5D5E5E5D5E5E5D5E5E5D5E343434BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB4646464B4B4BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB383838989598989598 989598989598989598383838BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3434345E5D5E5E5D5E5E5D5E5E5D5E5E5D5E 5E5D5E2F2E2F8A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB313131FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF070707000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000191919FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCE CECBCECECBCECECBCECECBCECECBCE5E5D5EBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E1D1E615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61181818777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777585858585858777777777777777777777777777777777777777777 777777777777777777777777777777777777383838777777777777777777777777777777 777777777777777777777777777777777777777777777777383838777777777777777777 777777777777777777777777777777777777777777777777777777777777383838777777 777777777777777777777777777777777777777777777777777777777777777777414141 000000090909777777777777777777777777383838777777777777777777777777585858 585858777777777777777777777777383838777777777777777777777777777777383838 777777777777777777777777585858585858777777777777777777777777383838777777 777777777777777777777777383838777777777777777777777777585858585858777777 777777777777777777383838777777777777777777777777777777585858FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE5E5D5EBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A474647615F61615F61615F61615F61615F61615F61615F612E2D2E 615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61615F61 615F61615F61615F61615F61393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE CECBCE5E5D5EBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE 676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCE CECBCECECBCECECBCECECBCECECBCE5E5D5EBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5E CECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCE CECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE5E5D5EBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031 CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBB3534356766676766676766676766673E3D3E777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 2C2C2C676667676667676667676667676667676667403F40FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF666666666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF403F40676667676667 676667676667676667403F40FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF403F40676667676667676667676667676667 676667353435BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF212121353535353535353535353535323232323232353535353535 3535353535353535353535353535351010103130313130313130313130313130311D1D1D 3130313130313130313130313130313130313130310E0E0E777777777777777777777777 777777777777777777777777777777777777777777777777777777383838777777777777 777777777777777777777777777777777777777777777777777777777777777777585858 585858777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 777777777777777777777777383838777777777777777777777777777777777777777777 777777777777777777777777777777777777383838777777777777777777777777777777 777777777777777777777777777777777777777777414141000000090909777777777777 777777777777383838777777777777777777777777585858585858777777777777777777 777777383838777777777777777777777777777777383838777777777777777777777777 585858585858777777777777777777777777383838777777777777777777777777777777 383838777777777777777777777777585858585858777777777777777777777777383838 777777777777777777777777777777585858FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 222222777777777777777777777777777777585858585858777777777777777777777777 7777773736375554555554555554555554555554555554555554552D2D2D777777777777 777777777777777777777777383838777777777777777777777777777777777777343334 5554555554555554555554555554555554552F2F2F303030777777777777777777777777 7777773838387777777777777777777777777777772D2D2D555455555455555455555455 555455555455555455373637777777777777777777777777777777777777383838777777 7777777777777777777777777777775858583C3C3C555455555455555455555455555455 555455202020FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232989598989598989598989598989598989598989598989598484648989598 989598989598989598989598989598989598989598989598989598484648989598989598 989598989598989598989598989598989598222122989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598706E70706E709895989895989895989895989895989895989895982C2C2CFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE414041666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858 989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCE CECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232989598989598989598989598989598989598 989598989598484648989598989598989598989598989598989598989598989598989598 989598484648989598989598989598989598989598989598989598989598222122989598 989598989598989598989598989598989598484648989598989598989598989598989598 989598989598989598989598989598706E70706E70989598989598989598989598989598 9895989895982C2C2CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE414041666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE414041666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCE CECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCE CECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70 989598989598989598989598989598989598989598484648989598989598989598989598 989598989598989598706E70706E70989598989598989598989598989598989598989598 434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE414041666666 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858 989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCE CECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB252525706E70706E70706E70706E70706E70353435706E70706E70706E70706E70 706E70706E70706E701F1F1F838383838383838383838383838383727272838383838383 838383838383838383838383838383363636838383838383838383838383838383727272 838383838383838383838383838383838383838383616161818181BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBB BBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB BBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A706E70989598989598989598989598989598989598989598484648 989598989598989598989598989598989598989598706E70706E70989598989598989598 989598989598989598989598434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCE CECBCECECBCE414041666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4D FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCECECBCE201F20FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4747478A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A202020706E70706E70706E70706E70 706E70353435706E70706E70706E70706E70706E70706E70706E70141414706E70706E70 706E70706E70706E70353435706E70706E70706E70706E70706E70706E70706E703C3B3C 666666BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBB BBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB 8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4D9895989895989895989895989895989895986E6D6E585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243 CECBCECECBCECECBCECECBCECECBCECECBCE414041666666FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5858586E6D6E989598989598989598 9895989895989895984D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCECECBCE CECBCE201F20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE1C1C1CCECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E8E8E181718201F20 201F20201F20201F20201F20222222383838383838383838383838383838313131383838 383838383838383838383838383838383838313131383838383838383838383838383838 383838313131383838383838383838383838383838383838313131383838383838383838 3838383838383838383838380E0E0E3838383838383838383838383838382D2D2D2D2D2D 3838383838383838383838383838381C1C1C2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A 2A2A2A202020383838383838383838383838383838383838222222383838383838383838 3838383838383838381A1A1A2424242424242424242424242424242424241515151A1A1A 383838383838383838383838383838222222383838383838383838383838383838202020 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A1C1C1C383838383838383838383838 3838383838382222223838383838383838383838383838383838382D2D2D1B1B1B242424 242424242424242424242424242424090909201F20201F20201F20201F20201F201E1E1E 2E2E2E383838383838383838383838383838313131383838383838383838383838383838 383838383838313131383838383838383838383838383838383838313131383838383838 3838383838383838383838383131313838383838383838383838383838383838382A2A2A A3A3A3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE1C1C1CCECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE1C1C1CCECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE706E70 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE1C1C1CCECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE706E708A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777151515232323232323232323232323232323171617232323232323 2323232323232323232323232323230D0C0D3130313130313130313130313130311D1D1D 3130313130313130313130313130313130313130311D1D1D212121323232323232323232 323232252525323232323232323232323232323232323232323232323232212121777777 777777777777777777777777777777777777777777777777777777777777777777777777 383838777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 777777777777777777414141000000090909777777777777777777777777383838777777 777777777777777777585858585858777777777777777777777777383838777777777777 777777777777777777383838777777777777777777777777585858585858777777777777 777777777777383838777777777777777777777777777777383838777777777777777777 777777585858585858777777777777777777777777383838777777777777777777777777 777777585858FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598 989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF2E2E2E615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F61615F61161516615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F61474647474647615F61615F61615F61615F61615F61615F61615F61252525FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A393A 555455555455555455555455555455555455555455333333555455555455555455555455 555455555455555455555455464546777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777474747464646 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3939394D4D4D4D4D4D4D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4343434343434D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D 333333555455555455555455555455555455555455555455444444444444555455555455 555455555455555455555455555455555455555455555455333333555455555455555455 555455555455555455555455444444444444555455555455555455555455555455555455 5554553F3F3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF7878783434344D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3A393A4242424D4D4D4D4D4D 4D4D4D4D4D4D2F2E2F7777777777777777777777777777777777777777773D3C3D4D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D3A393A777777777777777777777777777777777777 3838387777777777777777777777777777777777777777772A2A2AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2424244D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4646463636364D4D4D4D4D4D4D4D4D4D4D4D4D4D4D2E2D2E777777 7777777777777777777777777777777777772D2D2D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D 4D4D4D2D2D2D777777777777777777777777777777777777383838777777777777777777 7777777777777777774141418A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777615F61CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE555455FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5A5A5ACECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777141414282828282828282828282828282828181818282828282828 2828282828282828282828282828280B0B0B777777777777777777777777777777777777 7777777777777777777777777777777777777777773939391414141D1C1D1D1C1D1D1C1D 1D1C1D1414141D1C1D1D1C1D1D1C1D1D1C1D1D1C1D1D1C1D1D1C1D1D1C1D141414777777 777777777777777777777777777777777777777777777777777777777777777777777777 383838777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 777777777777777777414141000000090909777777777777777777777777383838777777 777777777777777777585858585858777777777777777777777777383838777777777777 777777777777777777383838777777777777777777777777585858585858777777777777 777777777777383838777777777777777777777777777777383838777777777777777777 777777585858585858777777777777777777777777383838777777777777777777777777 777777585858FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCE CECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598 CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE 989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777615F61CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5A5A5ACECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232 CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777535253989598989598989598989598494849FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5A5A5A989598989598989598989598989598434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE353535FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF353535CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2ECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF7878784141417777777777777777777777777777772E2D2E464646464646464646 4646464646462020204D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D403F403B3A3B 4342434342434342434342434342433A383A434243434243434243434243434243434243 3837387777777777777777777777777777777777777777772A2A2AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A2A2A777777777777 7777777777777777775858583433344646464646464646464646464646462827284D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D282828434243434243434243434243434243 4342432A2A2A434243434243434243434243434243434243313131777777777777777777 7777777777777777774141418A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 706E70CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF707070BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 818181616161838383838383838383838383838383838383838383727272838383838383 8383838383838383838383838383838383838383838383837B7B7B7B7B7B838383838383 838383838383838383838383838383383738838383838383838383838383838383838383 8383837B7B7B7B7B7B838383838383838383838383838383838383838383838383838383 838383727272838383838383838383838383838383838383838383222222706E70706E70 706E70706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70 706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70706E70 706E70706E701D1D1D706E70706E70706E70706E70706E70706E70706E70353435706E70 706E70706E70706E70706E70706E70706E70706E70706E70706E70535153535153706E70 706E70706E70706E70706E70706E70706E70212121838383838383838383838383838383 8383838383837B7B7B7B7B7B838383838383838383838383838383838383838383838383 8383838383837272728383838383838383838383838383838383838383833E3E3EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF444444989598989598989598989598 989598989598989598484648989598989598989598989598989598989598989598989598 434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434343989598989598989598 989598989598989598989598706E70706E70989598989598989598989598989598989598 989598989598989598989598484648989598989598989598989598989598989598989598 706E70706E70989598989598989598989598989598989598989598434343FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCE CECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB252525 706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70706E70 706E701D1D1DBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB6666663C3B3C706E70706E70706E70706E70353435706E70706E70 706E70706E70706E70706E70706E70706E70272727BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB666666 0000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF 707070BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB6666663C3B3C706E70706E70706E70706E70706E70706E70 706E70353435706E70706E70706E70706E70706E70706E70706E70706E70706E70706E70 535153535153706E70706E70706E70706E70706E70706E70706E701E1D1E706E70706E70 706E70706E70706E70706E70706E70535153535153706E70706E70706E70706E70706E70 706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70706E70 706E701E1E1E8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A3939398A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A212121706E70 706E70706E70706E70706E70706E70706E70535153535153706E70706E70706E70706E70 706E70706E70706E70706E70706E70706E70353435706E70706E70706E70706E70706E70 706E70706E701D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF444444 989598989598989598989598989598989598989598484648989598989598989598989598 989598989598989598989598434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434343989598989598989598989598989598989598989598706E70706E70989598989598 989598989598989598989598989598989598989598989598484648989598989598989598 989598989598989598989598706E70706E70989598989598989598989598989598989598 989598434343FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598 CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB4D4D4D8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A414141BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8181816666668A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A4D4D4DBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB6666660000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBB BBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB BBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE393939989598CECBCECECBCECECBCECECBCE CECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE989598464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE393939989598 CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCE CECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE393939989598CECBCECECBCECECBCECECBCECECBCECECBCE989598BBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE989598464646CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243989598989598989598989598989598393939989598CECBCECECBCECECBCECECBCE CECBCECECBCE989598BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF696869989598CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB505050989598989598989598 9895986E6D6E464646CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE989598 585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848777777777777777777777777 777777777777777777777777777777777777777777777777777777383838777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777585858585858777777777777777777777777777777777777777777 777777777777777777777777777777777777151515323232323232323232323232252525 323232323232323232323232323232323232323232323232212121777777777777777777 777777777777777777777777777777777777777777777777777777777777383838777777 777777777777777777777777777777777777777777777777777777777777777777414141 000000090909777777777777777777777777383838777777777777777777777777585858 585858777777777777777777777777383838777777777777777777777777777777383838 777777777777777777777777585858585858777777777777777777777777383838777777 777777777777777777777777383838777777777777777777777777585858585858777777 777777777777777777383838777777777777777777777777777777585858FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7878782A2A2A434243 4342434342434342434342432A2A2A585858585858585858585858585858272727434243 4342434342434342434342434342434342432D2D2D3A3A3A4D4D4D4D4D4D4D4D4D4D4D4D 4D4D4D323132434243434243434243434243434243434243383738403F40434243434243 434243434243434243434243272727FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF212121434243434243434243434243434243383838 3939395858585858585858585858585858582C2C2C434243434243434243434243434243 4342434342432F2E2F4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D292829434243434243 4342434342434342434342432B2A2B434243434243434243434243434243434243272727 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61 CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A353435615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61171717615F61615F61615F61615F61615F61615F61 615F61474647474647615F61615F61615F61615F61615F61615F61615F61615F61615F61 615F612E2D2E615F61615F61615F61615F61615F61615F61615F611D1D1DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF252525615F61615F61615F61615F61615F61 615F61615F61474647474647615F61615F61615F61615F61615F61615F61615F61615F61 615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61161516FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF393939615F61615F61615F61 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61393939FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE CECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61 CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCE CECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF333333615F61615F61615F61615F61 615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61615F61615F61 393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF201F20CECBCECECBCECECBCECECBCECECBCE9895988A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF484848777777777777777777777777 777777777777777777777777777777777777777777777777777777383838777777777777 777777777777777777777777777777777777777777777777777777777777777777383838 777777777777777777777777777777777777777777777777777777777777777777777777 777777383838777777777777777777777777777777777777777777777777777777777777 777777777777777777585858585858777777777777777777777777777777777777777777 7777777777777777777777777777777777770B0B0B282828282828282828282828181818 2828282828282828282828282828282828282828282828280C0C0C313031313031313031 313031272727272727313031313031313031313031313031313031313031151515777777 777777777777777777777777777777777777777777777777777777777777777777414141 000000090909777777777777777777777777383838777777777777777777777777585858 585858777777777777777777777777383838777777777777777777777777777777383838 777777777777777777777777585858585858777777777777777777777777383838777777 777777777777777777777777383838777777777777777777777777585858585858777777 777777777777777777383838777777777777777777777777777777585858FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A484648CECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777615F61CECBCECECBCECECBCECECBCE CECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF201F20CECBCECECBCECECBCECECBCECECBCE989598 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 232323CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF7878782A2A2A4342434342434342434342434342432928294D4D4D4D4D4D4D4D4D 4D4D4D4D4D4D2E2D2E777777777777777777777777777777777777777777383838434243 434243434243434243434243434243272527434243434243434243434243434243434243 292829403F40434243434243434243434243434243434243272727FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF212121434243434243 4342434342434342433838383433344D4D4D4D4D4D4D4D4D4D4D4D3E3D3E383838777777 777777777777777777777777777777777777383738434243434243434243434243434243 4342432625264342434342434342434342434342434342432C2B2C434243434243434243 4342434342434342432727278A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE232323CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE232323CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE323232FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E2D2ECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 232323CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE323232FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE 555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 8A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBB1D1D1D706E70706E70706E70706E70353435706E70706E70706E70706E70 706E70706E70706E70706E70191819706E70706E70706E70706E70535153535153706E70 706E70706E70706E70706E70706E70706E701F1E1F838383838383838383838383838383 7272728383838383838383838383838383838383834848480000000E0E0EBBBBBBBBBBBB BBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBB BBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB 8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCE CECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCE CECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE 434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF606060BBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4141418A8A8A8A8A8A8A8A8A8A8A8A8A8A8A 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A141414535153535153535153 5351533D3C3D3D3C3D535153535153535153535153535153535153535153151515706E70 706E70706E70706E70706E70353435706E70706E70706E70706E70706E70706E703D3C3D 0000000E0E0EBBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A 8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB585858 BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBB BBBBBBBBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBB8A8A8A8A8A8ABBBBBB BBBBBBBBBBBBBBBBBB585858BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB686868FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCE434243FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE555455FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCE CECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE232323CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A353435615F61615F61 615F61615F61615F61615F61615F612E2D2E615F61615F61615F61615F61615F61615F61 615F61615F61615F61615F61474647474647615F61615F61615F61615F61615F61615F61 615F61171717615F61615F61615F61615F61615F61615F61615F61474647474647615F61 615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61615F61 615F61615F61615F61615F61615F611D1D1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF252525615F61615F61615F61615F61615F61615F61615F61474647474647 615F61615F61615F61615F61615F61615F61615F61615F61615F61615F612E2D2E615F61 615F61615F61615F61615F61615F61615F61161516FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF333333615F61615F61615F61615F61615F61615F61615F612E2D2E 615F61615F61615F61615F61615F61615F61615F61615F61393939FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF393939615F61615F61615F61615F61615F61615F61615F61 474647474647615F61615F61615F61615F61615F61615F61615F61615F61615F61615F61 2E2D2E615F61615F61615F61615F61615F61615F61615F61474647474647615F61615F61 615F61615F61615F61615F61615F61393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCE434243FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE 555455FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB5E5D5ECECBCECECBCECECBCECECBCE676667777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCE434243FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE232323CECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF787878414141777777777777777777777777777777 3837384D4D4D4D4D4D4D4D4D4D4D4D4D4D4D353435696869696869696869696869696869 6968696968694241427777777777777777777777777777777777773837384D4D4D4D4D4D 4D4D4D4D4D4D4D4D4D4D4D4D373637646364696869696869696869696869696869696869 2A2A2AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF2A2A2A7777777777777777777777777777775858583F3F3F4D4D4D4D4D4D4D4D4D 4D4D4D4847483D3C3D696869696869696869696869696869696869696869353535777777 7777777777777777777777777777773736374D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D 3A383A6968696968696968696968696968696968693D3D3D8A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF313031CECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE232323CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5858586E6D6E 9895989895989895989895989895989895984D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777585758989598989598 9895989895989895986E6D6E313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4D989598989598989598989598989598 9895986E6D6E585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4342439895989895989895989895989895989895983B3B3B 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 313031CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE232323CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF484848777777777777777777777777777777777777777777777777 777777777777777777777777777777383838777777777777777777777777777777777777 777777777777777777777777777777777777777777383838777777777777777777777777 777777777777777777777777777777777777777777777777777777383838777777777777 777777777777777777777777777777777777777777777777777777777777777777585858 585858777777777777777777777777777777777777777777777777777777777777777777 777777777777383838777777777777777777777777777777777777777777777777777777 777777777777777777777777151515313031313031313031313031272727272727313031 3130313130313130313130313130313130310D0D0D232323232323232323232323232323 171617232323232323232323232323232323232323141414000000090909777777777777 777777777777383838777777777777777777777777585858585858777777777777777777 777777383838777777777777777777777777777777383838777777777777777777777777 585858585858777777777777777777777777383838777777777777777777777777777777 383838777777777777777777777777585858585858777777777777777777777777383838 777777777777777777777777777777585858FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598 CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCE CECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCE CECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCECECBCECECBCECECBCE454545 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61 CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777676667CECBCECECBCECECBCECECBCECECBCE989598313131FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCE CECBCECECBCECECBCECECBCECECBCE989598585858FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF434243CECBCECECBCECECBCE CECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE 615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF BBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE313031FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE2E2D2EFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455CECBCECECBCECECBCECECBCE CECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D4D4DCECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF585858989598CECBCECECBCECECBCECECBCE CECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777676667CECBCECECBCECECBCECECBCECECBCE989598 313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCE989598585858FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 434243CECBCECECBCECECBCECECBCECECBCECECBCE4545458A8A8AFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE706E70 000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF8A8A8A706E70CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE 989598989598CECBCECECBCECECBCECECBCECECBCECECBCECECBCE282728CECBCECECBCE CECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE313031FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF323232CECBCE CECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCECECBCE CECBCECECBCE2E2D2EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555455 CECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCECECBCE CECBCECECBCECECBCECECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4D4D4DCECBCECECBCECECBCECECBCECECBCECECBCECECBCE989598989598CECBCECECBCE CECBCECECBCECECBCECECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCECECBCE989598989598CECBCECECBCECECBCECECBCECECBCECECBCE CECBCE4D4D4DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A8A8A8A8A8AFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6060606B6B6B 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B565556FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777585758989598989598 9895989895989895986E6D6E313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF383838FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4342436B6B6B6B6B6B6B6B6B6B6B6B6B6B6B 6B6B6B6B6B6B606060FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF4342439895989895989895989895989895989895983B3B3B 8A8A8AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF323232CECBCECECBCECECBCECECBCECECBCE615F61CECBCECECBCECECBCE CECBCECECBCECECBCE706E70000000131313FFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFF FFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFBBBBBBBBBBBBFFFFFFFFFFFF FFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFF FFFFFFBBBBBBBBBBBBFFFFFFFFFFFFFFFFFFFFFFFF777777FFFFFFFFFFFFFFFFFFFFFFFF FFFFFF777777FFFFFFFFFFFFBBBBBB777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777626262323232353535353535 3535353535353535353535353535352E2E2E353535353535353535353535353535353535 353535353535353535353535323232323232353535353535353535353535353535353535 353535282728353535353535353535353535353535353535353535323232323232353535 3535353535353535353535353535353535353535353535353535352E2E2E353535353535 3535353535353535353535353535352F2F2F777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777686868777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777777777773D3D3D353535353535353535353535353535353535353535323232323232 3535353535353535353535353535353535353535353535353535353535352E2E2E353535 353535353535353535353535353535353535353535FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF403F404342434342434342434342434342434342434342433B3A3B 434243434243434243434243434243434243434243434243565656777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777686868777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777707070707070777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777474747434243434243434243434243434243434243434243 3F3E3F3F3E3F434243434243434243434243434243434243434243434243434243434243 3B3A3B4342434342434342434342434342434342434342433F3E3F3F3E3F434243434243 434243434243434243434243434243606060FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFC0C0C0383838383838383838383838383838383838313131383838383838383838 383838383838313131383838383838383838383838383838383838383838313131383838 383838383838383838383838383838313131383838383838383838383838383838383838 3131312F2F2F3131313131313131313131313131313131313C3C3C777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777707070707070777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 777777777777777777777777777777777777777777777777777777777777777777777777 7777777777777777777777777777777777777777777777777777773F3F3F383838383838 383838383838383838353535353535383838383838383838383838383838313131383838 383838383838383838383838383838383838313131383838383838383838383838383838 3838383131313838383838383838383838383838383838382D2D2D313131313131313131 3131313131313131312F2F2FC0C0C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF777777777777777777777777777777777777777777777777777777 777777777777777777777777777777686868777777777777777777777777777777777777 777777777777777777777777777777777777777777686868777777777777777777777777 777777777777777777777777777777777777777777777777777777686868777777777777 777777777777777777777777777777777777777777777777777777777777777777707070 707070777777777777777777777777777777777777777777777777777777777777777777 777777777777686868777777777777777777777777777777777777777777777777777777 777777777777777777777777686868777777777777777777777777777777777777777777 7777777777777777777777777777777777773D3D3D353535353535353535353535353535 2E2E2E3535353535353535353535353535353535352F2F2F1E1E1E4D4D4D777777777777 777777777777686868777777777777777777777777707070707070777777777777777777 777777686868777777777777777777777777777777686868777777777777777777777777 707070707070777777777777777777777777686868777777777777777777777777777777 686868777777777777777777777777707070707070777777777777777777777777686868 777777777777777777777777777777999999FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCCFFFFFFAAAAAADDDDDDFFFFFFFFFFFF FFFFFFFFFFFFDDDDDDEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDDEEEEEEFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAADDDDDDFFFFFF CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF999999999999CCCCCC 000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777CCCCCCFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFEEEEEE777777EEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFF777777CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF999999999999FFFFFFFFFFFFFFFFFFFFFFFF BBBBBB000000BBBBBBFFFFFFAAAAAACCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DDDDDD777777FFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 666666EEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777DDDDDDFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF666666EEEEEEFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDD777777FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF555555EEEEEEFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCC FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF666666AAAAAAFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF999999777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAA 666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF999999 777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF666666AAAAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFF FFFFFF999999666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFEEEEEE777777EEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAA CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000DDDDDDFFFFFFFFFFFF 000000555555111111000000444444EEEEEEFFFFFFFFFFFFCCCCCC111111FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555555999999FFFFFFFFFFFFEEEEEE777777777777777777333333 CCCCCCFFFFFFFFFFFFCCCCCC111111FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000DDDDDDFFFFFFFFFFFFEEEEEE555555777777 444444000000BBBBBBFFFFFFFFFFFFDDDDDD111111FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777DDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555555EEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 000000FFFFFFFFFFFFFFFFFF000000777777FFFFFFDDDDDD222222555555FFFFFFFFFFFF FFFFFF000000CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF666666 BBBBBBFFFFFFFFFFFF888888BBBBBBFFFFFFFFFFFFFFFFFF000000CCCCCCFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB000000FFFFFFFFFFFF FFFFFF333333BBBBBBFFFFFFEEEEEE000000BBBBBBFFFFFFFFFFFFFFFFFF000000BBBBBB FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAA666666FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF999999666666FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFBBBBBB000000FFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF 999999000000FFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 BBBBBBFFFFFFFFFFFF111111FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF BBBBBB000000FFFFFFFFFFFFCCCCCC000000FFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFF FFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555555999999FFFFFFFFFFFFFFFFFF777777666666555555444444FFFFFFFFFFFFFFFFFF DDDDDD111111FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB000000FFFFFFFFFFFFFFFFFF 000000BBBBBBFFFFFFFFFFFFBBBBBB111111FFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF111111BBBBBBFFFFFFFFFFFF000000DDDDDDFFFFFFFFFFFFFFFFFF EEEEEEFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFBBBBBB000000FFFFFFFFFFFFBBBBBB000000EEEEEEFFFFFF FFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFF555555DDDDDDFFFFFF 000000BBBBBBFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 000000DDDDDDFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF777777777777FFFFFFFFFFFF DDDDDD111111FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555555888888FFFFFFFFFFFF555555 333333DDDDDDFFFFFFBBBBBB999999FFFFFFFFFFFFDDDDDD111111FFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000DDDDDDFFFFFF EEEEEE111111888888FFFFFFEEEEEE000000AAAAAAFFFFFFFFFFFFDDDDDD000000FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFFFFFFFF FFFFFFFFFFFFDDDDDDBBBBBB333333BBBBBBFFFFFFFFFFFFFFFFFF000000BBBBBBFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF666666AAAAAAFFFFFFFFFFFF777777555555777777777777 888888FFFFFFFFFFFFFFFFFF999999666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB 666666FFFFFFFFFFFFEEEEEE555555000000111111777777FFFFFFFFFFFFFFFFFF999999 666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF666666AAAAAAFFFFFFFFFFFFAAAAAA222222333333888888222222777777EEEEEE FFFFFFAAAAAA666666FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 111111BBBBBBFFFFFFFFFFFFFFFFFF999999CCCCCCFFFFFF444444BBBBBBFFFFFFFFFFFF FFFFFF000000BBBBBBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDD777777FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555555EEEEEEFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF666666DDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFF555555EEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDD777777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF555555DDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF555555888888FFFFFFFFFFFFFFFFFF000000EEEEEEFFFFFF 333333BBBBBBFFFFFFFFFFFFDDDDDD000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFAAAAAAAAAAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777 CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF888888EEEEEEFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF777777CCCCCCFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAAAAAAAA FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAAAAAAAAFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBBBBBB666666FFFFFFFFFFFF FFFFFF555555444444AAAAAA333333333333BBBBBBFFFFFFAAAAAA666666FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFDDDDDDEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDDEEEEEEFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF CCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF666666DDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 555555DDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF888888EEEEEEFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFAAAAAAAAAAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCC FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCCCCCCFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF end %%PageTrailer %%Trailer %%EOF dune-istl-2.5.1/doc/doxygen/000077500000000000000000000000001313314427100156445ustar00rootroot00000000000000dune-istl-2.5.1/doc/doxygen/CMakeLists.txt000066400000000000000000000001141313314427100204000ustar00rootroot00000000000000# shortcut for creating the Doxyfile.in and Doxyfile add_doxygen_target() dune-istl-2.5.1/doc/doxygen/Doxylocal000066400000000000000000000004531313314427100175270ustar00rootroot00000000000000INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/dune/istl EXCLUDE += @top_srcdir@/dune/istl/test \ @top_srcdir@/dune/istl/paamg/test PREDEFINED += HAVE_SUPERLU dune-istl-2.5.1/doc/doxygen/mainpage.txt000066400000000000000000000006341313314427100201710ustar00rootroot00000000000000/** \mainpage dune-istl Automatic Documentation \section intro Introduction Welcome to the %Dune documentation pages. This documentation has been generated using Doxygen, a free source code documentation system for documenting C/C++ code. \section mods Modules The best way to start is from the page \subpage modules which gives you access to the documentation by category. */ /** \page modules Modules */ dune-istl-2.5.1/doc/doxygen/modules.txt000066400000000000000000000033351313314427100200610ustar00rootroot00000000000000/** @defgroup ISTL Iterative Solvers Template Library (ISTL) @brief Iterative Solvers supporting block recursive matrix and vector classes at compile time. The Iterative Solver Template Library applies generic programming in C++ to the domain of iterative solvers of linear systems stemming from finite element discretizations. Those discretizations exhibit a lot of structure, e.g:
  1. Certain discretizations for systems of PDEs or higher order methods result in matrices where individual entries are replaced by small blocks, say of size \f$2\times 2\f$ or \f$4\times 4\f$. Dense blocks of different sizes e.g. arise in \f$hp\f$ Discontinuous Galerkin discretization methods. It is straightforward and efficient to treat these small dense blocks as fully coupled and solve them with direct methods within the iterative method.
  2. Equation-wise ordering for systems results in matrices having an \f$n\times n\f$ block structure where \f$n\f$ corresponds to the number of variables in the PDE and the blocks themselves are large and sparse. As an example we mention the Stokes system.
  3. Other discretisation, e.~g. those of reaction/diffusion systems, produce sparse matrices whose blocks are sparse matrices of small dense blocks,
Our matrix and vector interface supports a block recursive structure. Each sparse matrix entry can itself be either a sparse or a small dense matrix. The solvers use this recursive block structure via template meta programming at compile time. ISTL consists of the \ref ISTL_SPMV "matrix and vector API" and the \ref ISTL_Solvers "solvers" which use the \ref ISTL_Prec preconditioners. */ dune-istl-2.5.1/doc/istl.bib000066400000000000000000000115451313314427100156260ustar00rootroot00000000000000@String{ap = "Ann. der Physik"} @String{as = "Acta Stereol."} @String{awr = "Adv. Water Res."} @String{ces = "Chem. Eng. Sci."} @String{mdbg = "Mitteilgn. Dtsch. Bodenkundl. Gesellsch."} @String{pre = "Phys. Rev. E"} @String{rg = "Reviews of Geophysics"} @String{ss = "Soil Sci."} @String{ste = "The Sci. of Total Environ."} @String{str = "Soil Till. Res."} @String{ta = "The Analyst"} @InProceedings{Dune, author = "P. Bastian and M. Droske and C. Engwer and R. Klöfkorn and T. Neubauer and M. Ohlberger and M. Rumpf", editor = "R. Kornhuber and {R.H.W.} Hoppe and {D.E.} Keyes and J. Périaux and O. Pironneau and J. Xu", booktitle = "Proceedings of the 15th Conference on Domain Decomposition Methods", title = "Towards a Unified Framework for Scientific Computing", publisher = "Springer-Verlag", series = {LNCSE}, note = "accepted for publication", pages = "", year = "2004", pdf = "TM105.pdf" } @Misc{BLASTForum, author = {{BLAST Forum}}, title = {Basic Linear Algebra Subprograms Technical ({BLAST}) Forum Standard}, year = {2001}, note = {\texttt{http://www.netlib.org/blas/blast-forum/}}, } @Article{BH99, author = "P. Bastian and R. Helmig", title = "Efficient fully-coupled solution techniques for two-phase flow in porous media. {P}arallel multigrid solution and large scale computations", journal = awr, volume = "23", pages = "199--216", year = "1999", pdf = "AdvWatRes2.pdf", bibsource = "file://tahiti/home/peter/TeX/bibtex/PeterBastian.bib", } @InProceedings{MTL_SciTools98, author = {J. Siek and A. Lumsdaine}, title = {A Modern Framework for Portable High-Performance Numerical Linear Algebra}, booktitle = {Advances in Software Tools for Scientific Computing}, pages = {1--56}, year = {2000}, editor = {{H. P.} Langtangen and {A. M.} Bruaset and E. Quak}, volume = {10}, series = {LNCSE}, publisher = {Springer-Verlag}, } @Misc{MTL, key = {MTL}, title = {Matrix Template Library}, note = {\texttt{http://www.osl.iu.edu/research/mtl/}}, } @Misc{ITL, key = {ITL}, title = {Iterative Template Library}, note = {\texttt{http://www.osl.iu.edu/research/itl/}}, } @Misc{DuneWeb, author = {DUNE}, note = {\texttt{http://www.dune-project.org/}}, } @Misc{Blitz, key = {Blitz++}, title = {Blitz++}, note = {\texttt{http://www.oonumerics.org/blitz/}}, } @Misc{LALinks, author = {Jack Dongarra}, title = {List of freely available software for linear algebra on the web}, year = {2006}, note = {\texttt{http://netlib.org/utk/people/JackDongarra/la-sw.html}} } @Book{Stroustrup, author = {B. Stroustrup}, ALTeditor = {}, title = {The {C++} Programming Language}, publisher = {Addison-Wesley}, year = {1997} } @Book{BN, author = {{J. J.} Barton and {L. R.} Nackman}, ALTeditor = {}, title = {Scientific and Engineering {C++}}, publisher = {Addison-Wesley}, year = {1994} } @TechReport{Veldhui99, author = {T. Veldhuizen}, title = {Techniques for Scientific {C}++}, institution = {Indiana University}, year = {1999}, note = {Computer Science Department} } @Misc{Labook, OPTkey = {}, author = {J.~Hefferson}, title = {Linear Algebra}, OPThowpublished = {in the web}, month = {May}, year = {2006}, note = {\texttt{http://joshua.amcvt.edu/}}, OPTannote = {} } @Misc{petsc-web-page, key = {PETSc}, author = {PETSc}, Note = {\texttt{http://www.mcs.anl.gov/petsc/}} } @TechReport{petsc-user-ref, Author = "S.~Balay and K.~Buschelman and V.~Eijkhout and W.~D.~Gropp and D.~Kaushik and M.~G.~Knepley and L.~C.~McInnes and B.~F.~Smith and H~Zhang", Title = "{PETS}c Users Manual", Number = "ANL-95/11 - Revision 2.1.5", Institution = "Argonne National Laboratory", Year = "2004"} @InProceedings{petsc-efficient, Author = "S.~Balay and W.~D.~Gropp and L.~C.~McInnes and B.~F.~Smith", Title = "Efficient Management of Parallelism in Object Oriented Numerical Software Libraries", Booktitle = "Modern Software Tools in Scientific Computing", Editor = "E. Arge and A. M. Bruaset and H. P. Langtangen", Pages = "163--202", Publisher = "Birkh{\"{a}}user Press", Year = "1997"} @Article{dddalg, author = {G.~Haase and U.~Langer and A.~Meyer}, title = {The Approximate Dirichlet Domain Decomposition Method. Part I: An Algebraic Approach}, journal = {Computing}, year = {1991}, OPTkey = {}, volume = {47}, OPTnumber = {}, pages = {137--151}, OPTmonth = {}, OPTnote = {}, OPTannote = {}, publisher = {Springer-Verlag Wien} }dune-istl-2.5.1/doc/istl.tex000066400000000000000000001034431313314427100156710ustar00rootroot00000000000000\documentclass[11pt]{article} \usepackage{multicol} \usepackage{ifthen} %\usepackage{multitoc} %\usepackage{german} %\usepackage{bibgerm} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{color} \usepackage{hyperref} \usepackage[dvips]{epsfig} \usepackage{subfigure} \usepackage[dvips]{graphicx} \usepackage[a4paper,body={148mm,240mm,nohead}]{geometry} \usepackage[ansinew]{inputenc} \usepackage{listings} \lstset{language=C++, basicstyle=\ttfamily, stringstyle=\ttfamily, commentstyle=\it, extendedchars=true} \newif\ifpdf \ifnum\ifx\pdfoutput\undefined0\else\pdfoutput\fi<1 \pdffalse % we are not running PDFLaTeX \else \pdftrue % we are running PDFLaTeX \fi \ifpdf \usepackage[pdftex]{graphicx} \else \usepackage{graphicx} \fi \ifpdf \DeclareGraphicsExtensions{.pdf, .jpg, .tif} \else \DeclareGraphicsExtensions{.eps, .jpg} \fi \newcommand{\C}{\mathbb{C}} \newcommand{\R}{\mathbb{R}} \newcommand{\N}{\mathbb{N}} \newcommand{\Z}{\mathbb{Z}} \newcommand{\Q}{\mathbb{Q}} \newcommand{\K}{\mathbb{K}} \title{Iterative Solver Template Library\thanks{Part of the Distributed and Unified Numerics Environment (DUNE) which is available from the site \url{http://www.dune-project.org/}}} \author{% Peter Bastian, Markus Blatt\\ Institut f\"ur parallele und verteilte Systeme (IPVS),\\ Universit\"at Stuttgart, Universit\"atsstr. 38, D-70569 Stuttgart, \\ email: \texttt{Peter.Bastian@ipvs.uni-stuttgart.de}, \texttt{Markus.Blatt@ipvs.uni-stuttgart.de}} \date{April 13, 2007} \begin{document} \maketitle \begin{abstract} This document describes the rationale behind and use of the Iterative Solver Template Library (ISTL) which provides a set of C++ templates to represent vectors, (sparse) matrices and some generic algorithms based on these. The most prominent features of the matrix/vector classes is that they support a recursive block structure in a bottom up way. The classes can be used, e.~g., to efficiently implement block preconditioners for $hp$-finite elements. \end{abstract} \begin{multicols}{2} {\small\tableofcontents} \end{multicols} \section{Introduction} The numerical solution of partial differential equations (PDEs) frequently requires the solution of large and sparse linear systems. Naturally, there are many libraries available on the internet for doing sparse matrix/vector computations. A comprehensive overview is given in \cite{LALinks}. The widely availably Basic Linear Algebra Subprograms (BLAS) standard has been extended to cover als sparse matrices \cite{BLASTForum}. BLAS divides the available functions into level 1 (vector operations), level 2 (vector/matrix operations) and level 3 (matrix/matrix operations). BLAS for sparse matrices contains only level 1 and 2 functionality and is quite different to the standard for dense matrices. The standard uses procedural programming style and offers only a FORTRAN and C interface. As a consequence, the interface is ``coarse grained'', meaning that ``small'' functions such as access to individual matrix elements is relatively slow. Generic programming techniqes in C++ offer the possibility to combine flexibility and reuse (``efficiency of the programmer'') with fast execution (``efficieny of the program'') as has been demonstrated with the Standard Template Library (STL), \cite{Stroustrup} or the Blitz++ library for multidimensional arrays \cite{Blitz}. A variety of template programming techniques such as traits, template metaprograms, expression templates or the Barton-Nackman trick are used in the implementations, see \cite{BN,Veldhui99} for an introduction. Application of these ideas to matrix/vector operations is available with the Matrix Template Library (MTL), \cite{MTL,MTL_SciTools98}. The Iterative Template Library (ITL), \cite{ITL}, implements iterative solvers for linear systems (mostly Krylov subspace methods) in a generic way based on MTL. The Distributed and Unified Numerics Environment (DUNE), \cite{Dune,DuneWeb}, applies the STL ideas to finite element computations. Why bother with yet another OO-implementation of (sparse) linear algebra when libraries, most notably the MTL, are available? The most important reason is that the functionality in existing libraries has not been designed specifically with advanced finite element methods in mind. Sparse matrices in finite element computations have a lot of structure. Here are some examples: \begin{itemize} \item Certain discretizations for systems of PDEs or higher order methods result in matrices where individual entries are replaced by small blocks, say of size $2\times 2$ or $4\times 4$, see Fig. \ref{fig:festructure}(a). Dense blocks of different sizes e.~g. arise in $hp$ Discontinuous Galerkin discretization methods, see Fig. \ref{fig:festructure}(b). Straightforward iterative methods solve these small blocks exactly, see e.~g.~\cite{BH99}. \item Equation-wise ordering for systems results in matrices having an $n\times n$ block structure where $n$ corresponds to the number of variables in the PDE and the blocks themselves are large, see Fig. \ref{fig:festructure}(d). As an example we mention the Stokes system. Iterative solvers such as the SIMPLE or Uzawa algorithm use this structure. \item Other discretizations, e.~g. those of reaction/diffusion systems, produce sparse matrices whose blocks are sparse matrices of small dense blocks, see fig. \ref{fig:festructure}(c). \item Other structures that can be exploited are the level structure arising from hierarchic meshes, a p-hierarchic structure (e.~g.~decomposition in linear and quadratic part), geometric structure from decomposition in subdomains or topological structure where unknowns are associated with nodes, edges, faces or elements of a mesh. \end{itemize} \begin{figure}[htb] \centering \epsfig{file=blockstructure, scale=0.485} \caption{Block structure of matrices arising in the finite element method} \label{fig:festructure} \end{figure} It is very important to note that this structure is typically known at compile-time and this knowledge should be exploited to produce efficient code. Moreover, block structuredness is recursive, i.~e.~matrices are build from blocks which can themselves be build from blocks. The Matrix Template Library also offers the possibility to partition a matrix into blocks. However, their concept is top-down, i.~e.~an already existing matrix is enriched by additional information to implement the block structure. This is done at run-time and might thus be less efficient and requires additional memory. In contrast the bottom-up composition of block matrices from blocks can save memory. We would like to stress that the library to be presented in this paper is not nearly as broad in scope as the MTL. \section{Vectors} The interface of our vector classes is designed according to what they represent from a mathematical point of view. The vector classes are representations of vector spaces. \subsection{Vector spaces} In mathemetics vectors are elements of a vector space. A vector space $V(\K)$, defined over a field $\K$, is a set of elements with two operations: (i) vector space addition $+ : V\times V \to V$ and (ii) scalar multiplication $* : \K\times V \to V$. These operations obey certain formal rules, see your favourite textbook on linear algebra, e.~g. \cite{LaBook}. In addition a vector space may be normed, i.~e.~there is a function (obeying certain rules) $\|.\| : V \to \R$ which measures distance in the vector space. Even more specialized vector spaces have a scalar product which is a function $\cdot : V\times V \to \K$. How do you construct a vector space? The easiest way is to take a field, such as $\K=\R$ or $\K=\C$ and take a tensor product: \begin{equation*} V = \K^n = \underbrace{\K\times\K\times\ldots\times\K}_{\text{$n$ times}}. \end{equation*} $n\in\N$ is called the dimension of the vector space. There are also infinite-dimensional vector spaceswhich are, however, not of interest in the context here. The idea of tensor products can be generalized. If we have vector spaces $V_1(\K),\ldots,V_n(\K)$ we can construct a new vector space by setting \begin{equation*} V(\K) = V_1\times V_2 \times \ldots \times V_n. \end{equation*} The $V_i$ can be \textit{any} vector space over the field $\K$. The dimension of $V$ is the sum of the dimensions of the $V_i$. For a mathematician every finite-dimensional vector space is isomorphic to the $\R^k$ for an appropriate $k$, but in our applications it is important to know the difference between $(\R^2)^7$ and $\R^{14}$. Having these remarks about vector spaces in mind we can now turn to the class design. \subsection{Vector classes} ISTL provides the following classes to make up vector spaces: \paragraph{FieldVector.} The \lstinline!template FieldVector! class template is used to represent a vector space $V=\K^n$ where the field is given by the type \lstinline!K!. \lstinline!K! may be \lstinline!double!, \lstinline!float!, \lstinline!complex! or any other numeric type. The dimension given by the template parameter \lstinline!n! is assumed to be small. Members of this class are implemented with template metaprograms to avoid tiny loops. Example: Use \lstinline!FieldVector! to define vectors with a fixed dimension 2. \paragraph{BlockVector.} The \lstinline!template BlockVector! class template builds a vector space $V=B^n$ where the ``block type'' $B$ is given by the template parameter \lstinline!B!. \lstinline!B! may be any other class implementing the vector interface. The number of blocks $n$ is given at run-time. Example: \begin{lstlisting}{} BlockVector > \end{lstlisting} can be used to define vectors of variable size where each block in turn consists of two \lstinline!double! values. \paragraph{VariableBlockVector.} \label{class:varblockvec} The \lstinline!template VariableBlockVector! class can be used to construct a vector space having a two-level block structure of the form $V=B^{n_1}\times B^{n_2}\times\ldots \times B^{n_m}$, i.e. it consists of $m$ blocks $i=1,\ldots,m$ and each block in turn consists of $n_i$ blocks given by the type \lstinline!B!. In principle this structure could be built also with the previous classes but the implementation here is more efficient. It allocates memory in one big array for all components and for certain operations it is more efficient to interpret the vector space as $V=B^{\sum_{i=1}^{m} n_i}$. \subsection{Vectors are containers} Vectors are containers over the base type \lstinline!K! or \lstinline!B! in the sense of the Standard Template Library. Random access is provided via \lstinline!operator[](int i)! where the indices are in the range $0,\ldots,n-1$ with the number of blocks $n$ given by the \lstinline!N! method. Here is a code fragment for illustration: \begin{lstlisting}{} typedef Dune::FieldVector,2> BType; Dune::BlockVector v(20); v[1] = 3.14; v[3][0] = 2.56; v[3][1] = std::complex(1,-1); \end{lstlisting} Note how one \lstinline!operator[]()! is used for each level of block recursion. Sequential access to container elements is provided via iterators. Here is a generic function accessing all the elements of a vector: \begin{lstlisting}{} template void f (V& v) { typedef typename V::Iterator iterator; for (iterator i=v.begin(); i!=v.end(); ++i) *i = i.index(); typedef typename V::ConstIterator const_iterator; for (const_iterator i=v.begin(); i!=v.end(); ++i) std::cout << (*i).two_norm() << std::endl; } \end{lstlisting} The \lstinline!Iterator! class provides read/write access while the \lstinline!ConstIterator! provides read-only access. The type names are accessed via the \lstinline!::!-operator from the scope of the vector class. A uniform naming scheme enables writing of generic algorithms. The following types are provided in the scope of any vector class: \subsection{Operations} A full list of all members of a vector class is given in Table \ref{Tab:VectorMembers}. The norms are the same as defined for the sparse BLAS standard \cite{BLASTForum}. The ``real'' variants avoid the evaluation of a square root for each component in case of complex vectors. The \lstinline!allocator_type! member type is explained below in the section on memory management. \begin{table}[htb] \begin{center} \begin{tabular}{|l|l|l|} \hline \textbf{expression} & \textbf{return type} & \textbf{note}\\ \hline \hline \texttt{X::field\_type} & T & T is assignable\\ \texttt{X::block\_type} & T & T is assignable\\ \texttt{X::allocator\_type} & T & see mem.~mgt.\\ \texttt{X::blocklevel} & \texttt{int} & block levels inside\\ \texttt{X::Iterator} & T & read/write access\\ \texttt{X::ConstIterator} & T & read-only access\\ \hline \texttt{X::X()} & & empty vector \\ \texttt{X::X(X\&)} & & deep copy\\ \texttt{X::}$\sim$\texttt{X()} & & free memory\\ \texttt{X::operator=(X\&)} & \texttt{X\&} & \\ \texttt{X::operator=(field\_type\&)} & \texttt{X\&} & from scalar\\ \hline \texttt{X::operator[](int)} & \texttt{block\_type\&} & \\ \texttt{X::operator[](int)} & \texttt{const block\_type\&} & \\ \texttt{X::begin()} & \texttt{Iterator} & \\ \texttt{X::end()} & \texttt{Iterator} & \\ \texttt{X::rbegin()} & \texttt{Iterator} & for reverse iteration \\ \texttt{X::rend()} & \texttt{Iterator} & \\ \texttt{X::find(int)} & \texttt{Iterator} & \\ \hline \texttt{X::operator+=(X\&)} & \texttt{X\&} & $x = x+y$\\ \texttt{X::operator-=(X\&)} & \texttt{X\&} & $x = x-y$\\ \texttt{X::operator*=(field\_type\&)} & \texttt{X\&} & $x = \alpha x$\\ \texttt{X::operator/=(field\_type\&)} & \texttt{X\&} & $x = \alpha^{-1} x$\\ \texttt{X::axpy(field\_type\&,X\&)} & \texttt{X\&} & $x = x+\alpha y$\\ \texttt{X::operator*(X\&)} & \texttt{field\_type} & $x\cdot y$\\ \hline \texttt{X::one\_norm()} & \texttt{double} & $\sum_i\sqrt{Re(x_i)^2+Im(x_i)^2}$\\ \texttt{X::one\_norm\_real()} & \texttt{double} &$\sum_i(|Re(x_i)|+|Im(x_i)|)$\\ \texttt{X::two\_norm()} & \texttt{double} &$\sqrt{\sum_i(Re(x_i)^2+Im(x_i)^2)}$\\ \texttt{X::two\_norm2()} & \texttt{double} &$\sum_i (Re(x_i)^2+Im(x_i)^2)$\\ \texttt{X::infinity\_norm()} & \texttt{double} &$\max_i\sqrt{Re(x_i)^2+Im(x_i)^2}$\\ \texttt{X::infinity\_norm\_real()} & \texttt{double} &$\max_i(|Re(x_i)|+|Im(x_i)|)$\\ \hline \texttt{X::N()} & \texttt{int} & number of blocks\\ \texttt{X::dim()} & \texttt{int} & dimension of space\\ \hline \end{tabular} \end{center} \caption{Members of a class \lstinline!X! conforming to the vector interface.} \label{Tab:VectorMembers} \end{table} \subsection[Memory model]{Object memory model and memory management} The memory model for all ISTL objects is deep copy as in the Standard Template Library and in contrast to the Matrix Template Library. Therefore, references must be used to avoid excessive copying of objects. On the other hand temporary vectors with appropriate structure can be generated simply with the copy constructor. \subsection{Vector creation} \section{Matrices} \subsection{Linear mappings} \subsection{Matrix classes} For a matrix representing a linear map (or homomorphism) $A: V \mapsto W$ from vector space $V$ to vector space $W$ the recursive block structure of the matrix rows and columns immediately follows from the recursive block structure of the vectors representing the domain and range of the mapping, respectively. As a natural consequence we designed the following matrix classes: \paragraph{FieldMatrix.} the \lstinline!template FieldMatrix! class template is used to represent a linear map $M: V_1 \to V_2$ where $V_1=\K^n$ and $V_2=\K^m$ are vector spaces over the field given by template parameter \lstinline!K!. \lstinline!K! may be \lstinline!double!, \lstinline!float!, \lstinline!complex! or any other numeric type. The dimensions of the two vector spaces given by the template parameters \lstinline!n! and \lstinline!m! are assumed to be small. The matrix is stored as a dense matrix. Example: Use \lstinline!FieldMatrix! to define a linear map from a vector space over doubles with dimension $2$ to one with dimension $3$. \paragraph{BCRSMatrix.} The \lstinline!template BCRSMatrix! class template represents a sparse matrix where the ``block type'' $B$ is given by the template parameter \lstinline!B!. \lstinline!B! may be any other class implementing the matrix interface. The matrix class uses a compressed row storage scheme. \paragraph{VariableBCRSMatrix.} The \lstinline!template VariableBCRSMatrix! class can be used to construct a linear map between two vector spaces having a two-level block structure $V=B^{n_1}\times B^{n_2}\times\ldots \times B^{n_m}$ and $W=B^{m_1}\times B^{m_2}\times\ldots \times B^{m_k}$. Both are represented by the \lstinline!template VariableBlockVector! class, see~\ref{class:varblockvec}. This is not implemented yet. \subsection[Matrix containers]{Matrices are containers of containers} Matrices are containers over the matrix rows. The matrix rows are containers over the type \lstinline!K! or \lstinline!B! in the sense of the Standard Template Library. Random access is provided via \lstinline!operator[](int i)! on the matrix to the matrix rows and on the matrix rows to the matrix columns (if present). Note that except for \lstinline!FieldMatrix!, which is a dense matrix, \lstinline!operator[]! on the matrix row triggers a binary search for the column. For sequential access use \lstinline!RowIterator! and \lstinline!ColIterator! for read/write access or \lstinline!ConstRowIterator! and \lstinline!ConstColIterator! for readonly access to rows and columns, respectively. Here is a small example that prints the sparsity pattern of a matrix of type \lstinline!M!: \begin{lstlisting}{} typedef typename M::ConstRowIterator RowI; typedef typename M::ConstColIterator ColI; for(RowI row = matrix.begin(); row != matrix.end(); ++row){ std::cout << "row "<begin(); col != row->end(); ++col) std::cout<1$ then each block $A_{ij}$ can be treated as (or actually is) a matrix itself. This recursiveness can be exploited in generic algorithm using the defined \lstinline!block_level! of the matrix and vector classes. Most preconditioner can be modified to honor this recursive structure for a specific number of block levels $k$. They then work as normal on the offdiagonal blocks, treating them as traditional matrix entries. For the diagonal values a special procedure applies: If $k>1$ the diagonal is treated as a matrix itself and the preconditioner is applied recursively on the matrix representing the diagonal value $D=A_{ii}$ with blocklevel $k-1$. For the case that $k=1$ the diagonal is treated as a matrix entry resulting in a linear solve or an identity operation depending on the algorithm. \subsection{Triangular solves} In the formulation of most iterative methods upper and lower triangular and diagonal solves play an important role. ISTL provides block recursive versions of these generic building blocks using template metaprogramming, see Table \ref{Tab:TriangularSolves} for a listing of these methods. In the table matrix $A$ is decomposed into $A=L+D+U$, where $L$ is a strictly lower block triangular, $D$ is a block diagonal and $U$ is a strictly upper block triangular matrix. An arbitrary block recursion level can be given by an additional parameter. If this parameter is omitted it defaults to $1$. \begin{table}[htb] \begin{center} \begin{tabular}{|l|l|} \hline \textbf{function} & \textbf{computation}\\ \hline \hline \texttt{bltsolve(A,v,d)} & $v=(L+D)^{-1}d$\\ \texttt{bltsolve(A,v,d,$\omega$)} & $v=\omega(L+D)^{-1}d$\\ \texttt{ubltsolve(A,v,d)} & $v=L^{-1}d$\\ \texttt{ubltsolve(A,v,d,$\omega$)} & $v=\omega L^{-1}d$\\ \hline \texttt{butsolve(A,v,d)} & $v=(D+U)^{-1}d$\\ \texttt{butsolve(A,v,d,$\omega$)} & $v=\omega(D+U)^{-1}d$\\ \texttt{ubutsolve(A,v,d)} & $v=U^{-1}d$\\ \texttt{ubutsolve(A,v,d,$\omega$)} & $v=\omega U^{-1}d$\\ \hline \texttt{bdsolve(A,v,d)} & $v=D^{-1}d$\\ \texttt{bdsolve(A,v,d,$\omega$)} & $v=\omega D^{-1}d$\\ \hline \end{tabular} \end{center} \caption{Functions available for block triangular and block diagonal solves. The matrix $A$ is decomposed into $A=L+D+U$ where $L$ is strictly lower block triangular, $D$ is block diagonal and $U$ is strictly upper block triangular. Standard is one level of block recursion, arbitrary level can be given by additional parameter.} \label{Tab:TriangularSolves} \end{table} \subsection{Simple iterative solvers} Using the same block recursive template metaprogramming technique, kernels for the defect formulations of simple iterative solvers are available in ISTL. The number of block recursion levels can again be given as an additional argument. See Table \ref{Tab:IterativeSolvers} for a list of these kernels. \begin{table}[htb] \begin{center} \begin{tabular}{|l|l|} \hline \textbf{function} & \textbf{computation}\\ \hline \hline \texttt{dbjac(A,x,b,$\omega$)} & $x=x+\omega D^{-1}(b-Ax)$ \\ \texttt{dbgs(A,x,b,$\omega$)} & $x = x + \omega (L+D)^{-1}(b-Ax)$\\ \texttt{bsorf(A,x,b,$\omega$)} & $x^{k+1}_i = x^k_i + \omega A_{ii}^{-1}\left [ b_i - \sum\limits_{ji} A_{ij}x^{k+1}_j\right ]$\\ \hline \end{tabular} \end{center} \caption{Kernels for iterative solvers. The matrix $A$ is decomposed into $A=L+D+U$ where $L$ is strictly lower block triangular, $D$ is block diagonal and $U$ is strictly upper block triangular. Standard is one level of block recursion, arbitrary level can be given by additional parameter.} \label{Tab:IterativeSolvers} \end{table} \subsection{Sparse LU decomposition} \section{Solver Interface} \label{sec:solver-interface} The solvers in ISTL do not work on matrices directly. Instead we use an abstract Operator concept. Thus we can even model and solve linear maps that are not stored as matrices (e.~g. on the fly computed linear operators). \subsection{Operators} \label{sec:operators} {\lstset{breaklines=true} The base class \lstinline!template LinearOperator! represents linear maps. The template parameter \lstinline!X! is the type of the domain and \lstinline!Y! is the type of the range of the operator. A linear operator provides the methods \lstinline!apply(const X& x, Y& y)! and apply \lstinline!applyscaledadd(const X& x, Y& y)! performing the operations $y = A(x)$ and $y = y + \alpha A(x)$, respectively. The subclass \lstinline!template AssembledLinearOperator! represents linear operators that have a matrix representation. Conversion from any matrix into a linear operator is done by the class \lstinline!template MatrixAdapter!. \subsection{Scalarproducts} \label{sec:scalarproducts} For convergence tests and the stopping criteria Krylow methods need to compute scalar products and norms on the underlying vector spaces. The base class \lstinline!template Scalarproduct! provides methods \lstinline!field_type dot(const X& x, const X&y)! and \lstinline!double norm(const X& x)! to calculate these. For sequential programs use \lstinline!template SeqScalarProduct! which simply maps this to functions of the vector implementations. \subsection{Preconditioners} \label{sec:preconditioners} The \lstinline!template Preconditioner! provides the abstract base class for all precondioners in ISTL. The method \lstinline!void pre(X& x, Y& b)! has to be called before applying the preconditioner. Here \lstinline!x! is the left hand side and \lstinline!b! is the right hand side of the operator equation. The method may, e.~g. scale the system, allocate memory or compute an (I)LU decomposition. The method \lstinline!void apply(X& v, const Y&)! applies one step of the preconditioner to the system $A(\vec v)=\vec d$. Here \lstinline!b! should contain the current defect and \lstinline!v! should be $0$. Upon exit of the method \lstinline!v! contains the computed update to the current guess, i.~e. $\vec v = M^{-1} \vec d$ where $M$ is the approximate inverse of the operator $A$ characterizing the preconditioner. The method \lstinline!void post(X& x)! should be called after all computations to give the precondtioner the chance to clean allocated resources. See Table \ref{tab:precond} for a list of available preconditioner. \begin{table}[htb] \centering \caption{Preconditioners} \label{tab:precond} \begin{tabular}{|l|l|c|c|} \hline \textbf{class} & \textbf{implements}&\textbf{s/p}& \textbf{recursive}\\\hline\hline \lstinline!SeqJac! & Jacobi method& s & x\\ \lstinline!SeqSOR! & successive overrelaxation (SOR) & s& x\\ \lstinline!SeqSSOR! & symmetric SSOR & s&x\\ \lstinline!SeqILU! & incomplete LU decomposition (ILU)& s&\\ \lstinline!SeqILUN! & ILU decpmposition of order N &s&\\ \lstinline!Pamg::AMG! & algebraic multigrid method &s/p&\\ \lstinline!BlockPreconditioner!& Additive overlapping Schwarz&p&\\\hline \end{tabular} \end{table} They have the template parameters \lstinline!M! representing the type of the matrix they work on, \lstinline!X! representing the type of the domain, \lstinline!Y! representing the type of the range of the linear system. The block recursive preconditioner are marked with ``x'' in the last column. For them the recursion depth is specified via an additional template parameter \lstinline!int l!. The column labeled ``s/p'' specifies whether they support {\bf s}equential and/or {\bf p}arallel mode. \subsection{Solvers} \label{sec:solvers} All solvers are subclasses of the abstract base class \lstinline!template InverseOperator! representing the inverse of an operator from the domain of type \lstinline!X! to the range of type \lstinline!Y!. The actual solve of the system $A(\vec x)=\vec b$ is done in the method \lstinline!void apply(X& x, Y& b, InverseOperatorResult& r)!. In the \lstinline!InverseOperatorResult! some statistics about the solution process, e.~g. iteration count, achieved defect reduction, etc., are stored. All solvers only use methods of instances of \lstinline!LinearOperator!, \lstinline!ScalarProduct! and \lstinline!Preconditioner!. These are provided in the constructor. See Table \ref{tab:solvers} for a list of available solvers. All solvers are template classes with a template parameter \lstinline!X! providing them with the vector implementation used. \begin{table}[htb] \centering \caption{ISTL Solvers} \label{tab:solvers} \begin{tabular}{|l|l|} \hline \textbf{class}&\textbf{implements}\\\hline\hline \lstinline!LoopSolver!& only apply precoditioner multiple time\\ \lstinline!GradientSolver!& preconditioned radient method\\ \lstinline!CGSolver!&preconditioned conjugate gradient method\\ \lstinline!BiCGStab!&preconditioned biconjugate gradient stabilized method\\\hline \end{tabular} \end{table} \subsection{Parallel Solvers} \label{sec:parallelism} Instead of using parallel data structures (matrices and vectors) that (implicitly) know the data distribution and communication patterns like in PETSc \cite{petsc-web-page,petsc-user-ref} we decided to decouple the parallelization from the data structures used. Basically we provide an abstract consistency model on top of our linear algebra. This is hidden in the parallel implementations of the interfaces of \lstinline!LinearOperator!, \lstinline!Scalarproduct! and \lstinline!Preconditioner!, which assure consistency of the data (by communication) for the \lstinline!InverseOperator! implementation. Therefore the same Krylow method algorithms work in parallel and sequential mode. Based on the idea proposed in \cite{dddalg} we implemented parallel overlapping Schwarz preconditioners with inexact (sequential) subdomain solvers and a parallel algebraic multigrid preconditioner together with appropriate implementations of \lstinline!LinearOperator! and \lstinline!Scalarproduct!. Nonoverlapping versions are currently being worked on. Note that using this approach it easy two switch form the currently implemented MPI version to new parallel programming paradigms that might be needed on new platforms. \section{Performance} We evaluated the performance of our implementation on a Petium 4 Mobile 2.4 GHz with a measured memory bandwidth of 1084 MB/s for the daypy operation ($x = y + \alpha z$) in Tables \ref{tab:istl_performance}. \begin{table}[htb] \centering \caption{Performance Tests} \label{tab:istl_performance} \mbox{\small \subtable[scalar product]{\label{tab:perf_sp} \begin{tabular}{lrrrrr} \hline \hline $N$ & 500 & 5000 & 50000 & 500000 & 5000000 \\ \hline MFLOPS & 896 & 775 & 167 & 160 & 164 \\ \hline \hline \end{tabular}} \subtable[daxpy operation $y = y + \alpha x$]{\label{tab:perf_daxpy} \begin{tabular}{rrrrr} \hline \hline 500 & 5000 & 50000 & 500000 & 5000000 \\ \hline 936 & 910 & 108 & 103 & 107 \\ \hline \hline \end{tabular}}} \mbox{\small \subtable[Matrix-vector product, %\lstinline!BCRSMatrix!, 5-point stencil, $b$: block size]{\label{tab:perf_mvp} \begin{tabular}{lrrrrr} \hline \hline $N,b$ & 100,1 & 10000,1 & 1000000,1 & 1000000,2 & 1000000,3\\ \hline MFLOPS & 388 & 140 & 136 & 230 & 260\\ \hline \hline \end{tabular}} \subtable[Damped Gau\ss{}--Seidel]{\label{tab:perf_gs} \begin{tabular}{rrr} \hline \hline & \mbox{C } & ISTL\\ \hline time / it. [s] & 0.17 & 0.18\\ \hline \hline \end{tabular}}} \end{table} The code was comiled with the GNU C++ compiler version 4.0 with -O3 optimization. In the tables $N$ is the number of unknown blocks (equals the number of unknows for the scalar cases in Tables \ref{tab:perf_sp}, \ref{tab:perf_daxpy}, \ref{tab:perf_gs}). The performance for the scalarproduct, see Table \ref{tab:perf_sp}, and the daxpy operation, see Table \ref{tab:perf_daxpy} is nearly optimal and for large $N$ the limiting factor is clearly the memory bandwidth. Table \ref{tab:perf_mvp} shows that we take advantage of cache reusage for matrices of dense blocks with block size $b>1$. In Table \ref{tab:perf_gs} we compared the generic implementation of the Gau\ss{}--Seidel solver in ISTL with a specialized C implementation. The measured times per iteration show that there is now lack of computational efficiency due to the generic implementation. % bibtex bibliography \bibliographystyle{plain} \bibliography{istl.bib} % some links % http://www.netlib.org/blas/blast-forum/ % http://www.osl.iu.edu/research/mtl/ % http://www.osl.iu.edu/research/itl/ (based on MTL, mostly Krylov) % http://netlib.org/utk/people/JackDongarra/la-sw.html % the last one: FREELY AVAILABLE SOFTWARE FOR % LINEAR ALGEBRA ON THE WEB (May 2004) by Jack Dongarra % http://www.oonumerics.org/blitz/ \end{document} dune-istl-2.5.1/dune-istl.pc.in000066400000000000000000000005101313314427100162530ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ CXX=@CXX@ CC=@CC@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ Description: Dune (Distributed and Unified Numerics Environment) istl module URL: http://dune-project.org/ Requires: ${DEPENDENCIES} Libs: Cflags: -I${includedir} dune-istl-2.5.1/dune.module000066400000000000000000000002041313314427100155600ustar00rootroot00000000000000Module: dune-istl Version: 2.5.1 Maintainer: dune-devel@lists.dune-project.org Depends: dune-common (>= 2.5.0) Whitespace-Hook: Yes dune-istl-2.5.1/dune/000077500000000000000000000000001313314427100143555ustar00rootroot00000000000000dune-istl-2.5.1/dune/CMakeLists.txt000066400000000000000000000000271313314427100171140ustar00rootroot00000000000000add_subdirectory(istl) dune-istl-2.5.1/dune/istl/000077500000000000000000000000001313314427100153305ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/CMakeLists.txt000066400000000000000000000016031313314427100200700ustar00rootroot00000000000000add_subdirectory("eigenvalue") add_subdirectory("paamg") add_subdirectory("tutorial") add_subdirectory(test) #install headers install(FILES basearray.hh bcrsmatrix.hh bdmatrix.hh btdmatrix.hh bvector.hh colcompmatrix.hh gsetc.hh ilu.hh ilusubdomainsolver.hh io.hh istlexception.hh ldl.hh matrix.hh matrixindexset.hh matrixmarket.hh matrixmatrix.hh matrixredistribute.hh matrixutils.hh multitypeblockmatrix.hh multitypeblockvector.hh novlpschwarz.hh operators.hh overlappingschwarz.hh owneroverlapcopy.hh pardiso.hh preconditioner.hh preconditioners.hh repartition.hh scalarproducts.hh scaledidmatrix.hh schwarz.hh solvercategory.hh solver.hh solvers.hh solvertype.hh spqr.hh superlu.hh supermatrix.hh umfpack.hh vbvector.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/istl) dune-istl-2.5.1/dune/istl/basearray.hh000066400000000000000000000442521313314427100176310ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_BASEARRAY_HH #define DUNE_ISTL_BASEARRAY_HH #include "assert.h" #include #include #include #include #include "istlexception.hh" #include /** \file \brief Implements several basic array containers. */ namespace Dune { /** \brief A simple array container for objects of type B Implement. - iterator access - const_iterator access - random access This container has *NO* memory management at all, copy constuctor, assignment and destructor are all default. The constructor is made protected to emphasize that objects are only usable in derived classes. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \todo There shouldn't be an allocator argument here, because the array is 'unmanaged'. And indeed, of the allocator, only its size_type is used. Hence, the signature of this class should be changed to \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the components typedef B member_type; //! export the allocator type typedef A allocator_type; //! the type for the index access typedef typename A::size_type size_type; //===== access to components //! random access to blocks B& operator[] (size_type i) { #ifdef DUNE_ISTL_WITH_CHECKING if (i>=n) DUNE_THROW(ISTLError,"index out of range"); #endif return p[i]; } //! same for read only access const B& operator[] (size_type i) const { #ifdef DUNE_ISTL_WITH_CHECKING if (i>=n) DUNE_THROW(ISTLError,"index out of range"); #endif return p[i]; } /** \brief Iterator implementation class */ template class RealIterator : public RandomAccessIteratorFacade, T> { public: //! \brief The unqualified value type typedef typename std::remove_const::type ValueType; friend class RandomAccessIteratorFacade, const ValueType>; friend class RandomAccessIteratorFacade, ValueType>; friend class RealIterator; friend class RealIterator; //! constructor RealIterator () : p(0), i(0) {} RealIterator (const B* _p, B* _i) : p(_p), i(_i) { } RealIterator(const RealIterator& it) : p(it.p), i(it.i) {} //! return index size_type index () const { return i-p; } //! equality bool equals (const RealIterator& other) const { assert(other.p==p); return i==other.i; } //! equality bool equals (const RealIterator& other) const { assert(other.p==p); return i==other.i; } std::ptrdiff_t distanceTo(const RealIterator& o) const { return o.i-i; } private: //! prefix increment void increment() { ++i; } //! prefix decrement void decrement() { --i; } // Needed for operator[] of the iterator B& elementAt (std::ptrdiff_t offset) const { return *(i+offset); } //! dereferencing B& dereference () const { return *i; } void advance(std::ptrdiff_t d) { i+=d; } const B* p; B* i; }; //! iterator type for sequential access typedef RealIterator iterator; //! begin iterator iterator begin () { return iterator(p,p); } //! end iterator iterator end () { return iterator(p,p+n); } //! @returns an iterator that is positioned before //! the end iterator of the vector, i.e. at the last entry. iterator beforeEnd () { return iterator(p,p+n-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. iterator beforeBegin () { return iterator(p,p-1); } //! random access returning iterator (end if not contained) iterator find (size_type i) { return iterator(p,p+std::min(i,n)); } //! iterator class for sequential access typedef RealIterator const_iterator; //! begin const_iterator const_iterator begin () const { return const_iterator(p,p+0); } //! end const_iterator const_iterator end () const { return const_iterator(p,p+n); } //! @returns an iterator that is positioned before //! the end iterator of the vector. i.e. at the last element. const_iterator beforeEnd () const { return const_iterator(p,p+n-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. const_iterator beforeBegin () const { return const_iterator(p,p-1); } //! random access returning iterator (end if not contained) const_iterator find (size_type i) const { return const_iterator(p,p+std::min(i,n)); } //===== sizes //! number of blocks in the array (are of size 1 here) size_type size () const { return n; } protected: //! makes empty array base_array_unmanaged () : n(0), p(0) {} //! make an initialized array base_array_unmanaged (size_type n_, B* p_) : n(n_), p(p_) {} size_type n; // number of elements in array B *p; // pointer to dynamically allocated built-in array }; /** \brief Extend base_array_unmanaged by functions to manipulate This container has *NO* memory management at all, copy constuctor, assignment and destructor are all default. A container can be constructed as empty or from a given pointer and size. This class is used to implement a view into a larger array. You can copy such an object to a base_array to make a real copy. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class base_array_window : public base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the components typedef B member_type; //! export the allocator type typedef A allocator_type; //! make iterators available as types typedef typename base_array_unmanaged::iterator iterator; //! make iterators available as types typedef typename base_array_unmanaged::const_iterator const_iterator; //! The type used for the index access typedef typename base_array_unmanaged::size_type size_type; //! The type used for the difference between two iterator positions typedef typename A::difference_type difference_type; //===== constructors and such //! makes empty array base_array_window () : base_array_unmanaged() { } //! make array from given pointer and size base_array_window (B* _p, size_type _n) : base_array_unmanaged(_n ,_p) {} //===== window manipulation methods //! set pointer and length void set (size_type _n, B* _p) { this->n = _n; this->p = _p; } //! advance pointer by newsize elements and then set size to new size void advance (difference_type newsize) { this->p += this->n; this->n = newsize; } //! increment pointer by offset and set size void move (difference_type offset, size_type newsize) { this->p += offset; this->n = newsize; } //! increment pointer by offset, leave size void move (difference_type offset) { this->p += offset; } //! return the pointer B* getptr () { return this->p; } }; /** \brief This container extends base_array_unmanaged by memory management with the usual copy semantics providing the full range of copy constructor, destructor and assignment operators. You can make - empty array - array with n components dynamically allocated - resize an array with complete loss of data - assign/construct from a base_array_window to make a copy of the data Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class base_array : public base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the components typedef B member_type; //! export the allocator type typedef A allocator_type; //! make iterators available as types typedef typename base_array_unmanaged::iterator iterator; //! make iterators available as types typedef typename base_array_unmanaged::const_iterator const_iterator; //! The type used for the index access typedef typename base_array_unmanaged::size_type size_type; //! The type used for the difference between two iterator positions typedef typename A::difference_type difference_type; //===== constructors and such //! makes empty array base_array () : base_array_unmanaged() {} //! make array with _n components base_array (size_type _n) : base_array_unmanaged(_n, 0) { if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = 0; } } //! copy constructor base_array (const base_array& a) { // allocate memory with same size as a this->n = a.n; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = 0; } // and copy elements for (size_type i=0; in; i++) this->p[i]=a.p[i]; } //! free dynamic memory ~base_array () { if (this->n>0) { int i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } } //! reallocate array to given size, any data is lost void resize (size_type _n) { if (this->n==_n) return; if (this->n>0) { int i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } this->n = _n; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = 0; } } //! assignment base_array& operator= (const base_array& a) { if (&a!=this) // check if this and a are different objects { // adjust size of array if (this->n!=a.n) // check if size is different { if (this->n>0) { int i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); // delete old memory } this->n = a.n; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = 0; } } // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } return *this; } protected: A allocator_; }; /** \brief A simple array container with non-consecutive index set. Elements in the array are of type B. This class provides - iterator access - const_iterator access - random access in log(n) steps using binary search - find returning iterator This container has *NO* memory management at all, copy constuctor, assignment and destructor are all default. The constructor is made protected to emphasize that objects are only usably in derived classes. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class compressed_base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the components typedef B member_type; //! export the allocator type typedef A allocator_type; //! The type used for the index access typedef typename A::size_type size_type; //===== access to components //! random access to blocks, assumes ascending ordering B& operator[] (size_type i) { const size_type* lb = std::lower_bound(j, j+n, i); if (lb == j+n || *lb != i) DUNE_THROW(ISTLError,"index "< class RealIterator : public BidirectionalIteratorFacade, T> { public: //! \brief The unqualified value type typedef typename std::remove_const::type ValueType; friend class BidirectionalIteratorFacade, const ValueType>; friend class BidirectionalIteratorFacade, ValueType>; friend class RealIterator; friend class RealIterator; //! constructor RealIterator () : p(0), j(0), i(0) {} //! constructor RealIterator (B* _p, size_type* _j, size_type _i) : p(_p), j(_j), i(_i) { } /** * @brief Copy constructor from mutable iterator */ RealIterator(const RealIterator& it) : p(it.p), j(it.j), i(it.i) {} //! equality bool equals (const RealIterator& it) const { assert(p==it.p); return (i)==(it.i); } //! equality bool equals (const RealIterator& it) const { assert(p==it.p); return (i)==(it.i); } //! return index corresponding to pointer size_type index () const { return j[i]; } //! Set index corresponding to pointer void setindex (size_type k) { return j[i] = k; } /** * @brief offset from the first entry. * * An iterator positioned at the beginning * has to be increment this amount of times to * the same position. */ size_type offset () const { return i; } private: //! prefix increment void increment() { ++i; } //! prefix decrement void decrement() { --i; } //! dereferencing B& dereference () const { return p[i]; } B* p; size_type* j; size_type i; }; /** @brief The iterator type. */ typedef RealIterator iterator; //! begin iterator iterator begin () { return iterator(p,j,0); } //! end iterator iterator end () { return iterator(p,j,n); } //! @returns an iterator that is positioned before //! the end iterator of the vector, i.e. at the last entry. iterator beforeEnd () { return iterator(p,j,n-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. iterator beforeBegin () { return iterator(p,j,-1); } //! random access returning iterator (end if not contained) iterator find (size_type i) { const size_type* lb = std::lower_bound(j, j+n, i); return (lb != j+n && *lb == i) ? iterator(p,j,lb-j) : end(); } //! const_iterator class for sequential access typedef RealIterator const_iterator; //! begin const_iterator const_iterator begin () const { return const_iterator(p,j,0); } //! end const_iterator const_iterator end () const { return const_iterator(p,j,n); } //! @returns an iterator that is positioned before //! the end iterator of the vector. i.e. at the last element. const_iterator beforeEnd () const { return const_iterator(p,j,n-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. const_iterator beforeBegin () const { return const_iterator(p,j,-1); } //! random access returning iterator (end if not contained) const_iterator find (size_type i) const { const size_type* lb = std::lower_bound(j, j+n, i); return (lb != j+n && *lb == i) ? const_iterator(p,j,lb-j) : end(); } //===== sizes //! number of blocks in the array (are of size 1 here) size_type size () const { return n; } protected: //! makes empty array compressed_base_array_unmanaged () : n(0), p(0), j(0) {} size_type n; // number of elements in array B *p; // pointer to dynamically allocated built-in array size_type* j; // the index set }; } // end namespace #endif dune-istl-2.5.1/dune/istl/bcrsmatrix.hh000066400000000000000000002201301313314427100200250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_BCRSMATRIX_HH #define DUNE_ISTL_BCRSMATRIX_HH #include #include #include #include #include #include #include #include #include "istlexception.hh" #include "bvector.hh" #include "matrixutils.hh" #include #include #include #include /*! \file * \brief Implementation of the BCRSMatrix class */ namespace Dune { /** * @defgroup ISTL_SPMV Sparse Matrix and Vector classes * @ingroup ISTL * @brief Matrix and Vector classes that support a block recursive * structure capable of representing the natural structure from Finite * Element discretisations. * * * The interface of our matrices is designed according to what they * represent from a mathematical point of view. The vector classes are * representations of vector spaces: * * - FieldVector represents a vector space \f$V=K^n\f$ where the field \f$K\f$ * is represented by a numeric type (e.g. double, float, complex). \f$n\f$ * is known at compile time. * - BlockVector represents a vector space \f$V=W\times W \times W \times\cdots\times W\f$ * where W is itself a vector space. * - VariableBlockVector represents a vector space having a two-level * block structure of the form * \f$V=B^{n_1}\times B^{n_2}\times\ldots \times B^{n_m}\f$, i.e. it is constructed * from \f$m\f$ vector spaces, \f$i=1,\ldots,m\f$. * * The matrix classes represent linear maps \f$A: V \mapsto W\f$ * from vector space \f$V\f$ to vector space \f$W\f$ the recursive block * structure of the matrix rows and columns immediately follows * from the recursive block structure of the vectors representing * the domain and range of the mapping, respectively: * - FieldMatrix represents a linear map \f$M: V_1 \to V_2\f$ where * \f$V_1=K^n\f$ and \f$V_2=K^m\f$ are vector spaces over the same field represented by a numerix type. * - BCRSMatrix represents a linear map \f$M: V_1 \to V_2\f$ where * \f$V_1=W\times W \times W \times\cdots\times W\f$ and \f$V_2=W\times W \times W \times\cdots\times W\f$ * where W is itself a vector space. * - VariableBCRSMatrix is not yet implemented. */ /** @addtogroup ISTL_SPMV @{ */ template struct MatrixDimension; //! Statistics about compression achieved in implicit mode. /** * To enable the user to tune parameters of the implicit build mode of a * Dune::BCRSMatrix manually, some statistics are exported upon during * the compression step. * */ template struct CompressionStatistics { //! average number of non-zeroes per row. double avg; //! maximum number of non-zeroes per row. size_type maximum; //! total number of elements written to the overflow area during construction. size_type overflow_total; //! fraction of wasted memory resulting from non-used overflow area. /** * mem_ratio is equal to `nonzeros()/(# allocated matrix entries)`. */ double mem_ratio; }; //! A wrapper for uniform access to the BCRSMatrix during and after the build stage in implicit build mode. /** * The implicit build mode of Dune::BCRSMatrix handles matrices differently during * assembly and afterwards. Using this class, one can wrap a BCRSMatrix to allow * use with code that is not written for the new build mode specifically. The wrapper * forwards any calls to operator[][] to the entry() method.The assembly code * does not even necessarily need to know that the underlying matrix is sparse. * Dune::AMG uses this to reassemble an existing matrix without code duplication. * The compress() method of Dune::BCRSMatrix still has to be called from outside * this wrapper after the pattern assembly is finished. * * \tparam M_ the matrix type */ template class ImplicitMatrixBuilder { public: //! The underlying matrix. typedef M_ Matrix; //! The block_type of the underlying matrix. typedef typename Matrix::block_type block_type; //! The size_type of the underlying matrix. typedef typename Matrix::size_type size_type; //! Proxy row object for entry access. /** * During matrix construction, there are no fully functional rows available * yet, so we instead hand out a simple proxy which only allows accessing * individual entries using operator[]. */ class row_object { public: //! Returns entry in column j. block_type& operator[](size_type j) const { return _m.entry(_i,j); } #ifndef DOXYGEN row_object(Matrix& m, size_type i) : _m(m) , _i(i) {} #endif private: Matrix& _m; size_type _i; }; //! Creates an ImplicitMatrixBuilder for matrix m. /** * \note You can only pass a completely set up matrix to this constructor: * All of setBuildMode(), setImplicitBuildModeParameters() and setSize() * must have been called with the correct values. * */ ImplicitMatrixBuilder(Matrix& m) : _m(m) { if (m.buildMode() != Matrix::implicit) DUNE_THROW(BCRSMatrixError,"You can only create an ImplicitBuilder for a matrix in implicit build mode"); if (m.buildStage() != Matrix::building) DUNE_THROW(BCRSMatrixError,"You can only create an ImplicitBuilder for a matrix with set size that has not been compressed() yet"); } //! Sets up matrix m for implicit construction using the given parameters and creates an ImplicitBmatrixuilder for it. /** * Using this constructor, you can perform the necessary matrix setup and the creation * of the ImplicitMatrixBuilder in a single step. The matrix must still be in the build stage * notAllocated, otherwise a BCRSMatrixError will be thrown. For a detailed explanation * of the matrix parameters, see BCRSMatrix. * * \param m the matrix to be built * \param rows the number of matrix rows * \param cols the number of matrix columns * \param avg_cols_per_row the average number of non-zero columns per row * \param overflow_fraction the amount of overflow to reserve in the matrix * * \sa BCRSMatrix */ ImplicitMatrixBuilder(Matrix& m, size_type rows, size_type cols, size_type avg_cols_per_row, double overflow_fraction) : _m(m) { if (m.buildStage() != Matrix::notAllocated) DUNE_THROW(BCRSMatrixError,"You can only set up a matrix for this ImplicitBuilder if it has no memory allocated yet"); m.setBuildMode(Matrix::implicit); m.setImplicitBuildModeParameters(avg_cols_per_row,overflow_fraction); m.setSize(rows,cols); } //! Returns a proxy for entries in row i. row_object operator[](size_type i) const { return row_object(_m,i); } //! The number of rows in the matrix. size_type N() const { return _m.N(); } //! The number of columns in the matrix. size_type M() const { return _m.M(); } private: Matrix& _m; }; /** \brief A sparse block matrix with compressed row storage Implements a block compressed row storage scheme. The block type B can be any type implementing the matrix interface. Different ways to build up a compressed row storage matrix are supported: 1. Row-wise scheme 2. Random scheme 3. implicit scheme Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. Details: 1. Row-wise scheme Rows are built up in sequential order. Size of the row and the column indices are defined. A row can be used as soon as it is initialized. With respect to memory there are two variants of this scheme: (a) number of non-zeroes known in advance (application finite difference schemes), (b) number of non-zeroes not known in advance (application: Sparse LU, ILU(n)). \code #include #include ... typedef FieldMatrix M; // third parameter is an optional upper bound for the number // of nonzeros. If given the matrix will use one array for all values // as opposed to one for each row. BCRSMatrix B(4,4,12,BCRSMatrix::row_wise); typedef BCRSMatrix::CreateIterator Iter; for(Iter row=B.createbegin(); row!=B.createend(); ++row){ // Add nonzeros for left neighbour, diagonal and right neighbour if(row.index()>0) row.insert(row.index()-1); row.insert(row.index()); if(row.index() #include ... typedef FieldMatrix M; BCRSMatrix B(4,4,BCRSMatrix::random); // initially set row size for each row B.setrowsize(0,1); B.setrowsize(3,4); B.setrowsize(2,1); B.setrowsize(1,1); // increase row size for row 2 B.incrementrowsize(2); // finalize row setup phase B.endrowsizes(); // add column entries to rows B.addindex(0,0); B.addindex(3,1); B.addindex(2,2); B.addindex(1,1); B.addindex(2,0); B.addindex(3,2); B.addindex(3,0); B.addindex(3,3); // finalize column setup phase B.endindices(); // set entries using the random access operator B[0][0] = 1; B[1][1] = 2; B[2][0] = 3; B[2][2] = 4; B[3][1] = 5; B[3][2] = 6; B[3][0] = 7; B[3][3] = 8; \endcode 3. implicit scheme With the above Random Scheme, the sparsity pattern has to be determined and stored before the matrix is assembled. This leads to increased memory usage and computation time. Often, one has good a priori knowledge about the number of entries a row contains on average. `implicit` mode tries to make use of that knowledge by allocating memory based on that average. If a row contains more non-zeroes than the average value these are stored in an auxiliary buffer during the initial assembly phase. After all indices are added a compression step optimizes the matrix and integrates any entries from the buffer into the standard BCRS storage making use of an optional overflow area to allow rows exceeding the average non-zero count. More precisely, if \f$\textrm{nnz}_j\f$ denotes the number of non-zeros in the \f$j\f$-th row, then the maximal number of allowed non-zeros in the \f$i\f$-th row is \f[ M_i = \textrm{avg} + A + \sum_{j #include typedef Dune::BCRSMatrix > M; M m(10, 10, 2, 0.4, M::implicit); //fill in some arbitrary entries, even operations on these would be possible, //you get a reference to the entry! the order of these statements is irrelevant! m.entry(0,0) = 0.; m.entry(8,0) = 0.; m.entry(1,8) = 0.; m.entry(1,0) = 0.; m.entry(1,5) = 0.; m.entry(2,0) = 0.; m.entry(3,5) = 0.; m.entry(3,0) = 0.; m.entry(3,8) = 0.; m.entry(4,0) = 0.; m.entry(9,0) = 0.; m.entry(9,5) = 0.; m.entry(9,8) = 0.; m.entry(5,0) = 0.; m.entry(5,5) = 0.; m.entry(5,8) = 0.; m.entry(6,0) = 0.; m.entry(7,0) = 0.; m.entry(7,5) = 0.; m.entry(7,8) = 0.; // internally the index array now looks like this (second row are the row pointers): // xxxxxxxx0x800x500x050x050x05 // ........|.|.|.|.|.|.|.|.|.|. // and the overflow area contains (1,5,0.0), (3,8,0.0), (5,8,0.0), (7,8,0.0), (9,8,0.0) // the data array has similar structure. //finish building by compressing the array Dune::CompressionStatistics stats = m.compress(); // internally the index array now looks like this: // 00580058005800580058xxxxxxxx // ||..||..||..||..||.......... \endcode */ template > class BCRSMatrix { friend struct MatrixDimension; public: enum BuildStage { /** @brief Matrix is not built at all, no memory has been allocated, build mode and size can still be set. */ notbuilt=0, /** @brief Matrix is not built at all, no memory has been allocated, build mode and size can still be set. */ notAllocated=0, /** @brief Matrix is currently being built, some memory has been allocated, build mode and size are fixed. */ building=1, /** @brief The row sizes of the matrix are known. * * Only used in random mode. */ rowSizesBuilt=2, /** @brief The matrix structure is fully built. */ built=3 }; //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! implement row_type with compressed vector typedef CompressedBlockVectorWindow row_type; //! The type for the index access and the size typedef typename A::size_type size_type; //! The type for the statistics object returned by compress() typedef ::Dune::CompressionStatistics CompressionStatistics; //! increment block level counter enum { //! The number of blocklevels the matrix contains. blocklevel = B::blocklevel+1 }; //! we support two modes enum BuildMode { /** * @brief Build in a row-wise manner. * * Rows are built up in sequential order. Size of the row and * the column indices are defined. A row can be used as soon as it * is initialized. With respect to memory there are two variants of * this scheme: (a) number of non-zeroes known in advance (application * finite difference schemes), (b) number of non-zeroes not known * in advance (application: Sparse LU, ILU(n)). */ row_wise, /** * @brief Build entries randomly. * * For general finite element implementations the number of rows n * is known, the number of non-zeroes might also be known (e.g. * \#edges + \#nodes for P2) but the size of a row and the indices of a row * cannot be defined in sequential order. */ random, /** * @brief Build entries randomly with an educated guess for the number of entries per row. * * Allows random order generation as in random mode, but row sizes do not need * to be given first. Instead an average number of non-zeroes per row is passed * to the constructor. Matrix setup is finished with compress(), full data access * during build stage is possible. */ implicit, /** * @brief Build mode not set! */ unknown }; //===== random access interface to rows of the matrix //! random access to the rows row_type& operator[] (size_type i) { #ifdef DUNE_ISTL_WITH_CHECKING if (build_mode == implicit && ready != built) DUNE_THROW(BCRSMatrixError,"You cannot use operator[] in implicit build mode before calling compress()"); if (r==0) DUNE_THROW(BCRSMatrixError,"row not initialized yet"); if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif return r[i]; } //! same for read only access const row_type& operator[] (size_type i) const { #ifdef DUNE_ISTL_WITH_CHECKING if (build_mode == implicit && ready != built) DUNE_THROW(BCRSMatrixError,"You cannot use operator[] in implicit build mode before calling compress()"); if (built!=ready) DUNE_THROW(BCRSMatrixError,"row not initialized yet"); if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif return r[i]; } //===== iterator interface to rows of the matrix //! %Iterator access to matrix rows template class RealRowIterator : public RandomAccessIteratorFacade, T> { public: //! \brief The unqualified value type typedef typename std::remove_const::type ValueType; friend class RandomAccessIteratorFacade, const ValueType>; friend class RandomAccessIteratorFacade, ValueType>; friend class RealRowIterator; friend class RealRowIterator; //! constructor RealRowIterator (row_type* _p, size_type _i) : p(_p), i(_i) {} //! empty constructor, use with care! RealRowIterator () : p(0), i(0) {} RealRowIterator(const RealRowIterator& it) : p(it.p), i(it.i) {} //! return index size_type index () const { return i; } std::ptrdiff_t distanceTo(const RealRowIterator& other) const { assert(other.p==p); return (other.i-i); } std::ptrdiff_t distanceTo(const RealRowIterator& other) const { assert(other.p==p); return (other.i-i); } //! equality bool equals (const RealRowIterator& other) const { assert(other.p==p); return i==other.i; } //! equality bool equals (const RealRowIterator& other) const { assert(other.p==p); return i==other.i; } private: //! prefix increment void increment() { ++i; } //! prefix decrement void decrement() { --i; } void advance(std::ptrdiff_t diff) { i+=diff; } T& elementAt(std::ptrdiff_t diff) const { return p[i+diff]; } //! dereferencing row_type& dereference () const { return p[i]; } row_type* p; size_type i; }; //! The iterator over the (mutable matrix rows typedef RealRowIterator iterator; typedef RealRowIterator Iterator; //! Get iterator to first row Iterator begin () { return Iterator(r,0); } //! Get iterator to one beyond last row Iterator end () { return Iterator(r,n); } //! @returns an iterator that is positioned before //! the end iterator of the rows, i.e. at the last row. Iterator beforeEnd () { return Iterator(r,n-1); } //! @returns an iterator that is positioned before //! the first row of the matrix. Iterator beforeBegin () { return Iterator(r,-1); } //! rename the iterators for easier access typedef Iterator RowIterator; /** \brief Iterator for the entries of each row */ typedef typename row_type::Iterator ColIterator; //! The const iterator over the matrix rows typedef RealRowIterator const_iterator; typedef RealRowIterator ConstIterator; //! Get const iterator to first row ConstIterator begin () const { return ConstIterator(r,0); } //! Get const iterator to one beyond last row ConstIterator end () const { return ConstIterator(r,n); } //! @returns an iterator that is positioned before //! the end iterator of the rows. i.e. at the last row. ConstIterator beforeEnd() const { return ConstIterator(r,n-1); } //! @returns an iterator that is positioned before //! the first row of the matrix. ConstIterator beforeBegin () const { return ConstIterator(r,-1); } //! rename the const row iterator for easier access typedef ConstIterator ConstRowIterator; //! Const iterator to the entries of a row typedef typename row_type::ConstIterator ConstColIterator; //===== constructors & resizers // we use a negative overflowsize to indicate that the implicit // mode parameters have not been set yet //! an empty matrix BCRSMatrix () : build_mode(unknown), ready(notAllocated), n(0), m(0), nnz_(0), allocationSize_(0), r(0), a(0), avg(0), overflowsize(-1.0) {} //! matrix with known number of nonzeroes BCRSMatrix (size_type _n, size_type _m, size_type _nnz, BuildMode bm) : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0), allocationSize_(0), r(0), a(0), avg(0), overflowsize(-1.0) { allocate(_n, _m, _nnz,true,false); } //! matrix with unknown number of nonzeroes BCRSMatrix (size_type _n, size_type _m, BuildMode bm) : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0), allocationSize_(0), r(0), a(0), avg(0), overflowsize(-1.0) { allocate(_n, _m,0,true,false); } //! \brief construct matrix with a known average number of entries per row /** * Constructs a matrix in implicit buildmode. * * @param _n number of rows of the matrix * @param _m number of columns of the matrix * @param _avg expected average number of entries per row * @param _overflowsize fraction of _n*_avg which is expected to be * needed for elements that exceed _avg entries per row. * */ BCRSMatrix (size_type _n, size_type _m, size_type _avg, double _overflowsize, BuildMode bm) : build_mode(bm), ready(notAllocated), n(0), m(0), nnz_(0), allocationSize_(0), r(0), a(0), avg(_avg), overflowsize(_overflowsize) { if (bm != implicit) DUNE_THROW(BCRSMatrixError,"Only call this constructor when using the implicit build mode"); // Prevent user from setting a negative overflowsize: // 1) It doesn't make sense // 2) We use a negative overflow value to indicate that the parameters // have not been set yet if (_overflowsize < 0.0) DUNE_THROW(BCRSMatrixError,"You cannot set a negative overflow fraction"); implicit_allocate(_n,_m); } /** * @brief copy constructor * * Does a deep copy as expected. */ BCRSMatrix (const BCRSMatrix& Mat) : build_mode(Mat.build_mode), ready(notAllocated), n(0), m(0), nnz_(0), allocationSize_(0), r(0), a(0), avg(Mat.avg), overflowsize(Mat.overflowsize) { if (!(Mat.ready == notAllocated || Mat.ready == built)) DUNE_THROW(InvalidStateException,"BCRSMatrix can only be copy-constructed when source matrix is completely empty (size not set) or fully built)"); // deep copy in global array size_type _nnz = Mat.nnz_; // in case of row-wise allocation if (_nnz<=0) { _nnz = 0; for (size_type i=0; i0) DUNE_THROW(Dune::BCRSMatrixError,"number of non-zeroes may not be set in implicit mode, use setImplicitBuildModeParameters() instead"); // implicit allocates differently implicit_allocate(rows,columns); } else { // allocate matrix memory allocate(rows, columns, nnz, true, false); } } /** @brief Set parameters needed for creation in implicit build mode. * * Use this method before setSize() to define storage behaviour of a matrix * in implicit build mode * @param _avg expected average number of entries per row * @param _overflowsize fraction of _n*_avg which is expected to be * needed for elements that exceed _avg entries per row. */ void setImplicitBuildModeParameters(size_type _avg, double _overflow) { // Prevent user from setting a negative overflowsize: // 1) It doesn't make sense // 2) We use a negative overflow value to indicate that the parameters // have not been set yet if (_overflow < 0.0) DUNE_THROW(BCRSMatrixError,"You cannot set a negative overflow fraction"); // make sure the parameters aren't changed after memory has been allocated if (ready != notAllocated) DUNE_THROW(InvalidStateException,"You cannot modify build mode parameters at this stage anymore"); avg = _avg; overflowsize = _overflow; } /** * @brief assignment * * Frees and reallocates space. * Both sparsity pattern and values are set from Mat. */ BCRSMatrix& operator= (const BCRSMatrix& Mat) { // return immediately when self-assignment if (&Mat==this) return *this; if (!((ready == notAllocated || ready == built) && (Mat.ready == notAllocated || Mat.ready == built))) DUNE_THROW(InvalidStateException,"BCRSMatrix can only be copied when both target and source are empty or fully built)"); // make it simple: ALWAYS throw away memory for a and j_ // and deallocate rows only if n != Mat.n deallocate(n!=Mat.n); // reallocate the rows if required if (n>0 && n!=Mat.n) { // free rows for(row_type *riter=r+(n-1), *rend=r-1; riter!=rend; --riter) rowAllocator_.destroy(riter); rowAllocator_.deallocate(r,n); } nnz_ = Mat.nnz_; if (nnz_ <= 0) { for (size_type i=0; i0) { // update number of nonzeroes including this row nnz += s; // alloc memory / set window if (Mat.nnz_ > 0) { // memory is allocated in one long array // check if that memory is sufficient if (nnz > Mat.nnz_) DUNE_THROW(BCRSMatrixError,"allocated nnz too small"); // set row i Mat.r[i].set(s,nullptr,current_row.getindexptr()); current_row.setindexptr(current_row.getindexptr()+s); }else{ // memory is allocated individually per row // allocate and set row i B* b = Mat.allocator_.allocate(s); // use placement new to call constructor that allocates // additional memory. new (b) B[s]; size_type* j = Mat.sizeAllocator_.allocate(s); Mat.r[i].set(s,b,j); } }else // setup empty row Mat.r[i].set(0,nullptr,nullptr); // initialize the j array for row i from pattern std::copy(pattern.cbegin(), pattern.cend(), Mat.r[i].getindexptr()); // now go to next row i++; pattern.clear(); // check if this was last row if (i==Mat.n) { Mat.ready = built; if(Mat.nnz_ > 0) { // Set nnz to the exact number of nonzero blocks inserted // as some methods rely on it Mat.nnz_ = nnz; // allocate data array Mat.allocateData(); Mat.setDataPointers(); } } // done return *this; } //! inequality bool operator!= (const CreateIterator& it) const { return (i!=it.i) || (&Mat!=&it.Mat); } //! equality bool operator== (const CreateIterator& it) const { return (i==it.i) && (&Mat==&it.Mat); } //! The number of the row that the iterator currently points to size_type index () const { return i; } //! put column index in row void insert (size_type j) { pattern.insert(j); } //! return true if column index is in row bool contains (size_type j) { return pattern.find(j) != pattern.end(); } /** * @brief Get the current row size. * @return The number of indices already * inserted for the current row. */ size_type size() const { return pattern.size(); } private: BCRSMatrix& Mat; // the matrix we are defining size_type i; // current row to be defined size_type nnz; // count total number of nonzeros typedef std::set > PatternType; PatternType pattern; // used to compile entries in a row row_type current_row; // row pointing to the current row to setup }; //! allow CreateIterator to access internal data friend class CreateIterator; //! get initial create iterator CreateIterator createbegin () { return CreateIterator(*this,0); } //! get create iterator pointing to one after the last block CreateIterator createend () { return CreateIterator(*this,n); } //===== random creation interface /** \brief Set number of indices in row i to s * * The number s may actually be larger than the true number of nonzero entries in row i. In that * case, the extra memory goes wasted. You will receive run-time warnings about this, sent to * the Dune::dwarn stream. */ void setrowsize (size_type i, size_type s) { if (build_mode!=random) DUNE_THROW(BCRSMatrixError,"requires random build mode"); if (ready != building) DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up"); r[i].setsize(s); } //! get current number of indices in row i size_type getrowsize (size_type i) const { #ifdef DUNE_ISTL_WITH_CHECKING if (r==0) DUNE_THROW(BCRSMatrixError,"row not initialized yet"); if (i>=n) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif return r[i].getsize(); } //! increment size of row i by s (1 by default) void incrementrowsize (size_type i, size_type s = 1) { if (build_mode!=random) DUNE_THROW(BCRSMatrixError,"requires random build mode"); if (ready != building) DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up"); r[i].setsize(r[i].getsize()+s); } //! indicate that size of all rows is defined void endrowsizes () { if (build_mode!=random) DUNE_THROW(BCRSMatrixError,"requires random build mode"); if (ready != building) DUNE_THROW(BCRSMatrixError,"matrix row sizes already built up"); // compute total size, check positivity size_type total=0; for (size_type i=0; i= m) DUNE_THROW(BCRSMatrixError,"column index exceeds matrix size"); // get row range size_type* const first = r[row].getindexptr(); size_type* const last = first + r[row].getsize(); // find correct insertion position for new column index size_type* pos = std::lower_bound(first,last,col); // check if index is already in row if (pos!=last && *pos == col) return; // find end of already inserted column indices size_type* end = std::lower_bound(pos,last,m); if (end==last) DUNE_THROW(BCRSMatrixError,"row is too small"); // insert new column index at correct position std::copy_backward(pos,end,end+1); *pos = col; } //! Set all column indices for row from the given iterator range. /** * The iterator range has to be of the same length as the previously set row size. * The entries in the iterator range do not have to be in any particular order, but * must not contain duplicate values. * * Calling this method overwrites any previously set column indices! */ template void setIndices(size_type row, It begin, It end) { size_type row_size = r[row].size(); size_type* col_begin = r[row].getindexptr(); size_type* col_end; // consistency check between allocated row size and number of passed column indices if ((col_end = std::copy(begin,end,r[row].getindexptr())) != col_begin + row_size) DUNE_THROW(BCRSMatrixError,"Given size of row " << row << " (" << row_size << ") does not match number of passed entries (" << (col_end - col_begin) << ")"); std::sort(col_begin,col_end); } //! indicate that all indices are defined, check consistency void endindices () { if (build_mode!=random) DUNE_THROW(BCRSMatrixError,"requires random build mode"); if (ready==built) DUNE_THROW(BCRSMatrixError,"matrix already built up"); if (ready==building) DUNE_THROW(BCRSMatrixError,"row sizes are not built up yet"); if (ready==notAllocated) DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet"); // check if there are undefined indices RowIterator endi=end(); for (RowIterator i=begin(); i!=endi; ++i) { ColIterator endj = (*i).end(); for (ColIterator j=(*i).begin(); j!=endj; ++j) { if (j.index() >= m) { dwarn << "WARNING: size of row "<< i.index()<<" is "<= n) DUNE_THROW(BCRSMatrixError,"row index exceeds matrix size"); if (col >= m) DUNE_THROW(BCRSMatrixError,"column index exceeds matrix size"); #endif size_type* begin = r[row].getindexptr(); size_type* end = begin + r[row].getsize(); size_type* pos = std::find(begin, end, col); //treat the case that there was a match in the array if (pos != end) if (*pos == col) { std::ptrdiff_t offset = pos - r[row].getindexptr(); B* aptr = r[row].getptr() + offset; return *aptr; } //determine whether overflow has to be taken into account or not if (r[row].getsize() == avg) return overflow[std::make_pair(row,col)]; else { //modify index array *end = col; //do simulatenous operations on data array a std::ptrdiff_t offset = end - r[row].getindexptr(); B* apos = r[row].getptr() + offset; //increase rowsize r[row].setsize(r[row].getsize()+1); //return reference to the newly created entry return *apos; } } //! Finishes the buildstage in implicit mode. /** * Performs compression of index and data arrays with linear * complexity in the number of nonzeroes. * * After calling this method, the matrix is in the built state * and no more entries can be added. * * \returns An object with some statistics about the compression for * future optimization. */ CompressionStatistics compress() { if (build_mode!=implicit) DUNE_THROW(BCRSMatrixError,"requires implicit build mode"); if (ready==built) DUNE_THROW(BCRSMatrixError,"matrix already built up, no more need for compression"); if (ready==notAllocated) DUNE_THROW(BCRSMatrixError,"matrix size not set and no memory allocated yet"); if (ready!=building) DUNE_THROW(InvalidStateException,"You may only call compress() at the end of the 'building' stage"); //calculate statistics CompressionStatistics stats; stats.overflow_total = overflow.size(); stats.maximum = 0; //get insertion iterators pointing to one before start (for later use of ++it) size_type* jiit = j_.get(); B* aiit = a; //get iterator to the smallest overflow element typename OverflowType::iterator oit = overflow.begin(); //store a copy of index pointers on which to perform sortation std::vector perm; //iterate over all rows and copy elements into their position in the compressed array for (size_type i=0; i::iterator it = perm.begin(); for (size_type* iit = begin; iit < begin + size; ++iit, ++it) *it = iit; //sort permutation array std::sort(perm.begin(),perm.end(),PointerCompare()); //change row window pointer to their new positions r[i].setindexptr(jiit); r[i].setptr(aiit); for (it = perm.begin(); it != perm.end(); ++it) { //check whether there are elements in the overflow area which take precedence while ((oit!=overflow.end()) && (oit->first < std::make_pair(i,**it))) { //check whether there is enough memory to write to if (jiit > begin) DUNE_THROW(Dune::ImplicitModeOverflowExhausted, "Allocated memory for BCRSMatrix exhausted during compress()!" "Please increase either the average number of entries per row or the overflow fraction." ); //copy an element from the overflow area to the insertion position in a and j *jiit = oit->first.second; ++jiit; *aiit = oit->second; ++aiit; ++oit; r[i].setsize(r[i].getsize()+1); } //check whether there is enough memory to write to if (jiit > begin) DUNE_THROW(Dune::ImplicitModeOverflowExhausted, "Allocated memory for BCRSMatrix exhausted during compress()!" "Please increase either the average number of entries per row or the overflow fraction." ); //copy element from array *jiit = **it; ++jiit; B* apos = *it - j_.get() + a; *aiit = *apos; ++aiit; } //copy remaining elements from the overflow area while ((oit!=overflow.end()) && (oit->first.first == i)) { //check whether there is enough memory to write to if (jiit > begin) DUNE_THROW(Dune::ImplicitModeOverflowExhausted, "Allocated memory for BCRSMatrix exhausted during compress()!" "Please increase either the average number of entries per row or the overflow fraction." ); //copy and element from the overflow area to the insertion position in a and j *jiit = oit->first.second; ++jiit; *aiit = oit->second; ++aiit; ++oit; r[i].setsize(r[i].getsize()+1); } // update maximum row size if (r[i].getsize()>stats.maximum) stats.maximum = r[i].getsize(); } // overflow area may be cleared overflow.clear(); //determine average number of entries and memory usage std::ptrdiff_t diff = (r[n-1].getindexptr() + r[n-1].getsize() - j_.get()); nnz_ = diff; stats.avg = (double) (nnz_) / (double) n; stats.mem_ratio = (double) (nnz_) / (double) allocationSize_; //matrix is now built ready = built; return stats; } //===== vector space arithmetic //! vector space multiplication with scalar BCRSMatrix& operator*= (const field_type& k) { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); #endif if (nnz_ > 0) { // process 1D array for (size_type i=0; i 0) { // process 1D array for (size_type i=0; ioperator+=(*j); } return *this; } /*! \brief Subtract the entries of another matrix from this one. * * \param b The matrix to subtract from this one. Its sparsity pattern * has to be subset of the sparsity pattern of this matrix. */ BCRSMatrix& operator-= (const BCRSMatrix& b) { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built || b.ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if(N()!=b.N() || M() != b.M()) DUNE_THROW(RangeError, "Matrix sizes do not match!"); #endif RowIterator endi=end(); ConstRowIterator j=b.begin(); for (RowIterator i=begin(); i!=endi; ++i, ++j) { i->operator-=(*j); } return *this; } /*! \brief Add the scaled entries of another matrix to this one. * * Matrix axpy operation: *this += alpha * b * * \param alpha Scaling factor. * \param b The matrix to add to this one. Its sparsity pattern has to * be subset of the sparsity pattern of this matrix. */ BCRSMatrix& axpy(field_type alpha, const BCRSMatrix& b) { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built || b.ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if(N()!=b.N() || M() != b.M()) DUNE_THROW(RangeError, "Matrix sizes do not match!"); #endif RowIterator endi=end(); ConstRowIterator j=b.begin(); for(RowIterator i=begin(); i!=endi; ++i, ++j) i->axpy(alpha, *j); return *this; } //===== linear maps //! y = A x template void mv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=M()) DUNE_THROW(BCRSMatrixError, "Size mismatch: M: " << N() << "x" << M() << " x: " << x.N()); if (y.N()!=N()) DUNE_THROW(BCRSMatrixError, "Size mismatch: M: " << N() << "x" << M() << " y: " << y.N()); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { y[i.index()]=0; ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umv(x[j.index()],y[i.index()]); } } //! y += A x template void umv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umv(x[j.index()],y[i.index()]); } } //! y -= A x template void mmv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmv(x[j.index()],y[i.index()]); } } //! y += alpha A x template void usmv (F&& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).usmv(alpha,x[j.index()],y[i.index()]); } } //! y = A^T x template void mtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif for(size_type i=0; i void umtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umtv(x[i.index()],y[j.index()]); } } //! y -= A^T x template void mmtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmtv(x[i.index()],y[j.index()]); } } //! y += alpha A^T x template void usmtv (const field_type& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).usmtv(alpha,x[i.index()],y[j.index()]); } } //! y += A^H x template void umhv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umhv(x[i.index()],y[j.index()]); } } //! y -= A^H x template void mmhv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmhv(x[i.index()],y[j.index()]); } } //! y += alpha A^H x template void usmhv (const field_type& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); if (x.N()!=N()) DUNE_THROW(BCRSMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(BCRSMatrixError,"index out of range"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).usmhv(alpha,x[i.index()],y[j.index()]); } } //===== norms //! square of frobenius norm, need for block recursion typename FieldTraits::real_type frobenius_norm2 () const { #ifdef DUNE_ISTL_WITH_CHECKING if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); #endif double sum=0; ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) sum += (*j).frobenius_norm2(); } return sum; } //! frobenius norm: sqrt(sum over squared values of entries) typename FieldTraits::real_type frobenius_norm () const { return sqrt(frobenius_norm2()); } //! infinity norm (row sum norm, how to generalize for blocks?) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm(); norm = max(sum, norm); } return norm; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm_real(); norm = max(sum, norm); } return norm; } //! infinity norm (row sum norm, how to generalize for blocks?) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm(); norm = max(sum, norm); isNaN += sum; } isNaN /= isNaN; return norm * isNaN; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { if (ready != built) DUNE_THROW(BCRSMatrixError,"You can only call arithmetic operations on fully built BCRSMatrix instances"); using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm_real(); norm = max(sum, norm); isNaN += sum; } isNaN /= isNaN; return norm * isNaN; } //===== sizes //! number of rows (counted in blocks) size_type N () const { return n; } //! number of columns (counted in blocks) size_type M () const { return m; } //! number of blocks that are stored (the number of blocks that possibly are nonzero) size_type nonzeroes () const { return nnz_; } //! The current build stage of the matrix. BuildStage buildStage() const { return ready; } //! The currently selected build mode of the matrix. BuildMode buildMode() const { return build_mode; } //===== query //! return true if (i,j) is in pattern bool exists (size_type i, size_type j) const { #ifdef DUNE_ISTL_WITH_CHECKING if (i<0 || i>=n) DUNE_THROW(BCRSMatrixError,"row index out of range"); if (j<0 || j>=m) DUNE_THROW(BCRSMatrixError,"column index out of range"); #endif return (r[i].size() && r[i].find(j) != r[i].end()); } protected: // state information BuildMode build_mode; // row wise or whole matrix BuildStage ready; // indicate the stage the matrix building is in // The allocator used for memory management typename A::template rebind::other allocator_; typename A::template rebind::other rowAllocator_; typename A::template rebind::other sizeAllocator_; // size of the matrix size_type n; // number of rows size_type m; // number of columns size_type nnz_; // number of nonzeroes contained in the matrix size_type allocationSize_; //allocated size of a and j arrays, except in implicit mode: nnz_==allocationsSize_ // zero means that memory is allocated separately for each row. // the rows are dynamically allocated row_type* r; // [n] the individual rows having pointers into a,j arrays // dynamically allocated memory B* a; // [allocationSize] non-zero entries of the matrix in row-wise ordering // If a single array of column indices is used, it can be shared // between different matrices with the same sparsity pattern std::shared_ptr j_; // [allocationSize] column indices of entries // additional data is needed in implicit buildmode size_type avg; double overflowsize; typedef std::map, B> OverflowType; OverflowType overflow; void setWindowPointers(ConstRowIterator row) { row_type current_row(a,j_.get(),0); // Pointers to current row data for (size_type i=0; igetsize(); if (s>0) { // setup pointers and size r[i].set(s,current_row.getptr(), current_row.getindexptr()); // update pointer for next row current_row.setptr(current_row.getptr()+s); current_row.setindexptr(current_row.getindexptr()+s); } else{ // empty row r[i].set(0,nullptr,nullptr); } } } //! Copy row sizes from iterator range starting at row and set column index pointers for all rows. /** * This method does not modify the data pointers, as those are set only * after building the pattern (to allow for a delayed allocation). */ void setColumnPointers(ConstRowIterator row) { size_type* jptr = j_.get(); for (size_type i=0; igetsize(); if (s>0) { // setup pointers and size r[i].setsize(s); r[i].setindexptr(jptr); } else{ // empty row r[i].set(0,nullptr,nullptr); } // advance position in global array jptr += s; } } //! Set data pointers for all rows. /** * This method assumes that column pointers and row sizes have been correctly set up * by a prior call to setColumnPointers(). */ void setDataPointers() { B* aptr = a; for (size_type i=0; i 0) { // setup pointers and size r[i].setptr(aptr); } else{ // empty row r[i].set(0,nullptr,nullptr); } // advance position in global array aptr += r[i].getsize(); } } //! \brief Copy the window structure from another matrix void copyWindowStructure(const BCRSMatrix& Mat) { setWindowPointers(Mat.begin()); // copy data for (size_type i=0; i0) { // a,j_ have been allocated as one long vector j_.reset(); if (a) { for(B *aiter=a+(allocationSize_-1), *aend=a-1; aiter!=aend; --aiter) allocator_.destroy(aiter); allocator_.deallocate(a,allocationSize_); a = nullptr; } } else if (r) { // check if memory for rows have been allocated individually for (size_type i=0; i0) { for (B *col=r[i].getptr()+(r[i].getsize()-1), *colend = r[i].getptr()-1; col!=colend; --col) { allocator_.destroy(col); } sizeAllocator_.deallocate(r[i].getindexptr(),1); allocator_.deallocate(r[i].getptr(),1); // clear out row data in case we don't want to deallocate the rows // otherwise we might run into a double free problem here later r[i].set(0,nullptr,nullptr); } } // deallocate the rows if (n>0 && deallocateRows && r) { for(row_type *riter=r+(n-1), *rend=r-1; riter!=rend; --riter) rowAllocator_.destroy(riter); rowAllocator_.deallocate(r,n); r = nullptr; } // Mark matrix as not built at all. ready=notAllocated; } /** \brief Class used by shared_ptr to deallocate memory using the proper allocator */ class Deallocator { typename A::template rebind::other& sizeAllocator_; public: Deallocator(typename A::template rebind::other& sizeAllocator) : sizeAllocator_(sizeAllocator) {} void operator()(size_type* p) { sizeAllocator_.deallocate(p,1); } }; /** * @brief Allocate memory for the matrix structure * * Sets the number of rows and columns of the matrix and allocates * the memory needed for the storage of the matrix entries. * * @warning After calling this methods on an already allocated (and probably * setup matrix) results in all the structure and data being lost. Please * call deallocate() before calling allocate in this case. * * @param row The number of rows the matrix should contain. * @param columns the number of columns the matrix should contain. * @param allocationSize The number of nonzero entries the matrix should hold (if omitted * defaults to 0). * @param allocateRow Whether we have to allocate the row pointers, too. (Defaults to * true) */ void allocate(size_type rows, size_type columns, size_type allocationSize, bool allocateRows, bool allocate_data) { // Store size n = rows; m = columns; nnz_ = allocationSize; allocationSize_ = allocationSize; // allocate rows if(allocateRows) { if (n>0) { if (r) DUNE_THROW(InvalidStateException,"Rows have already been allocated, cannot allocate a second time"); r = rowAllocator_.allocate(rows); }else{ r = 0; } } // allocate a and j_ array if (allocate_data) allocateData(); if (allocationSize_>0) { // allocate column indices only if not yet present (enable sharing) if (!j_.get()) j_.reset(sizeAllocator_.allocate(allocationSize_),Deallocator(sizeAllocator_)); }else{ j_.reset(); for(row_type* ri=r; ri!=r+rows; ++ri) rowAllocator_.construct(ri, row_type()); } // Mark the matrix as not built. ready = building; } void allocateData() { if (a) DUNE_THROW(InvalidStateException,"Cannot allocate data array (already allocated)"); if (allocationSize_>0) { a = allocator_.allocate(allocationSize_); // use placement new to call constructor that allocates // additional memory. new (a) B[allocationSize_]; } else { a = nullptr; } } /** @brief organizes allocation implicit mode * calculates correct array size to be allocated and sets the * the window pointers to their correct positions for insertion. * internally uses allocate() for the real allocation. */ void implicit_allocate(size_type _n, size_type _m) { if (build_mode != implicit) DUNE_THROW(InvalidStateException,"implicit_allocate() may only be called in implicit build mode"); if (ready != notAllocated) DUNE_THROW(InvalidStateException,"memory has already been allocated"); // check to make sure the user has actually set the parameters if (overflowsize < 0) DUNE_THROW(InvalidStateException,"You have to set the implicit build mode parameters before starting to build the matrix"); //calculate size of overflow region, add buffer for row sort! size_type osize = (size_type) (_n*avg)*overflowsize + 4*avg; allocationSize_ = _n*avg + osize; allocate(_n, _m, allocationSize_,true,true); //set row pointers correctly size_type* jptr = j_.get() + osize; B* aptr = a + osize; for (size_type i=0; i #include /** \file \author Oliver Sander \brief Implementation of the BDMatrix class */ namespace Dune { /** * @addtogroup ISTL_SPMV * @{ */ /** \brief A block-diagonal matrix \todo It would be safer and more efficient to have a real implementation of a block-diagonal matrix and not just subclassing from BCRSMatrix. But that's quite a lot of work for that little advantage.*/ template > class BDMatrix : public BCRSMatrix { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! implement row_type with compressed vector //typedef BCRSMatrix::row_type row_type; //! The type for the index access and the size typedef typename A::size_type size_type; //! increment block level counter enum {blocklevel = B::blocklevel+1}; /** \brief Default constructor */ BDMatrix() : BCRSMatrix() {} explicit BDMatrix(int size) : BCRSMatrix(size, size, BCRSMatrix::random) { for (int i=0; iBCRSMatrix::setrowsize(i, 1); this->BCRSMatrix::endrowsizes(); for (int i=0; iBCRSMatrix::addindex(i, i); this->BCRSMatrix::endindices(); } //! assignment BDMatrix& operator= (const BDMatrix& other) { this->BCRSMatrix::operator=(other); return *this; } //! assignment from scalar BDMatrix& operator= (const field_type& k) { this->BCRSMatrix::operator=(k); return *this; } /** \brief Inverts the matrix */ void invert() { for (int i=0; iN(); i++) (*this)[i][i].invert(); } private: // //////////////////////////////////////////////////////////////////////////// // The following methods from the base class should now actually be called // //////////////////////////////////////////////////////////////////////////// // createbegin and createend should be in there, too, but I can't get it to compile // BCRSMatrix::CreateIterator createbegin () {} // BCRSMatrix::CreateIterator createend () {} void setrowsize (size_type i, size_type s) {} void incrementrowsize (size_type i) {} void endrowsizes () {} void addindex (size_type row, size_type col) {} void endindices () {} }; /** @}*/ } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/btdmatrix.hh000066400000000000000000000126101313314427100176470ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_BTDMATRIX_HH #define DUNE_ISTL_BTDMATRIX_HH #include #include /** \file \author Oliver Sander \brief Implementation of the BTDMatrix class */ namespace Dune { /** * @addtogroup ISTL_SPMV * @{ */ /** \brief A block-tridiagonal matrix \todo It would be safer and more efficient to have a real implementation of a block-tridiagonal matrix and not just subclassing from BCRSMatrix. But that's quite a lot of work for that little advantage.*/ template > class BTDMatrix : public BCRSMatrix { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! implement row_type with compressed vector //typedef BCRSMatrix::row_type row_type; //! The type for the index access and the size typedef typename A::size_type size_type; //! increment block level counter enum {blocklevel = B::blocklevel+1}; /** \brief Default constructor */ BTDMatrix() : BCRSMatrix() {} explicit BTDMatrix(int size) : BCRSMatrix(size, size, BCRSMatrix::random) { // special handling for 1x1 matrices if (size==1) { this->BCRSMatrix::setrowsize(0, 1); this->BCRSMatrix::endrowsizes(); this->BCRSMatrix::addindex(0, 0); this->BCRSMatrix::endindices(); return; } // Set number of entries for each row this->BCRSMatrix::setrowsize(0, 2); for (int i=1; iBCRSMatrix::setrowsize(i, 3); this->BCRSMatrix::setrowsize(size-1, 2); this->BCRSMatrix::endrowsizes(); // The actual entries for each row this->BCRSMatrix::addindex(0, 0); this->BCRSMatrix::addindex(0, 1); for (int i=1; iBCRSMatrix::addindex(i, i-1); this->BCRSMatrix::addindex(i, i ); this->BCRSMatrix::addindex(i, i+1); } this->BCRSMatrix::addindex(size-1, size-2); this->BCRSMatrix::addindex(size-1, size-1); this->BCRSMatrix::endindices(); } //! assignment BTDMatrix& operator= (const BTDMatrix& other) { this->BCRSMatrix::operator=(other); return *this; } //! assignment from scalar BTDMatrix& operator= (const field_type& k) { this->BCRSMatrix::operator=(k); return *this; } /** \brief Use the Thomas algorithm to solve the system Ax=b in O(n) time * * \exception ISTLError if the matrix is singular * */ template void solve (V& x, const V& rhs) const { // special handling for 1x1 matrices. The generic algorithm doesn't work for them if (this->N()==1) { (*this)[0][0].solve(x[0],rhs[0]); return; } // Make copies of the rhs and the right matrix band V d = rhs; std::vector c(this->N()-1); for (size_t i=0; iN()-1; i++) c[i] = (*this)[i][i+1]; /* Modify the coefficients. */ block_type a_00_inv = (*this)[0][0]; a_00_inv.invert(); //c[0] /= (*this)[0][0]; /* Division by zero risk. */ block_type c_0_tmp = c[0]; FMatrixHelp::multMatrix(a_00_inv, c_0_tmp, c[0]); // d = a^{-1} d /* Division by zero would imply a singular matrix. */ typename V::block_type d_0_tmp = d[0]; a_00_inv.mv(d_0_tmp,d[0]); for (unsigned int i = 1; i < this->N(); i++) { // id = ( a_ii - c_{i-1} a_{i, i-1} ) ^{-1} block_type tmp; FMatrixHelp::multMatrix((*this)[i][i-1],c[i-1], tmp); block_type id = (*this)[i][i]; id -= tmp; id.invert(); /* Division by zero risk. */ if (iN() - 1] = d[this->N() - 1]; for (int i = this->N() - 2; i >= 0; i--) { //x[i] = d[i] - c[i] * x[i + 1]; x[i] = d[i]; c[i].mmv(x[i+1], x[i]); } } private: // //////////////////////////////////////////////////////////////////////////// // The following methods from the base class should now actually be called // //////////////////////////////////////////////////////////////////////////// // createbegin and createend should be in there, too, but I can't get it to compile // BCRSMatrix::CreateIterator createbegin () {} // BCRSMatrix::CreateIterator createend () {} void setrowsize (size_type i, size_type s) {} void incrementrowsize (size_type i) {} void endrowsizes () {} void addindex (size_type row, size_type col) {} void endindices () {} }; /** @}*/ } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/bvector.hh000066400000000000000000000777561313314427100173430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_BVECTOR_HH #define DUNE_ISTL_BVECTOR_HH #include #include #include #include #include #include #include #include "istlexception.hh" #include "basearray.hh" /*! \file \brief This file implements a vector space as a tensor product of a given vector space. The number of components can be given at run-time. */ namespace Dune { template > class BlockVectorWindow; /** \brief An unmanaged vector of blocks. block_vector_unmanaged extends the base_array_unmanaged by vector operations such as addition and scalar multiplication. No memory management is added. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class block_vector_unmanaged : public base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! The size type for the index access typedef typename A::size_type size_type; //! make iterators available as types typedef typename base_array_unmanaged::iterator Iterator; //! make iterators available as types typedef typename base_array_unmanaged::const_iterator ConstIterator; //! for STL compatibility typedef B value_type; //! Type used for references typedef B& reference; //! Type used for const references typedef const B& const_reference; //===== assignment from scalar //! Assignment from a scalar block_vector_unmanaged& operator= (const field_type& k) { for (size_type i=0; in; i++) (*this)[i] = k; return *this; } //===== vector space arithmetic //! vector space addition block_vector_unmanaged& operator+= (const block_vector_unmanaged& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif for (size_type i=0; in; ++i) (*this)[i] += y[i]; return *this; } //! vector space subtraction block_vector_unmanaged& operator-= (const block_vector_unmanaged& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif for (size_type i=0; in; ++i) (*this)[i] -= y[i]; return *this; } //! vector space multiplication with scalar block_vector_unmanaged& operator*= (const field_type& k) { for (size_type i=0; in; ++i) (*this)[i] *= k; return *this; } //! vector space division by scalar block_vector_unmanaged& operator/= (const field_type& k) { for (size_type i=0; in; ++i) (*this)[i] /= k; return *this; } //! vector space axpy operation block_vector_unmanaged& axpy (const field_type& a, const block_vector_unmanaged& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif for (size_type i=0; in; ++i) (*this)[i].axpy(a,y[i]); return *this; } /** * \brief indefinite vector dot product \f$\left (x^T \cdot y \right)\f$ which corresponds to Petsc's VecTDot * * http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecTDot.html * @param y other (compatible) vector * @return */ template typename PromotionTraits::PromotedType operator* (const block_vector_unmanaged& y) const { typedef typename PromotionTraits::PromotedType PromotedType; PromotedType sum(0); #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif for (size_type i=0; in; ++i) { sum += PromotedType(((*this)[i])*y[i]); } return sum; } /** * @brief vector dot product \f$\left (x^H \cdot y \right)\f$ which corresponds to Petsc's VecDot * * http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDot.html * @param y other (compatible) vector * @return */ template typename PromotionTraits::PromotedType dot(const block_vector_unmanaged& y) const { typedef typename PromotionTraits::PromotedType PromotedType; PromotedType sum(0); #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=y.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif for (size_type i=0; in; ++i) sum += ((*this)[i]).dot(y[i]); return sum; } //===== norms //! one norm (sum over absolute values of entries) typename FieldTraits::real_type one_norm () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (*this)[i].one_norm(); return sum; } //! simplified one norm (uses Manhattan norm for complex values) typename FieldTraits::real_type one_norm_real () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (*this)[i].one_norm_real(); return sum; } //! two norm sqrt(sum over squared values of entries) typename FieldTraits::real_type two_norm () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (*this)[i].two_norm2(); return sqrt(sum); } //! Square of the two-norm (the sum over the squared values of the entries) typename FieldTraits::real_type two_norm2 () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (*this)[i].two_norm2(); return sum; } //! infinity norm (maximum of absolute values of entries) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type const a = x.infinity_norm(); norm = max(a, norm); } return norm; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type const a = x.infinity_norm_real(); norm = max(a, norm); } return norm; } //! infinity norm (maximum of absolute values of entries) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type const a = x.infinity_norm(); norm = max(a, norm); isNaN += a; } isNaN /= isNaN; return norm * isNaN; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type const a = x.infinity_norm_real(); norm = max(a, norm); isNaN += a; } isNaN /= isNaN; return norm * isNaN; } //===== sizes //! number of blocks in the vector (are of size 1 here) size_type N () const { return this->n; } //! dimension of the vector space size_type dim () const { size_type d=0; for (size_type i=0; in; i++) d += (*this)[i].dim(); return d; } protected: //! make constructor protected, so only derived classes can be instantiated block_vector_unmanaged () : base_array_unmanaged() { } }; /** @addtogroup ISTL_SPMV @{ */ /** \brief A vector of blocks with memory management. BlockVector adds memory management with ordinary copy semantics to the block_vector_unmanaged template. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. */ template > class BlockVector : public block_vector_unmanaged { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! The type for the index access typedef typename A::size_type size_type; //! increment block level counter enum { //! The number of blocklevel we contain. blocklevel = B::blocklevel+1 }; //! make iterators available as types typedef typename block_vector_unmanaged::Iterator Iterator; //! make iterators available as types typedef typename block_vector_unmanaged::ConstIterator ConstIterator; //===== constructors and such //! makes empty vector BlockVector () : block_vector_unmanaged(), capacity_(0) {} //! make vector with _n components explicit BlockVector (size_type _n) { this->n = _n; capacity_ = _n; if (capacity_>0) { this->p = this->allocator_.allocate(capacity_); // actually construct the objects new(this->p)B[capacity_]; } else { this->p = 0; this->n = 0; capacity_ = 0; } } /** \brief Construct from a std::initializer_list */ BlockVector (std::initializer_list const &l) { this->n = l.size(); capacity_ = l.size(); if (capacity_>0) { this->p = this->allocator_.allocate(capacity_); // actually construct the objects new(this->p)B[capacity_]; std::copy_n(l.begin(), l.size(), this->p); } else { this->p = 0; this->n = 0; capacity_ = 0; } } /** \brief Make vector with _n components but preallocating capacity components If _n > capacity then space for _n entries is allocated. \note This constructor is somewhat dangerous. People may be tempted to write something like \code BlockVector > my_vector(100,0); \endcode expecting to obtain a vector of 100 doubles initialized with zero. However, the code calls this constructor which tacitly does something else! */ template BlockVector (size_type _n, S _capacity) { static_assert(std::numeric_limits::is_integer, "capacity must be an unsigned integral type (be aware, that this constructor does not set the default value!)" ); size_type capacity = _capacity; this->n = _n; if(this->n > capacity) capacity_ = _n; else capacity_ = capacity; if (capacity_>0) { this->p = this->allocator_.allocate(capacity_); new (this->p)B[capacity_]; } else { this->p = 0; this->n = 0; capacity_ = 0; } } /** * @brief Reserve space. * * After calling this method the vector can hold up to * capacity values. If the specified capacity is smaller * than the current capacity and bigger than the current size * space will be freed. * * If the template parameter copyOldValues is true the values will * be copied. If it is false the old values are lost. * * @param capacity The maximum number of elements the vector * needs to hold. * @param copyOldValues If false no object will be copied and the data might be * lost. Default value is true. */ void reserve(size_type capacity, bool copyOldValues=true) { if(capacity >= block_vector_unmanaged::N() && capacity != capacity_) { // save the old data B* pold = this->p; if(capacity>0) { // create new array with capacity this->p = this->allocator_.allocate(capacity); new (this->p)B[capacity]; if(copyOldValues) { // copy the old values B* to = this->p; B* from = pold; for(size_type i=0; i < block_vector_unmanaged::N(); ++i, ++from, ++to) *to = *from; } if(capacity_ > 0) { // Destruct old objects and free memory int i=capacity_; while (i) pold[--i].~B(); this->allocator_.deallocate(pold,capacity_); } }else{ if(capacity_ > 0) // free old data this->p = 0; capacity_ = 0; } capacity_ = capacity; } } /** * @brief Get the capacity of the vector. * * I. e. the maximum number of elements the vector can hold. * @return The capacity of the vector. */ size_type capacity() const { return capacity_; } /** * @brief Resize the vector. * * After calling this method BlockVector::N() will return size * If the capacity of the vector is smaller than the specified * size then reserve(size) will be called. * * If the template parameter copyOldValues is true the values * will be copied if the capacity changes. If it is false * the old values are lost. * @param size The new size of the vector. * @param copyOldValues If false no object will be copied and the data might be * lost. */ void resize(size_type size, bool copyOldValues=true) { if(size > block_vector_unmanaged::N()) if(capacity_ < size) this->reserve(size, copyOldValues); this->n = size; } //! copy constructor BlockVector (const BlockVector& a) : block_vector_unmanaged(a) { // allocate memory with same size as a this->n = a.n; capacity_ = a.capacity_; if (capacity_>0) { this->p = this->allocator_.allocate(capacity_); new (this->p)B[capacity_]; } else { this->n = 0; this->p = 0; } // and copy elements for (size_type i=0; in; i++) this->p[i]=a.p[i]; } //! free dynamic memory ~BlockVector () { if (capacity_>0) { int i=capacity_; while (i) this->p[--i].~B(); this->allocator_.deallocate(this->p,capacity_); } } //! assignment BlockVector& operator= (const BlockVector& a) { if (&a!=this) // check if this and a are different objects { // adjust size of vector if (capacity_!=a.capacity_) // check if size is different { if (capacity_>0) { int i=capacity_; while (i) this->p[--i].~B(); this->allocator_.deallocate(this->p,capacity_); // free old memory } capacity_ = a.capacity_; if (capacity_>0) { this->p = this->allocator_.allocate(capacity_); new (this->p)B[capacity_]; } else { this->p = 0; capacity_ = 0; } } this->n = a.n; // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } return *this; } //! assign from scalar BlockVector& operator= (const field_type& k) { // forward to operator= in base class (static_cast&>(*this)) = k; return *this; } //! Assignment from BlockVectorWindow template BlockVector& operator= (const BlockVectorWindow& other) { resize(other.size()); for(std::size_t i=0; i struct FieldTraits< BlockVector > { typedef typename FieldTraits::field_type field_type; typedef typename FieldTraits::real_type real_type; }; /** @} */ //! Send BlockVector to an output stream template std::ostream& operator<< (std::ostream& s, const BlockVector& v) { typedef typename BlockVector::size_type size_type; for (size_type i=0; i #else template > #endif class BlockVectorWindow : public block_vector_unmanaged { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! The type for the index access typedef typename A::size_type size_type; //! increment block level counter enum { //! The number of blocklevels we contain blocklevel = B::blocklevel+1 }; //! make iterators available as types typedef typename block_vector_unmanaged::Iterator Iterator; //! make iterators available as types typedef typename block_vector_unmanaged::ConstIterator ConstIterator; //===== constructors and such //! makes empty array BlockVectorWindow () : block_vector_unmanaged() { } //! make array from given pointer and size BlockVectorWindow (B* _p, size_type _n) { this->n = _n; this->p = _p; } //! copy constructor, this has reference semantics! BlockVectorWindow (const BlockVectorWindow& a) { this->n = a.n; this->p = a.p; } //! assignment BlockVectorWindow& operator= (const BlockVectorWindow& a) { // check correct size #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif if (&a!=this) // check if this and a are different objects { // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } return *this; } //! assign from scalar BlockVectorWindow& operator= (const field_type& k) { (static_cast&>(*this)) = k; return *this; } //===== window manipulation methods //! set size and pointer void set (size_type _n, B* _p) { this->n = _n; this->p = _p; } //! set size only void setsize (size_type _n) { this->n = _n; } //! set pointer only void setptr (B* _p) { this->p = _p; } //! get pointer B* getptr () { return this->p; } //! get size size_type getsize () { return this->n; } }; /** compressed_block_vector_unmanaged extends the compressed base_array_unmanaged by vector operations such as addition and scalar multiplication. No memory management is added. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class compressed_block_vector_unmanaged : public compressed_base_array_unmanaged { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! make iterators available as types typedef typename compressed_base_array_unmanaged::iterator Iterator; //! make iterators available as types typedef typename compressed_base_array_unmanaged::const_iterator ConstIterator; //! The type for the index access typedef typename A::size_type size_type; //===== assignment from scalar compressed_block_vector_unmanaged& operator= (const field_type& k) { for (size_type i=0; in; i++) (this->p)[i] = k; return *this; } //===== vector space arithmetic //! vector space addition template compressed_block_vector_unmanaged& operator+= (const V& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch"); #endif for (size_type i=0; ioperator[](y.j[i]) += y.p[i]; return *this; } //! vector space subtraction template compressed_block_vector_unmanaged& operator-= (const V& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch"); #endif for (size_type i=0; ioperator[](y.j[i]) -= y.p[i]; return *this; } //! vector space axpy operation template compressed_block_vector_unmanaged& axpy (const field_type& a, const V& y) { #ifdef DUNE_ISTL_WITH_CHECKING if (!includesindexset(y)) DUNE_THROW(ISTLError,"index set mismatch"); #endif for (size_type i=0; ioperator[](y.j[i])).axpy(a,y.p[i]); return *this; } //! vector space multiplication with scalar compressed_block_vector_unmanaged& operator*= (const field_type& k) { for (size_type i=0; in; ++i) (this->p)[i] *= k; return *this; } //! vector space division by scalar compressed_block_vector_unmanaged& operator/= (const field_type& k) { for (size_type i=0; in; ++i) (this->p)[i] /= k; return *this; } //===== Euclidean scalar product //! scalar product field_type operator* (const compressed_block_vector_unmanaged& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (!includesindexset(y) || !y.includesindexset(*this) ) DUNE_THROW(ISTLError,"index set mismatch"); #endif field_type sum=0; for (size_type i=0; in; ++i) sum += (this->p)[i] * y[(this->j)[i]]; return sum; } //===== norms //! one norm (sum over absolute values of entries) typename FieldTraits::real_type one_norm () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (this->p)[i].one_norm(); return sum; } //! simplified one norm (uses Manhattan norm for complex values) typename FieldTraits::real_type one_norm_real () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (this->p)[i].one_norm_real(); return sum; } //! two norm sqrt(sum over squared values of entries) typename FieldTraits::real_type two_norm () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (this->p)[i].two_norm2(); return sqrt(sum); } //! Square of the two-norm (the sum over the squared values of the entries) typename FieldTraits::real_type two_norm2 () const { typename FieldTraits::real_type sum=0; for (size_type i=0; in; ++i) sum += (this->p)[i].two_norm2(); return sum; } //! infinity norm (maximum of absolute values of entries) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type const a = x.infinity_norm(); norm = max(a, norm); } return norm; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type const a = x.infinity_norm_real(); norm = max(a, norm); } return norm; } //! infinity norm (maximum of absolute values of entries) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type const a = x.infinity_norm(); norm = max(a, norm); isNaN += a; } isNaN /= isNaN; return norm * isNaN; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type const a = x.infinity_norm_real(); norm = max(a, norm); isNaN += a; } isNaN /= isNaN; return norm * isNaN; } //===== sizes //! number of blocks in the vector (are of size 1 here) size_type N () const { return this->n; } //! dimension of the vector space size_type dim () const { size_type d=0; for (size_type i=0; in; i++) d += (this->p)[i].dim(); return d; } protected: //! make constructor protected, so only derived classes can be instantiated compressed_block_vector_unmanaged () : compressed_base_array_unmanaged() { } //! return true if index sets coincide template bool includesindexset (const V& y) { typename V::ConstIterator e=this->end(); for (size_type i=0; ifind(y.j[i])==e) return false; return true; } }; /** CompressedBlockVectorWindow adds window manipulation functions to the compressed_block_vector_unmanaged template. This class has no memory management. It assumes that the storage for the entries of the vector and its index set is maintained outside of this class. But you can copy objects of this class and of the base class with reference semantics. Assignment copies the data, if the format is incopmpatible with the argument an exception is thrown in debug mode. Error checking: no error checking is provided normally. Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. \internal This class is an implementation detail, and should not be used outside of dune-istl. */ template > class CompressedBlockVectorWindow : public compressed_block_vector_unmanaged { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the type representing the components typedef B block_type; //! export the allocator type typedef A allocator_type; //! The type for the index access typedef typename A::size_type size_type; //! increment block level counter enum { //! The number of block level this vector contains. blocklevel = B::blocklevel+1 }; //! make iterators available as types typedef typename compressed_block_vector_unmanaged::Iterator Iterator; //! make iterators available as types typedef typename compressed_block_vector_unmanaged::ConstIterator ConstIterator; //===== constructors and such //! makes empty array CompressedBlockVectorWindow () : compressed_block_vector_unmanaged() { } //! make array from given pointers and size CompressedBlockVectorWindow (B* _p, size_type* _j, size_type _n) { this->n = _n; this->p = _p; this->j = _j; } //! copy constructor, this has reference semantics! CompressedBlockVectorWindow (const CompressedBlockVectorWindow& a) { this->n = a.n; this->p = a.p; this->j = a.j; } //! assignment CompressedBlockVectorWindow& operator= (const CompressedBlockVectorWindow& a) { // check correct size #ifdef DUNE_ISTL_WITH_CHECKING if (this->n!=a.N()) DUNE_THROW(ISTLError,"vector size mismatch"); #endif if (&a!=this) // check if this and a are different objects { // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; for (size_type i=0; in; i++) this->j[i]=a.j[i]; } return *this; } //! assign from scalar CompressedBlockVectorWindow& operator= (const field_type& k) { (static_cast&>(*this)) = k; return *this; } //===== window manipulation methods //! set size and pointer void set (size_type _n, B* _p, size_type* _j) { this->n = _n; this->p = _p; this->j = _j; } //! set size only void setsize (size_type _n) { this->n = _n; } //! set pointer only void setptr (B* _p) { this->p = _p; } //! set pointer only void setindexptr (size_type* _j) { this->j = _j; } //! get pointer B* getptr () { return this->p; } //! get pointer size_type* getindexptr () { return this->j; } //! get pointer const B* getptr () const { return this->p; } //! get pointer const size_type* getindexptr () const { return this->j; } //! get size size_type getsize () const { return this->n; } }; } // end namespace #endif dune-istl-2.5.1/dune/istl/colcompmatrix.hh000066400000000000000000000401631313314427100205360ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_COLCOMPMATRIX_HH #define DUNE_ISTL_COLCOMPMATRIX_HH #include "bcrsmatrix.hh" #include "bvector.hh" #include #include #include #include #include namespace Dune { /** * @brief Provides access to an iterator over all matrix rows. * * @tparam M The type of the matrix. */ template class MatrixRowSet { public: //! @brief The type of the matrix. typedef M Matrix; //! @brief The matrix row iterator type. typedef typename Matrix::ConstRowIterator const_iterator; /** * @brief Construct an row set over all matrix rows. * @param m The matrix for which we manage the rows. */ MatrixRowSet(const Matrix& m) : m_(m) {} //! @brief Get the row iterator at the first row. const_iterator begin() const { return m_.begin(); } //! @brief Get the row iterator at the end of all rows. const_iterator end() const { return m_.end(); } private: const Matrix& m_; }; /** * @brief Provides access to an iterator over an arbitrary subset * of matrix rows. * * @tparam M The type of the matrix. * @tparam S the type of the set of valid row indices. */ template class MatrixRowSubset { public: /** @brief the type of the matrix class. */ typedef M Matrix; /** @brief the type of the set of valid row indices. */ typedef S RowIndexSet; /** * @brief Construct an row set over all matrix rows. * @param m The matrix for which we manage the rows. * @param s The set of row indices we manage. */ MatrixRowSubset(const Matrix& m, const RowIndexSet& s) : m_(m), s_(s) {} const Matrix& matrix() const { return m_; } const RowIndexSet& rowIndexSet() const { return s_; } //! @brief The matrix row iterator type. class const_iterator : public ForwardIteratorFacade { public: const_iterator(typename Matrix::const_iterator firstRow, typename RowIndexSet::const_iterator pos) : firstRow_(firstRow), pos_(pos) {} const typename Matrix::row_type& dereference() const { return *(firstRow_+ *pos_); } bool equals(const const_iterator& o) const { return pos_==o.pos_; } void increment() { ++pos_; } typename RowIndexSet::value_type index() const { return *pos_; } private: //! @brief Iterator pointing to the first row of the matrix. typename Matrix::const_iterator firstRow_; //! @brief Iterator pointing to the current row index. typename RowIndexSet::const_iterator pos_; }; //! @brief Get the row iterator at the first row. const_iterator begin() const { return const_iterator(m_.begin(), s_.begin()); } //! @brief Get the row iterator at the end of all rows. const_iterator end() const { return const_iterator(m_.begin(), s_.end()); } private: //! @brief The matrix for which we manage the row subset. const Matrix& m_; //! @brief The set of row indices we manage. const RowIndexSet& s_; }; /** * @brief Utility class for converting an ISTL Matrix into a column-compressed matrix * @tparam M the matrix type */ template struct ColCompMatrix {}; /** * @brief Inititializer for the ColCompMatrix * as needed by OverlappingSchwarz * @tparam M the matrix type */ template struct ColCompMatrixInitializer {}; template class SeqOverlappingSchwarz; template struct SeqOverlappingSchwarzAssemblerHelper; /** * @brief Converter for BCRSMatrix to column-compressed Matrix. * specialization for BCRSMatrix */ template class ColCompMatrix,TA> > { friend struct ColCompMatrixInitializer,TA> >; public: /** @brief The type of the matrix to convert. */ typedef BCRSMatrix,TA> Matrix; friend struct SeqOverlappingSchwarzAssemblerHelper, true>; typedef typename Matrix::size_type size_type; /** * @brief Constructor that initializes the data. * @param mat The matrix to convert. */ explicit ColCompMatrix(const Matrix& mat); ColCompMatrix(); /** @brief Destructor */ virtual ~ColCompMatrix(); /** * @brief Get the number of rows. * @return The number of rows. */ size_type N() const { return N_; } size_type nnz() const { return Nnz_/n/m; } /** * @brief Get the number of columns. * @return The number of columns. */ size_type M() const { return M_; } B* getValues() const { return values; } int* getRowIndex() const { return rowindex; } int* getColStart() const { return colstart; } ColCompMatrix& operator=(const Matrix& mat); ColCompMatrix& operator=(const ColCompMatrix& mat); /** * @brief Initialize data from a given set of matrix rows and columns * @param mat the matrix with the values * @param mrs The set of row (and column) indices to remove */ virtual void setMatrix(const Matrix& mat, const std::set& mrs); /** @brief free allocated space. */ virtual void free(); /** @brief Initialize data from given matrix. */ virtual void setMatrix(const Matrix& mat); public: int N_, M_, Nnz_; B* values; int* rowindex; int* colstart; }; template class ColCompMatrixInitializer,A> > { template friend class OverlappingSchwarzInitializer; public: typedef Dune::BCRSMatrix,A> Matrix; typedef Dune::ColCompMatrix ColCompMatrix; typedef typename Matrix::row_type::const_iterator CIter; typedef typename Matrix::size_type size_type; ColCompMatrixInitializer(ColCompMatrix& lum); ColCompMatrixInitializer(); virtual ~ColCompMatrixInitializer(); template void addRowNnz(const Iter& row) const; template void addRowNnz(const Iter& row, const Set& s) const; void allocate(); template void countEntries(const Iter& row, const CIter& col) const; void countEntries(size_type colidx) const; void calcColstart() const; template void copyValue(const Iter& row, const CIter& col) const; void copyValue(const CIter& col, size_type rowindex, size_type colidx) const; virtual void createMatrix() const; protected: void allocateMatrixStorage() const; void allocateMarker(); ColCompMatrix* mat; size_type cols; mutable size_type *marker; }; template ColCompMatrixInitializer,A> >::ColCompMatrixInitializer(ColCompMatrix& mat_) : mat(&mat_), cols(mat_.M()), marker(0) { mat->Nnz_=0; } template ColCompMatrixInitializer,A> >::ColCompMatrixInitializer() : mat(0), cols(0), marker(0) {} template ColCompMatrixInitializer,A> >::~ColCompMatrixInitializer() { if(marker) delete[] marker; } template template void ColCompMatrixInitializer,A> >::addRowNnz(const Iter& row) const { mat->Nnz_+=row->getsize(); } template template void ColCompMatrixInitializer,A> >::addRowNnz(const Iter& row, const Map& indices) const { typedef typename Iter::value_type::const_iterator RIter; typedef typename Map::const_iterator MIter; MIter siter =indices.begin(); for(RIter entry=row->begin(); entry!=row->end(); ++entry) { for(; siter!=indices.end() && *siterNnz_; } } template void ColCompMatrixInitializer,A> >::allocate() { allocateMatrixStorage(); allocateMarker(); } template void ColCompMatrixInitializer,A> >::allocateMatrixStorage() const { mat->Nnz_*=n*m; // initialize data mat->values=new T[mat->Nnz_]; mat->rowindex=new int[mat->Nnz_]; mat->colstart=new int[cols+1]; } template void ColCompMatrixInitializer,A> >::allocateMarker() { marker = new typename Matrix::size_type[cols]; for(size_type i=0; i < cols; ++i) marker[i]=0; } template template void ColCompMatrixInitializer,A> >::countEntries(const Iter& row, const CIter& col) const { DUNE_UNUSED_PARAMETER(row); countEntries(col.index()); } template void ColCompMatrixInitializer,A> >::countEntries(size_type colindex) const { for(size_type i=0; i < m; ++i) { assert(colindex*m+i void ColCompMatrixInitializer,A> >::calcColstart() const { mat->colstart[0]=0; for(size_type i=0; i < cols; ++i) { assert(icolstart[i+1]=mat->colstart[i]+marker[i]; marker[i]=mat->colstart[i]; } } template template void ColCompMatrixInitializer,A> >::copyValue(const Iter& row, const CIter& col) const { copyValue(col, row.index(), col.index()); } template void ColCompMatrixInitializer,A> >::copyValue(const CIter& col, size_type rowindex, size_type colindex) const { for(size_type i=0; icolstart[colindex*m+j+1]); assert((int)marker[colindex*m+j]Nnz_); mat->rowindex[marker[colindex*m+j]]=rowindex*n+i; mat->values[marker[colindex*m+j]]=(*col)[i][j]; ++marker[colindex*m+j]; // index for next entry in column } } } template void ColCompMatrixInitializer,A> >::createMatrix() const { delete[] marker; marker=0; } template void copyToColCompMatrix(F& initializer, const MRS& mrs) { typedef typename MRS::const_iterator Iter; typedef typename std::iterator_traits::value_type::const_iterator CIter; for(Iter row=mrs.begin(); row!= mrs.end(); ++row) initializer.addRowNnz(row); initializer.allocate(); for(Iter row=mrs.begin(); row!= mrs.end(); ++row) { for(CIter col=row->begin(); col != row->end(); ++col) initializer.countEntries(row, col); } initializer.calcColstart(); for(Iter row=mrs.begin(); row!= mrs.end(); ++row) { for(CIter col=row->begin(); col != row->end(); ++col) { initializer.copyValue(row, col); } } initializer.createMatrix(); } template void copyToColCompMatrix(F& initializer, const MatrixRowSubset& mrs) { typedef MatrixRowSubset MRS; typedef typename MRS::RowIndexSet SIS; typedef typename SIS::const_iterator SIter; typedef typename MRS::const_iterator Iter; typedef typename std::iterator_traits::value_type row_type; typedef typename row_type::const_iterator CIter; // Calculate upper Bound for nonzeros for(Iter row=mrs.begin(); row!= mrs.end(); ++row) initializer.addRowNnz(row, mrs.rowIndexSet()); initializer.allocate(); typedef typename MRS::Matrix::size_type size_type; // A vector containing the corresponding indices in // the to create submatrix. // If an entry is the maximum of size_type then this index will not appear in // the submatrix. std::vector subMatrixIndex(mrs.matrix().N(), std::numeric_limits::max()); size_type s=0; for(SIter index = mrs.rowIndexSet().begin(); index!=mrs.rowIndexSet().end(); ++index) subMatrixIndex[*index]=s++; for(Iter row=mrs.begin(); row!= mrs.end(); ++row) for(CIter col=row->begin(); col != row->end(); ++col) { if(subMatrixIndex[col.index()]!=std::numeric_limits::max()) // This column is in our subset (use submatrix column index) initializer.countEntries(subMatrixIndex[col.index()]); } initializer.calcColstart(); for(Iter row=mrs.begin(); row!= mrs.end(); ++row) for(CIter col=row->begin(); col != row->end(); ++col) { if(subMatrixIndex[col.index()]!=std::numeric_limits::max()) // This value is in our submatrix -> copy (use submatrix indices initializer.copyValue(col, subMatrixIndex[row.index()], subMatrixIndex[col.index()]); } initializer.createMatrix(); } #ifndef DOXYGEN template ColCompMatrix,TA> >::ColCompMatrix() : N_(0), M_(0), Nnz_(0), values(0), rowindex(0), colstart(0) {} template ColCompMatrix,TA> > ::ColCompMatrix(const Matrix& mat) : N_(n*mat.N()), M_(m*mat.M()), Nnz_(n*m*mat.nonzeroes()) {} template ColCompMatrix,TA> >& ColCompMatrix,TA> >::operator=(const Matrix& mat) { if(N_+M_+Nnz_!=0) free(); setMatrix(mat); return *this; } template ColCompMatrix,TA> >& ColCompMatrix,TA> >::operator=(const ColCompMatrix& mat) { if(N_+M_+Nnz_!=0) free(); N_=mat.N_; M_=mat.M_; Nnz_= mat.Nnz_; if(M_>0) { colstart=new int[M_+1]; for(int i=0; i<=M_; ++i) colstart[i]=mat.colstart[i]; } if(Nnz_>0) { values = new B[Nnz_]; rowindex = new int[Nnz_]; for(int i=0; i void ColCompMatrix,TA> > ::setMatrix(const Matrix& mat) { N_=n*mat.N(); M_=m*mat.M(); ColCompMatrixInitializer initializer(*this); copyToColCompMatrix(initializer, MatrixRowSet(mat)); } template void ColCompMatrix,TA> > ::setMatrix(const Matrix& mat, const std::set& mrs) { if(N_+M_+Nnz_!=0) free(); N_=mrs.size()*n; M_=mrs.size()*m; ColCompMatrixInitializer initializer(*this); copyToColCompMatrix(initializer, MatrixRowSubset >(mat,mrs)); } template ColCompMatrix,TA> >::~ColCompMatrix() { if(N_+M_+Nnz_!=0) free(); } template void ColCompMatrix,TA> >::free() { delete[] values; delete[] rowindex; delete[] colstart; N_ = 0; M_ = 0; Nnz_ = 0; } #endif // DOXYGEN } #endif dune-istl-2.5.1/dune/istl/eigenvalue/000077500000000000000000000000001313314427100174545ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/eigenvalue/CMakeLists.txt000066400000000000000000000002341313314427100222130ustar00rootroot00000000000000add_subdirectory(test) #install headers install(FILES arpackpp.hh poweriteration.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/istl/eigenvalue) dune-istl-2.5.1/dune/istl/eigenvalue/arpackpp.hh000066400000000000000000001201651313314427100216030ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_EIGENVALUE_ARPACKPP_HH #define DUNE_ISTL_EIGENVALUE_ARPACKPP_HH #if HAVE_ARPACKPP #include // provides std::abs, std::pow, std::sqrt #include // provides std::cout, std::endl #include // provides std::string #include // provides Dune::FieldVector #include // provides DUNE_THROW(...) #include // provides Dune::BlockVector #include // provides Dune::ISTLError #include // provides Dune::printvector(...) #ifdef Status #undef Status // prevent preprocessor from damaging the ARPACK++ // code when "X11/Xlib.h" is included (the latter // defines Status as "#define Status int" and // ARPACK++ provides a class with a method called // Status) #endif #include "arssym.h" // provides ARSymStdEig namespace Dune { /** * \brief Wrapper for a DUNE-ISTL BCRSMatrix which can be used * together with those algorithms of the ARPACK++ library * which solely perform the products A*v and/or A^T*A*v * and/or A*A^T*v. * * \todo The current implementation is limited to DUNE-ISTL * BCRSMatrix types with blocklevel 2. An extension to * blocklevel >= 2 might be provided in a future version. * * \tparam BCRSMatrix Type of a DUNE-ISTL BCRSMatrix; * is assumed to have blocklevel 2. * * \author Sebastian Westerheide. */ template class ArPackPlusPlus_BCRSMatrixWrapper { public: //! Type of the underlying field of the matrix typedef typename BCRSMatrix::field_type Real; public: //! Construct from BCRSMatrix A ArPackPlusPlus_BCRSMatrixWrapper (const BCRSMatrix& A) : A_(A), m_(A_.M() * mBlock), n_(A_.N() * nBlock) { // assert that BCRSMatrix type has blocklevel 2 static_assert (BCRSMatrix::blocklevel == 2, "Only BCRSMatrices with blocklevel 2 are supported."); // allocate memory for auxiliary block vector objects // which are compatible to matrix rows / columns domainBlockVector.resize(A_.N(),false); rangeBlockVector.resize(A_.M(),false); } //! Perform matrix-vector product w = A*v inline void multMv (Real* v, Real* w) { // get vector v as an object of appropriate type arrayToDomainBlockVector(v,domainBlockVector); // perform matrix-vector product A_.mv(domainBlockVector,rangeBlockVector); // get vector w from object of appropriate type rangeBlockVectorToArray(rangeBlockVector,w); }; //! Perform matrix-vector product w = A^T*A*v inline void multMtMv (Real* v, Real* w) { // get vector v as an object of appropriate type arrayToDomainBlockVector(v,domainBlockVector); // perform matrix-vector product A_.mv(domainBlockVector,rangeBlockVector); A_.mtv(rangeBlockVector,domainBlockVector); // get vector w from object of appropriate type domainBlockVectorToArray(domainBlockVector,w); }; //! Perform matrix-vector product w = A*A^T*v inline void multMMtv (Real* v, Real* w) { // get vector v as an object of appropriate type arrayToRangeBlockVector(v,rangeBlockVector); // perform matrix-vector product A_.mtv(rangeBlockVector,domainBlockVector); A_.mv(domainBlockVector,rangeBlockVector); // get vector w from object of appropriate type rangeBlockVectorToArray(rangeBlockVector,w); }; //! Return number of rows in the matrix inline int nrows () const { return m_; } //! Return number of columns in the matrix inline int ncols () const { return n_; } protected: // Number of rows and columns in each block of the matrix constexpr static int mBlock = BCRSMatrix::block_type::rows; constexpr static int nBlock = BCRSMatrix::block_type::cols; // Type of vectors in the domain of the linear map associated with // the matrix, i.e. block vectors compatible to matrix rows constexpr static int dbvBlockSize = nBlock; typedef Dune::FieldVector DomainBlockVectorBlock; typedef Dune::BlockVector DomainBlockVector; // Type of vectors in the range of the linear map associated with // the matrix, i.e. block vectors compatible to matrix columns constexpr static int rbvBlockSize = mBlock; typedef Dune::FieldVector RangeBlockVectorBlock; typedef Dune::BlockVector RangeBlockVector; // Types for vector index access typedef typename DomainBlockVector::size_type dbv_size_type; typedef typename RangeBlockVector::size_type rbv_size_type; typedef typename DomainBlockVectorBlock::size_type dbvb_size_type; typedef typename RangeBlockVectorBlock::size_type rbvb_size_type; // Get vector v from a block vector object which is compatible to // matrix rows static inline void domainBlockVectorToArray (const DomainBlockVector& dbv, Real* v) { for (dbv_size_type block = 0; block < dbv.N(); ++block) for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock) v[block*dbvBlockSize + iBlock] = dbv[block][iBlock]; } // Get vector v from a block vector object which is compatible to // matrix columns static inline void rangeBlockVectorToArray (const RangeBlockVector& rbv, Real* v) { for (rbv_size_type block = 0; block < rbv.N(); ++block) for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock) v[block*rbvBlockSize + iBlock] = rbv[block][iBlock]; } public: //! Get vector v as a block vector object which is compatible to //! matrix rows static inline void arrayToDomainBlockVector (const Real* v, DomainBlockVector& dbv) { for (dbv_size_type block = 0; block < dbv.N(); ++block) for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock) dbv[block][iBlock] = v[block*dbvBlockSize + iBlock]; } //! Get vector v as a block vector object which is compatible to //! matrix columns static inline void arrayToRangeBlockVector (const Real* v, RangeBlockVector& rbv) { for (rbv_size_type block = 0; block < rbv.N(); ++block) for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock) rbv[block][iBlock] = v[block*rbvBlockSize + iBlock]; } protected: // The DUNE-ISTL BCRSMatrix const BCRSMatrix& A_; // Number of rows and columns in the matrix const int m_, n_; // Auxiliary block vector objects which are // compatible to matrix rows / columns mutable DomainBlockVector domainBlockVector; mutable RangeBlockVector rangeBlockVector; }; /** * \brief A class template for performing some eigenvalue algorithms * provided by the ARPACK++ library which is based on the implicitly * restarted Arnoldi/Lanczos method (IRAM/IRLM), a synthesis of the * Arnoldi/Lanczos process with the implicitily shifted QR technique. * The method is designed to compute eigenvalue-eigenvector pairs of * large scale sparse nonsymmetric/symmetric matrices. This class * template uses the algorithms to compute the dominant (i.e. largest * magnitude) and least dominant (i.e. smallest magnitude) eigenvalue * as well as the spectral condition number of square, symmetric * matrices and to compute the largest and smallest singular value as * well as the spectral condition number of nonsymmetric matrices. * * \note For a recent version of the ARPACK++ library working with recent * compiler versions see "http://reuter.mit.edu/software/arpackpatch/" * or the git repository "https://github.com/m-reuter/arpackpp.git". * * \note Note that the Arnoldi/Lanczos process currently is initialized * using a vector which is randomly generated by ARPACK++. This * could be changed in a future version, since ARPACK++ supports * manual initialization of this vector. * * \todo The current implementation is limited to DUNE-ISTL BCRSMatrix types * with blocklevel 2. An extension to blocklevel >= 2 might be provided * in a future version. * * \todo Maybe make ARPACK++ parameter ncv available to the user. * * \tparam BCRSMatrix Type of a DUNE-ISTL BCRSMatrix whose eigenvalues * respectively singular values shall be considered; * is assumed to have blocklevel 2. * \tparam BlockVector Type of the associated vectors; compatible with the * rows of a BCRSMatrix object (if #rows >= #ncols) or * its columns (if #rows < #ncols). * * \author Sebastian Westerheide. */ template class ArPackPlusPlus_Algorithms { public: typedef typename BlockVector::field_type Real; public: /** * \brief Construct from required parameters. * * \param[in] m The DUNE-ISTL BCRSMatrix whose eigenvalues * resp. singular values shall be considered. * \param[in] nIterationsMax Influences the maximum number of Arnoldi * update iterations allowed; depending on the * algorithm, c*nIterationsMax iterations may * be performed, where c is a natural number. * \param[in] verbosity_level Verbosity setting; * >= 1: algorithms print a preamble and * the final result, * >= 2: algorithms print information about * the problem solved using ARPACK++, * >= 3: the final result output includes * the approximated eigenvector, * >= 4: sets the ARPACK(++) verbosity mode. */ ArPackPlusPlus_Algorithms (const BCRSMatrix& m, const unsigned int nIterationsMax = 100000, const unsigned int verbosity_level = 0) : m_(m), nIterationsMax_(nIterationsMax), verbosity_level_(verbosity_level), nIterations_(0), title_(" ArPackPlusPlus_Algorithms: "), blank_(title_.length(),' ') {} /** * \brief Assume the matrix to be square, symmetric and perform IRLM * to compute an approximation lambda of its dominant * (i.e. largest magnitude) eigenvalue and the corresponding * approximation x of an associated eigenvector. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] lambda The approximated dominant eigenvalue. * \param[out] x The associated approximated eigenvector. */ inline void computeSymMaxMagnitude (const Real& epsilon, BlockVector& x, Real& lambda) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of " << "the dominant eigenvalue of a matrix which " << "is assumed to be symmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A is square if (nrows != ncols) DUNE_THROW(Dune::ISTLError,"Matrix is not square (" << nrows << "x" << ncols << ")."); // allocate memory for variables, set parameters const int nev = 1; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues with largest magnitude char which[] = "LM"; ARSymStdEig dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated dominant eigenvalue of A lambda = ev[nev-1]; // obtain associated approximated eigenvector of A Real* x_raw = dprob.RawEigenvector(nev-1); WrappedMatrix::arrayToDomainBlockVector(x_raw,x); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute residual norm BlockVector r(x); Real* Ax_raw = new Real[nrows]; A.multMv(x_raw,Ax_raw); WrappedMatrix::arrayToDomainBlockVector(Ax_raw,r); r.axpy(-lambda,x); const Real r_norm = r.two_norm(); // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained eigenvalues of A by solving " << "A*x = λ*x using the ARPACK++ class ARSym" << "StdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " dominant eigenvalue of A: " << lambda << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } // free dynamically allocated memory delete[] Ax_raw; delete[] ev; } /** * \brief Assume the matrix to be square, symmetric and perform IRLM * to compute an approximation lambda of its least dominant * (i.e. smallest magnitude) eigenvalue and the corresponding * approximation x of an associated eigenvector. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] lambda The approximated least dominant eigenvalue. * \param[out] x The associated approximated eigenvector. */ inline void computeSymMinMagnitude (const Real& epsilon, BlockVector& x, Real& lambda) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of the " << "least dominant eigenvalue of a matrix which " << "is assumed to be symmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A is square if (nrows != ncols) DUNE_THROW(Dune::ISTLError,"Matrix is not square (" << nrows << "x" << ncols << ")."); // allocate memory for variables, set parameters const int nev = 1; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues with smallest magnitude char which[] = "SM"; ARSymStdEig dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated least dominant eigenvalue of A lambda = ev[nev-1]; // obtain associated approximated eigenvector of A Real* x_raw = dprob.RawEigenvector(nev-1); WrappedMatrix::arrayToDomainBlockVector(x_raw,x); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute residual norm BlockVector r(x); Real* Ax_raw = new Real[nrows]; A.multMv(x_raw,Ax_raw); WrappedMatrix::arrayToDomainBlockVector(Ax_raw,r); r.axpy(-lambda,x); const Real r_norm = r.two_norm(); // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained eigenvalues of A by solving " << "A*x = λ*x using the ARPACK++ class ARSym" << "StdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " least dominant eigenvalue of A: " << lambda << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } // free dynamically allocated memory delete[] Ax_raw; delete[] ev; } /** * \brief Assume the matrix to be square, symmetric and perform IRLM * to compute an approximation of its spectral condition number * which, for symmetric matrices, can be expressed as the ratio * of the dominant eigenvalue's magnitude and the least dominant * eigenvalue's magnitude. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] cond_2 The approximated spectral condition number. */ inline void computeSymCond2 (const Real& epsilon, Real& cond_2) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of the " << "spectral condition number of a matrix which " << "is assumed to be symmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A is square if (nrows != ncols) DUNE_THROW(Dune::ISTLError,"Matrix is not square (" << nrows << "x" << ncols << ")."); // allocate memory for variables, set parameters const int nev = 2; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues from both ends of the spectrum char which[] = "BE"; ARSymStdEig dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated dominant and least dominant eigenvalue of A const Real& lambda_max = ev[nev-1]; const Real& lambda_min = ev[0]; // obtain associated approximated eigenvectors of A Real* x_max_raw = dprob.RawEigenvector(nev-1); Real* x_min_raw = dprob.RawEigenvector(0); // obtain approximated spectral condition number of A cond_2 = std::abs(lambda_max / lambda_min); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute each residual norm Real* Ax_max_raw = new Real[nrows]; Real* Ax_min_raw = new Real[nrows]; A.multMv(x_max_raw,Ax_max_raw); A.multMv(x_min_raw,Ax_min_raw); Real r_max_norm = 0.0; Real r_min_norm = 0.0; for (int i = 0; i < nrows; ++i) { r_max_norm += std::pow(Ax_max_raw[i] - lambda_max * x_max_raw[i],2); r_min_norm += std::pow(Ax_min_raw[i] - lambda_min * x_min_raw[i],2); } r_max_norm = std::sqrt(r_max_norm); r_min_norm = std::sqrt(r_min_norm); // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained eigenvalues of A by solving " << "A*x = λ*x using the ARPACK++ class ARSym" << "StdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " dominant eigenvalue of A: " << lambda_max << std::endl; std::cout << blank_ << " least dominant eigenvalue of A: " << lambda_min << std::endl; std::cout << blank_ << " spectral condition number of A: " << cond_2 << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = {" << r_max_norm << "," << r_min_norm << "}, " << "λ = {" << lambda_max << "," << lambda_min << "}): cond_2 = " << cond_2 << std::endl; } // free dynamically allocated memory delete[] Ax_min_raw; delete[] Ax_max_raw; delete[] ev; } /** * \brief Assume the matrix to be nonsymmetric and perform IRLM * to compute an approximation sigma of its largest * singlar value and the corresponding approximation x of * an associated singular vector. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] sigma The approximated largest singlar value. * \param[out] x The associated approximated right-singular * vector (if #rows >= #ncols) respectively * left-singular vector (if #rows < #ncols). */ inline void computeNonSymMax (const Real& epsilon, BlockVector& x, Real& sigma) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of the " << "largest singular value of a matrix which " << "is assumed to be nonsymmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A^T*A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A has more rows than columns (extend code later to the opposite case!) if (nrows < ncols) DUNE_THROW(Dune::ISTLError,"Matrix has less rows than " << "columns (" << nrows << "x" << ncols << ")." << " This case is not implemented, yet."); // allocate memory for variables, set parameters const int nev = 1; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A^T*A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues with largest algebraic value char which[] = "LA"; ARSymStdEig dprob(ncols, nev, &A, &WrappedMatrix::multMtMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A^T*A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated largest eigenvalue of A^T*A const Real& lambda = ev[nev-1]; // obtain associated approximated eigenvector of A^T*A Real* x_raw = dprob.RawEigenvector(nev-1); WrappedMatrix::arrayToDomainBlockVector(x_raw,x); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute residual norm BlockVector r(x); Real* AtAx_raw = new Real[ncols]; A.multMtMv(x_raw,AtAx_raw); WrappedMatrix::arrayToDomainBlockVector(AtAx_raw,r); r.axpy(-lambda,x); const Real r_norm = r.two_norm(); // calculate largest singular value of A (note that // x is right-singular / left-singular vector of A) sigma = std::sqrt(lambda); // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained singular values of A by sol" << "ving (A^T*A)*x = σ²*x using the ARPACK++ " << "class ARSymStdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A^T*A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " largest eigenvalue of A^T*A: " << lambda << std::endl; std::cout << blank_ << " => largest singular value of A: " << sigma << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "σ = " << sigma << std::endl; if (verbosity_level_ > 2) { // print approximated right-singular / left-singular vector // via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } // free dynamically allocated memory delete[] AtAx_raw; delete[] ev; } /** * \brief Assume the matrix to be nonsymmetric and perform IRLM * to compute an approximation sigma of its smallest * singlar value and the corresponding approximation x of * an associated singular vector. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] sigma The approximated smallest singlar value. * \param[out] x The associated approximated right-singular * vector (if #rows >= #ncols) respectively * left-singular vector (if #rows < #ncols). */ inline void computeNonSymMin (const Real& epsilon, BlockVector& x, Real& sigma) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of the " << "smallest singular value of a matrix which " << "is assumed to be nonsymmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A^T*A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A has more rows than columns (extend code later to the opposite case!) if (nrows < ncols) DUNE_THROW(Dune::ISTLError,"Matrix has less rows than " << "columns (" << nrows << "x" << ncols << ")." << " This case is not implemented, yet."); // allocate memory for variables, set parameters const int nev = 1; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A^T*A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues with smallest algebraic value char which[] = "SA"; ARSymStdEig dprob(ncols, nev, &A, &WrappedMatrix::multMtMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A^T*A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated smallest eigenvalue of A^T*A const Real& lambda = ev[nev-1]; // obtain associated approximated eigenvector of A^T*A Real* x_raw = dprob.RawEigenvector(nev-1); WrappedMatrix::arrayToDomainBlockVector(x_raw,x); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute residual norm BlockVector r(x); Real* AtAx_raw = new Real[ncols]; A.multMtMv(x_raw,AtAx_raw); WrappedMatrix::arrayToDomainBlockVector(AtAx_raw,r); r.axpy(-lambda,x); const Real r_norm = r.two_norm(); // calculate smallest singular value of A (note that // x is right-singular / left-singular vector of A) sigma = std::sqrt(lambda); // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained singular values of A by sol" << "ving (A^T*A)*x = σ²*x using the ARPACK++ " << "class ARSymStdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A^T*A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " smallest eigenvalue of A^T*A: " << lambda << std::endl; std::cout << blank_ << " => smallest singular value of A: " << sigma << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "σ = " << sigma << std::endl; if (verbosity_level_ > 2) { // print approximated right-singular / left-singular vector // via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } // free dynamically allocated memory delete[] AtAx_raw; delete[] ev; } /** * \brief Assume the matrix to be nonsymmetric and perform IRLM * to compute an approximation of its spectral condition * number which can be expressed as the ratio of the * largest singular value and the smallest singular value. * * \param[in] epsilon The target relative accuracy of Ritz values * (0 == machine precision). * \param[out] cond_2 The approximated spectral condition number. */ inline void computeNonSymCond2 (const Real& epsilon, Real& cond_2) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Computing an approximation of the " << "spectral condition number of a matrix which " << "is assumed to be nonsymmetric." << std::endl; // use type ArPackPlusPlus_BCRSMatrixWrapper to store matrix information // and to perform the product A^T*A*v (LU decomposition is not used) typedef ArPackPlusPlus_BCRSMatrixWrapper WrappedMatrix; WrappedMatrix A(m_); // get number of rows and columns in A const int nrows = A.nrows(); const int ncols = A.ncols(); // assert that A has more rows than columns (extend code later to the opposite case!) if (nrows < ncols) DUNE_THROW(Dune::ISTLError,"Matrix has less rows than " << "columns (" << nrows << "x" << ncols << ")." << " This case is not implemented, yet."); // allocate memory for variables, set parameters const int nev = 2; // Number of eigenvalues to compute const int ncv = 20; // Number of Arnoldi vectors generated at each iteration (0 == auto) const Real tol = epsilon; // Stopping tolerance (relative accuracy of Ritz values) (0 == machine precision) const int maxit = nIterationsMax_*nev; // Maximum number of Arnoldi update iterations allowed (0 == 100*nev) Real* ev = new Real[nev]; // Computed eigenvalues of A^T*A const bool ivec = true; // Flag deciding if eigenvectors shall be determined int nconv; // Number of converged eigenvalues // define what we need: eigenvalues from both ends of the spectrum char which[] = "BE"; ARSymStdEig dprob(ncols, nev, &A, &WrappedMatrix::multMtMv, which, ncv, tol, maxit); // set ARPACK verbosity mode if requested if (verbosity_level_ > 3) dprob.Trace(); // find eigenvalues and eigenvectors of A^T*A, obtain the eigenvalues nconv = dprob.Eigenvalues(ev,ivec); // obtain approximated largest and smallest eigenvalue of A^T*A const Real& lambda_max = ev[nev-1]; const Real& lambda_min = ev[0]; // obtain associated approximated eigenvectors of A^T*A Real* x_max_raw = dprob.RawEigenvector(nev-1); Real* x_min_raw = dprob.RawEigenvector(0); // obtain number of Arnoldi update iterations actually taken nIterations_ = dprob.GetIter(); // compute each residual norm Real* AtAx_max_raw = new Real[ncols]; Real* AtAx_min_raw = new Real[ncols]; A.multMtMv(x_max_raw,AtAx_max_raw); A.multMtMv(x_min_raw,AtAx_min_raw); Real r_max_norm = 0.0; Real r_min_norm = 0.0; for (int i = 0; i < ncols; ++i) { r_max_norm += std::pow(AtAx_max_raw[i] - lambda_max * x_max_raw[i],2); r_min_norm += std::pow(AtAx_min_raw[i] - lambda_min * x_min_raw[i],2); } r_max_norm = std::sqrt(r_max_norm); r_min_norm = std::sqrt(r_min_norm); // calculate largest and smallest singular value of A const Real sigma_max = std::sqrt(lambda_max); const Real sigma_min = std::sqrt(lambda_min); // obtain approximated spectral condition number of A cond_2 = sigma_max / sigma_min; // print verbosity information if (verbosity_level_ > 0) { if (verbosity_level_ > 1) { // print some information about the problem std::cout << blank_ << "Obtained singular values of A by sol" << "ving (A^T*A)*x = σ²*x using the ARPACK++ " << "class ARSymStdEig:" << std::endl; std::cout << blank_ << " converged eigenvalues of A^T*A: " << nconv << " / " << nev << std::endl; std::cout << blank_ << " largest eigenvalue of A^T*A: " << lambda_max << std::endl; std::cout << blank_ << " smallest eigenvalue of A^T*A: " << lambda_min << std::endl; std::cout << blank_ << " => largest singular value of A: " << sigma_max << std::endl; std::cout << blank_ << " => smallest singular value of A: " << sigma_min << std::endl; } std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = {" << r_max_norm << "," << r_min_norm << "}, " << "σ = {" << sigma_max << "," << sigma_min << "}): cond_2 = " << cond_2 << std::endl; } // free dynamically allocated memory delete[] AtAx_min_raw; delete[] AtAx_max_raw; delete[] ev; } /** * \brief Return the number of iterations in last application of * an algorithm. */ inline unsigned int getIterationCount () const { if (nIterations_ == 0) DUNE_THROW(Dune::ISTLError,"No algorithm applied, yet."); return nIterations_; } protected: // parameters related to iterative eigenvalue algorithms const BCRSMatrix& m_; const unsigned int nIterationsMax_; // verbosity setting const unsigned int verbosity_level_; // memory for storing temporary variables (mutable as they shall // just be effectless auxiliary variables of the const apply*(...) // methods) mutable unsigned int nIterations_; // constants for printing verbosity information const std::string title_; const std::string blank_; }; } // namespace Dune #endif // HAVE_ARPACKPP #endif // DUNE_ISTL_EIGENVALUE_ARPACKPP_HH dune-istl-2.5.1/dune/istl/eigenvalue/poweriteration.hh000066400000000000000000001260771313314427100230650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_EIGENVALUE_POWERITERATION_HH #define DUNE_ISTL_EIGENVALUE_POWERITERATION_HH #include // provides std::size_t #include // provides std::sqrt, std::abs #include // provides std::is_same #include // provides std::cout, std::endl #include // provides std::numeric_limits #include // provides std::left, std::ios::left #include // provides std::setw, std::resetiosflags #include // provides std::unique_ptr #include // provides std::string #include // provides DUNE_THROW(...) #include // provides Dune::LinearOperator #include // provides Dune::SolverCategory::sequential #include // provides Dune::IsDirectSolver #include // provides Dune::MatrixAdapter #include // provides Dune::ISTLError #include // provides Dune::printvector(...) #include // provides Dune::InverseOperatorResult namespace Dune { /** * \brief A linear operator scaling vectors by a scalar value. * The scalar value can be changed as it is given in a * form decomposed into an immutable and a mutable part. * * \author Sebastian Westerheide. */ template class ScalingLinearOperator : public Dune::LinearOperator { public: typedef X domain_type; typedef Y range_type; typedef typename X::field_type field_type; enum {category = Dune::SolverCategory::sequential}; ScalingLinearOperator (field_type immutable_scaling, const field_type& mutable_scaling) : immutable_scaling_(immutable_scaling), mutable_scaling_(mutable_scaling) {} virtual void apply (const X& x, Y& y) const { y = x; y *= immutable_scaling_*mutable_scaling_; } virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const { X temp(x); temp *= immutable_scaling_*mutable_scaling_; y.axpy(alpha,temp); } protected: const field_type immutable_scaling_; const field_type& mutable_scaling_; }; /** * \brief A linear operator representing the sum of two linear operators. * * \tparam OP1 Type of the first linear operator. * \tparam OP2 Type of the second linear operator. * * \author Sebastian Westerheide. */ template class LinearOperatorSum : public Dune::LinearOperator { public: typedef typename OP1::domain_type domain_type; typedef typename OP1::range_type range_type; typedef typename domain_type::field_type field_type; enum {category = Dune::SolverCategory::sequential}; LinearOperatorSum (const OP1& op1, const OP2& op2) : op1_(op1), op2_(op2) { static_assert(std::is_same::value, "Domain type of both operators doesn't match!"); static_assert(std::is_same::value, "Range type of both operators doesn't match!"); } virtual void apply (const domain_type& x, range_type& y) const { op1_.apply(x,y); op2_.applyscaleadd(1.0,x,y); } virtual void applyscaleadd (field_type alpha, const domain_type& x, range_type& y) const { range_type temp(y); op1_.apply(x,temp); op2_.applyscaleadd(1.0,x,temp); y.axpy(alpha,temp); } protected: const OP1& op1_; const OP2& op2_; }; /** * \brief Helper class for notifying a DUNE-ISTL linear solver about * a change of the iteration matrix object in a unified way, * i.e. independent from the solver's type (direct/iterative). * * \author Sebastian Westerheide. */ template class SolverHelper { public: static void setMatrix (ISTLLinearSolver& solver, const BCRSMatrix& matrix) { static const bool is_direct_solver = Dune::IsDirectSolver::value; SolverHelper:: Implementation::setMatrix(solver,matrix); } protected: /** * \brief Implementation that works together with iterative ISTL * solvers, e.g. Dune::CGSolver or Dune::BiCGSTABSolver. */ template struct Implementation { static void setMatrix (ISTLLinearSolver&, const BCRSMatrix&) {} }; /** * \brief Implementation that works together with direct ISTL * solvers, e.g. Dune::SuperLU or Dune::UMFPack. */ template struct Implementation { static void setMatrix (ISTLLinearSolver& solver, const BCRSMatrix& matrix) { solver.setMatrix(matrix); } }; }; /** * \brief A class template for performing some iterative eigenvalue algorithms * based on power iteration. * * Given a square matrix whose eigenvalues shall be considered, this class * template provides methods for performing the power iteration algorithm, * the inverse iteration algorithm, the inverse iteration with shift algorithm, * the Rayleigh quotient iteration algorithm and the TLIME iteration algorithm. * * \note Note that all algorithms except the power iteration algorithm require * matrix inversion via a linear solver. When using an iterative linear * solver, the algorithms become inexact "inner-outer" iterative methods. * It is known that the number of inner solver iterations can increase * steadily as the outer eigenvalue iteration proceeds. In this case, you * should consider using a "tuned preconditioner", see e.g. [Freitag and * Spence, 2008]. * * \note In the current implementation, preconditioners like Dune::SeqILUn * which are based on matrix decomposition act on the initial iteration * matrix in each iteration, even for methods like the Rayleigh quotient * algorithm in which the iteration matrix (m_ - mu_*I) may change in * each iteration. This is due to the fact that those preconditioners * currently don't support to be notified about a change of the matrix * object. * * \todo The current implementation is limited to DUNE-ISTL BCRSMatrix types * with blocklevel 2. An extension to blocklevel >= 2 might be provided * in a future version. * * \tparam BCRSMatrix Type of a DUNE-ISTL BCRSMatrix whose eigenvalues * shall be considered; is assumed to have blocklevel * 2 with square blocks. * \tparam BlockVector Type of the associated vectors; compatible with * the rows of a BCRSMatrix object and its columns. * * \author Sebastian Westerheide. */ template class PowerIteration_Algorithms { protected: // Type definitions for type of iteration operator (m_ - mu_*I) typedef typename Dune::MatrixAdapter MatrixOperator; typedef ScalingLinearOperator ScalingOperator; typedef LinearOperatorSum OperatorSum; public: //! Type of underlying field typedef typename BlockVector::field_type Real; //! Type of iteration operator (m_ - mu_*I) typedef OperatorSum IterationOperator; public: /** * \brief Construct from required parameters. * * \param[in] m The square DUNE-ISTL BCRSMatrix whose * eigenvalues shall be considered. * \param[in] nIterationsMax The maximum number of iterations allowed. * \param[in] verbosity_level Verbosity setting; * >= 1: algorithms print a preamble and * the final result, * >= 2: algorithms print information on * each iteration, * >= 3: the final result output includes * the approximated eigenvector. */ PowerIteration_Algorithms (const BCRSMatrix& m, const unsigned int nIterationsMax = 1000, const unsigned int verbosity_level = 0) : m_(m), nIterationsMax_(nIterationsMax), verbosity_level_(verbosity_level), mu_(0.0), matrixOperator_(m_), scalingOperator_(-1.0,mu_), itOperator_(matrixOperator_,scalingOperator_), nIterations_(0), title_(" PowerIteration_Algorithms: "), blank_(title_.length(),' ') { // assert that BCRSMatrix type has blocklevel 2 static_assert (BCRSMatrix::blocklevel == 2, "Only BCRSMatrices with blocklevel 2 are supported."); // assert that BCRSMatrix type has square blocks static_assert (BCRSMatrix::block_type::rows == BCRSMatrix::block_type::cols, "Only BCRSMatrices with square blocks are supported."); // assert that m_ is square const int nrows = m_.M() * BCRSMatrix::block_type::rows; const int ncols = m_.N() * BCRSMatrix::block_type::cols; if (nrows != ncols) DUNE_THROW(Dune::ISTLError,"Matrix is not square (" << nrows << "x" << ncols << ")."); } //! disallow copying (default copy constructor does a shallow copy, //! if copying was required a deep copy would have to be implemented //! due to member variables which hold a dynamically allocated object) PowerIteration_Algorithms (const PowerIteration_Algorithms&) = delete; //! disallow copying (default assignment operator does a shallow copy, //! if copying was required a deep copy would have to be implemented //! due to member variables which hold a dynamically allocated object) PowerIteration_Algorithms& operator= (const PowerIteration_Algorithms&) = delete; /** * \brief Perform the power iteration algorithm to compute an approximation * lambda of the dominant (i.e. largest magnitude) eigenvalue and * the corresponding approximation x of an associated eigenvector. * * \param[in] epsilon The target residual norm. * \param[out] lambda The approximated dominant eigenvalue. * \param[in,out] x The associated approximated eigenvector; * shall be initialized with an estimate * for an eigenvector associated with the * eigenvalue which shall be approximated. */ inline void applyPowerIteration (const Real& epsilon, BlockVector& x, Real& lambda) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Performing power iteration approximating " << "the dominant eigenvalue." << std::endl; // allocate memory for auxiliary variables BlockVector y(x); BlockVector temp(x); // perform power iteration x *= (1.0 / x.two_norm()); m_.mv(x,y); Real r_norm = std::numeric_limits::max(); nIterations_ = 0; while (r_norm > epsilon) { // update and check number of iterations if (++nIterations_ > nIterationsMax_) DUNE_THROW(Dune::ISTLError,"Power iteration did not converge " << "in " << nIterationsMax_ << " iterations " << "(â•‘residualâ•‘_2 = " << r_norm << ", epsilon = " << epsilon << ")."); // do one iteration of the power iteration algorithm // (use that y = m_ * x) x = y; x *= (1.0 / y.two_norm()); // get approximated eigenvalue lambda via the Rayleigh quotient m_.mv(x,y); lambda = x * y; // get norm of residual (use that y = m_ * x) temp = y; temp.axpy(-lambda,x); r_norm = temp.two_norm(); // print verbosity information if (verbosity_level_ > 1) std::cout << blank_ << std::left << "iteration " << std::setw(3) << nIterations_ << " (â•‘residualâ•‘_2 = " << std::setw(11) << r_norm << "): λ = " << lambda << std::endl << std::resetiosflags(std::ios::left); } // print verbosity information if (verbosity_level_ > 0) { std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } } /** * \brief Perform the inverse iteration algorithm to compute an approximation * lambda of the least dominant (i.e. smallest magnitude) eigenvalue * and the corresponding approximation x of an associated eigenvector. * * \tparam ISTLLinearSolver Type of a DUNE-ISTL InverseOperator * which shall be used as a linear solver. * \tparam avoidLinSolverCrime The less accurate the linear solver is, * the more corrupted gets the implemented * computation of lambda and its associated * residual. Setting this mode can help * increasing their accuracy at the cost of * a bit of efficiency which is beneficial * e.g. when using a very inexact linear * solver. Defaults to false. * * \param[in] epsilon The target residual norm. * \param[in] solver The DUNE-ISTL InverseOperator which shall * be used as a linear solver; is assumed to * be constructed using the linear operator * returned by getIterationOperator() (resp. * matrix returned by getIterationMatrix()). * \param[out] lambda The approximated least dominant eigenvalue. * \param[in,out] x The associated approximated eigenvector; * shall be initialized with an estimate * for an eigenvector associated with the * eigenvalue which shall be approximated. */ template inline void applyInverseIteration (const Real& epsilon, ISTLLinearSolver& solver, BlockVector& x, Real& lambda) const { constexpr Real gamma = 0.0; applyInverseIteration(gamma,epsilon,solver,x,lambda); } /** * \brief Perform the inverse iteration with shift algorithm to compute an * approximation lambda of the eigenvalue closest to a given shift * and the corresponding approximation x of an associated eigenvector. * * \tparam ISTLLinearSolver Type of a DUNE-ISTL InverseOperator * which shall be used as a linear solver. * \tparam avoidLinSolverCrime The less accurate the linear solver is, * the more corrupted gets the implemented * computation of lambda and its associated * residual. Setting this mode can help * increasing their accuracy at the cost of * a bit of efficiency which is beneficial * e.g. when using a very inexact linear * solver. Defaults to false. * * \param[in] gamma The shift. * \param[in] epsilon The target residual norm. * \param[in] solver The DUNE-ISTL InverseOperator which shall * be used as a linear solver; is assumed to * be constructed using the linear operator * returned by getIterationOperator() (resp. * matrix returned by getIterationMatrix()). * \param[out] lambda The approximated eigenvalue closest to gamma. * \param[in,out] x The associated approximated eigenvector; * shall be initialized with an estimate * for an eigenvector associated with the * eigenvalue which shall be approximated. */ template inline void applyInverseIteration (const Real& gamma, const Real& epsilon, ISTLLinearSolver& solver, BlockVector& x, Real& lambda) const { // print verbosity information if (verbosity_level_ > 0) { std::cout << title_; if (gamma == 0.0) std::cout << "Performing inverse iteration approximating " << "the least dominant eigenvalue." << std::endl; else std::cout << "Performing inverse iteration with shift " << "gamma = " << gamma << " approximating the " << "eigenvalue closest to gamma." << std::endl; } // initialize iteration operator, // initialize iteration matrix when needed updateShiftMu(gamma,solver); // allocate memory for linear solver statistics Dune::InverseOperatorResult solver_statistics; // allocate memory for auxiliary variables BlockVector y(x); Real y_norm; BlockVector temp(x); // perform inverse iteration with shift x *= (1.0 / x.two_norm()); Real r_norm = std::numeric_limits::max(); nIterations_ = 0; while (r_norm > epsilon) { // update and check number of iterations if (++nIterations_ > nIterationsMax_) DUNE_THROW(Dune::ISTLError,"Inverse iteration " << (gamma != 0.0 ? "with shift " : "") << "did not " << "converge in " << nIterationsMax_ << " iterations " << "(â•‘residualâ•‘_2 = " << r_norm << ", epsilon = " << epsilon << ")."); // do one iteration of the inverse iteration with shift algorithm, // part 1: solve (m_ - gamma*I) * y = x for y // (protect x from being changed) temp = x; solver.apply(y,temp,solver_statistics); // get norm of y y_norm = y.two_norm(); // compile time switch between accuracy and efficiency if (avoidLinSolverCrime) { // get approximated eigenvalue lambda via the Rayleigh quotient // (use that x_new = y / y_norm) m_.mv(y,temp); lambda = (y * temp) / (y_norm * y_norm); // get norm of residual // (use that x_new = y / y_norm, additionally use that temp = m_ * y) temp.axpy(-lambda,y); r_norm = temp.two_norm() / y_norm; } else { // get approximated eigenvalue lambda via the Rayleigh quotient // (use that x_new = y / y_norm and use that (m_ - gamma*I) * y = x) lambda = gamma + (y * x) / (y_norm * y_norm); // get norm of residual // (use that x_new = y / y_norm and use that (m_ - gamma*I) * y = x) temp = x; temp.axpy(gamma-lambda,y); r_norm = temp.two_norm() / y_norm; } // do one iteration of the inverse iteration with shift algorithm, // part 2: update x x = y; x *= (1.0 / y_norm); // print verbosity information if (verbosity_level_ > 1) std::cout << blank_ << std::left << "iteration " << std::setw(3) << nIterations_ << " (â•‘residualâ•‘_2 = " << std::setw(11) << r_norm << "): λ = " << lambda << std::endl << std::resetiosflags(std::ios::left); } // print verbosity information if (verbosity_level_ > 0) { std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } } /** * \brief Perform the Rayleigh quotient iteration algorithm to compute * an approximation lambda of an eigenvalue and the corresponding * approximation x of an associated eigenvector. * * \tparam ISTLLinearSolver Type of a DUNE-ISTL InverseOperator * which shall be used as a linear solver. * \tparam avoidLinSolverCrime The less accurate the linear solver is, * the more corrupted gets the implemented * computation of lambda and its associated * residual. Setting this mode can help * increasing their accuracy at the cost of * a bit of efficiency which is beneficial * e.g. when using a very inexact linear * solver. Defaults to false. * * \param[in] epsilon The target residual norm. * \param[in] solver The DUNE-ISTL InverseOperator which shall * be used as a linear solver; is assumed to * be constructed using the linear operator * returned by getIterationOperator() (resp. * matrix returned by getIterationMatrix()). * \param[in,out] lambda The approximated eigenvalue; * shall be initialized with an estimate for * the eigenvalue which shall be approximated. * \param[in,out] x The associated approximated eigenvector; * shall be initialized with an estimate * for an eigenvector associated with the * eigenvalue which shall be approximated. */ template inline void applyRayleighQuotientIteration (const Real& epsilon, ISTLLinearSolver& solver, BlockVector& x, Real& lambda) const { // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Performing Rayleigh quotient iteration for " << "estimated eigenvalue " << lambda << "." << std::endl; // allocate memory for linear solver statistics Dune::InverseOperatorResult solver_statistics; // allocate memory for auxiliary variables BlockVector y(x); Real y_norm; Real lambda_update; BlockVector temp(x); // perform Rayleigh quotient iteration x *= (1.0 / x.two_norm()); Real r_norm = std::numeric_limits::max(); nIterations_ = 0; while (r_norm > epsilon) { // update and check number of iterations if (++nIterations_ > nIterationsMax_) DUNE_THROW(Dune::ISTLError,"Rayleigh quotient iteration did not " << "converge in " << nIterationsMax_ << " iterations " << "(â•‘residualâ•‘_2 = " << r_norm << ", epsilon = " << epsilon << ")."); // update iteration operator, // update iteration matrix when needed updateShiftMu(lambda,solver); // do one iteration of the Rayleigh quotient iteration algorithm, // part 1: solve (m_ - lambda*I) * y = x for y // (protect x from being changed) temp = x; solver.apply(y,temp,solver_statistics); // get norm of y y_norm = y.two_norm(); // compile time switch between accuracy and efficiency if (avoidLinSolverCrime) { // get approximated eigenvalue lambda via the Rayleigh quotient // (use that x_new = y / y_norm) m_.mv(y,temp); lambda = (y * temp) / (y_norm * y_norm); // get norm of residual // (use that x_new = y / y_norm, additionally use that temp = m_ * y) temp.axpy(-lambda,y); r_norm = temp.two_norm() / y_norm; } else { // get approximated eigenvalue lambda via the Rayleigh quotient // (use that x_new = y / y_norm and use that (m_ - lambda_old*I) * y = x) lambda_update = (y * x) / (y_norm * y_norm); lambda += lambda_update; // get norm of residual // (use that x_new = y / y_norm and use that (m_ - lambda_old*I) * y = x) temp = x; temp.axpy(-lambda_update,y); r_norm = temp.two_norm() / y_norm; } // do one iteration of the Rayleigh quotient iteration algorithm, // part 2: update x x = y; x *= (1.0 / y_norm); // print verbosity information if (verbosity_level_ > 1) std::cout << blank_ << std::left << "iteration " << std::setw(3) << nIterations_ << " (â•‘residualâ•‘_2 = " << std::setw(11) << r_norm << "): λ = " << lambda << std::endl << std::resetiosflags(std::ios::left); } // print verbosity information if (verbosity_level_ > 0) { std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } } /** * \brief Perform the "two-level iterative method for eigenvalue calculations * (TLIME)" iteration algorithm presented in [Szyld, 1988] to compute * an approximation lambda of an eigenvalue and the corresponding * approximation x of an associated eigenvector. * * The algorithm combines the inverse iteration with shift and the Rayleigh * quotient iteration in order to compute an eigenvalue in a given interval * J = (gamma - eta, gamma + eta). It guarantees that if an eigenvalue exists * in J, the method will converge to an eigenvalue in J, while exploiting * the cubic convergence of the Rayleigh quotient iteration, but without its * drawback that - depending on the initial vector - it can converge to an * arbitrary eigenvalue of the matrix. When J is free of eigenvalues, the * method will determine this fact and converge linearly to the eigenvalue * closest to J. * * \tparam ISTLLinearSolver Type of a DUNE-ISTL InverseOperator * which shall be used as a linear solver. * \tparam avoidLinSolverCrime The less accurate the linear solver is, * the more corrupted gets the implemented * computation of lambda and its associated * residual. Setting this mode can help * increasing their accuracy at the cost of * a bit of efficiency which is beneficial * e.g. when using a very inexact linear * solver. Defaults to false. * * \param[in] gamma An estimate for the eigenvalue which shall * be approximated. * \param[in] eta Radius around gamma in which the eigenvalue * is expected. * \param[in] epsilon The target norm of the residual with respect * to the Rayleigh quotient. * \param[in] solver The DUNE-ISTL InverseOperator which shall * be used as a linear solver; is assumed to * be constructed using the linear operator * returned by getIterationOperator() (resp. * matrix returned by getIterationMatrix()). * \param[in] delta The target relative change of the Rayleigh * quotient, indicating that inverse iteration * has become stationary and switching to Rayleigh * quotient iteration is appropriate; is only * considered if J is free of eigenvalues. * \param[in] m The minimum number of inverse iterations before * switching to Rayleigh quotient iteration; is * only considered if J is free of eigenvalues. * \param[out] extrnl If true, the interval J is free of eigenvalues; * the approximated eigenvalue-eigenvector pair * (lambda,x_s) then corresponds to the eigenvalue * closest to J. * \param[out] lambda The approximated eigenvalue. * \param[in,out] x The associated approximated eigenvector; * shall be initialized with an estimate * for an eigenvector associated with the * eigenvalue which shall be approximated. */ template inline void applyTLIMEIteration (const Real& gamma, const Real& eta, const Real& epsilon, ISTLLinearSolver& solver, const Real& delta, const std::size_t& m, bool& extrnl, BlockVector& x, Real& lambda) const { // use same variable names as in [Szyld, 1988] BlockVector& x_s = x; Real& mu_s = lambda; // print verbosity information if (verbosity_level_ > 0) std::cout << title_ << "Performing TLIME iteration for " << "estimated eigenvalue in the " << "interval (" << gamma - eta << "," << gamma + eta << ")." << std::endl; // allocate memory for linear solver statistics Dune::InverseOperatorResult solver_statistics; // allocate memory for auxiliary variables bool doRQI; Real mu; BlockVector y(x_s); Real omega; Real mu_s_old; Real mu_s_update; BlockVector temp(x_s); Real q_norm, r_norm; // perform TLIME iteration x_s *= (1.0 / x_s.two_norm()); extrnl = true; doRQI = false; r_norm = std::numeric_limits::max(); nIterations_ = 0; while (r_norm > epsilon) { // update and check number of iterations if (++nIterations_ > nIterationsMax_) DUNE_THROW(Dune::ISTLError,"TLIME iteration did not " << "converge in " << nIterationsMax_ << " iterations (â•‘residualâ•‘_2 = " << r_norm << ", epsilon = " << epsilon << ")."); // set shift for next iteration according to inverse iteration // with shift (II) resp. Rayleigh quotient iteration (RQI) if (doRQI) mu = mu_s; else mu = gamma; // update II/RQI iteration operator, // update II/RQI iteration matrix when needed updateShiftMu(mu,solver); // do one iteration of the II/RQI algorithm, // part 1: solve (m_ - mu*I) * y = x for y temp = x_s; solver.apply(y,temp,solver_statistics); // do one iteration of the II/RQI algorithm, // part 2: compute omega omega = (1.0 / y.two_norm()); // backup the old Rayleigh quotient mu_s_old = mu_s; // compile time switch between accuracy and efficiency if (avoidLinSolverCrime) { // update the Rayleigh quotient mu_s, i.e. the approximated eigenvalue // (use that x_new = y * omega) m_.mv(y,temp); mu_s = (y * temp) * (omega * omega); // get norm of "the residual with respect to the shift used by II", // use normal representation of q // (use that x_new = y * omega, use that temp = m_ * y) temp.axpy(-gamma,y); q_norm = temp.two_norm() * omega; // get norm of "the residual with respect to the Rayleigh quotient" r_norm = q_norm*q_norm - (gamma-mu_s)*(gamma-mu_s); // prevent that truncation errors invalidate the norm // (we don't want to calculate sqrt of a negative number) if (r_norm >= 0) { // use relation between the norms of r and q for efficiency r_norm = std::sqrt(r_norm); } else { // use relation between r and q // (use that x_new = y * omega, use that temp = (m_ - gamma*I) * y = q / omega) temp.axpy(gamma-mu_s,y); r_norm = temp.two_norm() * omega; } } else { // update the Rayleigh quotient mu_s, i.e. the approximated eigenvalue if (!doRQI) { // (use that x_new = y * omega, additionally use that (m_ - gamma*I) * y = x_s) mu_s = gamma + (y * x_s) * (omega * omega); } else { // (use that x_new = y * omega, additionally use that (m_ - mu_s_old*I) * y = x_s) mu_s_update = (y * x_s) * (omega * omega); mu_s += mu_s_update; } // get norm of "the residual with respect to the shift used by II" if (!doRQI) { // use special representation of q in the II case // (use that x_new = y * omega, additionally use that (m_ - gamma*I) * y = x_s) q_norm = omega; } else { // use special representation of q in the RQI case // (use that x_new = y * omega, additionally use that (m_ - mu_s_old*I) * y = x_s) temp = x_s; temp.axpy(mu_s-gamma,y); q_norm = temp.two_norm() * omega; } // get norm of "the residual with respect to the Rayleigh quotient" // don't use efficient relation between the norms of r and q, as // this relation seems to yield a less accurate r_norm in the case // where linear solver crime is admitted if (!doRQI) { // (use that x_new = y * omega and use that (m_ - gamma*I) * y = x_s) temp = x_s; temp.axpy(gamma-lambda,y); r_norm = temp.two_norm() * omega; } else { // (use that x_new = y * omega and use that (m_ - mu_s_old*I) * y = x_s) temp = x_s; temp.axpy(-mu_s_update,y); r_norm = temp.two_norm() * omega; } } // do one iteration of the II/RQI algorithm, // part 3: update x x_s = y; x_s *= omega; // // for relative residual norm mode, scale with mu_s^{-1} // r_norm /= std::abs(mu_s); // print verbosity information if (verbosity_level_ > 1) std::cout << blank_ << "iteration " << std::left << std::setw(3) << nIterations_ << " (" << (doRQI ? "RQI," : "II, ") << " " << (doRQI ? "—>" : " ") << " " << "â•‘râ•‘_2 = " << std::setw(11) << r_norm << ", " << (doRQI ? " " : "—>") << " " << "â•‘qâ•‘_2 = " << std::setw(11) << q_norm << "): λ = " << lambda << std::endl << std::resetiosflags(std::ios::left); // check if the eigenvalue closest to gamma lies in J if (!doRQI && q_norm < eta) { // J is not free of eigenvalues extrnl = false; // by theory we know now that mu_s also lies in J assert(std::abs(mu_s-gamma) < eta); // switch to RQI doRQI = true; } // revert to II if J is not free of eigenvalues but // at some point mu_s falls back again outside J if (!extrnl && doRQI && std::abs(mu_s-gamma) >= eta) doRQI = false; // if eigenvalue closest to gamma does not lie in J use RQI // solely to accelerate the convergence to this eigenvalue // when II has become stationary if (extrnl && !doRQI) { // switch to RQI if the relative change of the Rayleigh // quotient indicates that II has become stationary if (nIterations_ >= m && std::abs(mu_s - mu_s_old) / std::abs(mu_s) < delta) doRQI = true; } } // // compute final residual and lambda again (paranoia....) // m_.mv(x_s,temp); // mu_s = x_s * temp; // temp.axpy(-mu_s,x_s); // r_norm = temp.two_norm(); // // r_norm /= std::abs(mu_s); // print verbosity information if (verbosity_level_ > 0) { if (extrnl) std::cout << blank_ << "Interval " << "(" << gamma - eta << "," << gamma + eta << ") is free of eigenvalues, approximating " << "the closest eigenvalue." << std::endl; std::cout << blank_ << "Result (" << "#iterations = " << nIterations_ << ", " << "â•‘residualâ•‘_2 = " << r_norm << "): " << "λ = " << lambda << std::endl; if (verbosity_level_ > 2) { // print approximated eigenvector via DUNE-ISTL I/O methods Dune::printvector(std::cout,x,blank_+"x",blank_+"row"); } } } /** * \brief Return the iteration operator (m_ - mu_*I). * * The linear operator returned by this method shall be used * to create the linear solver object. For linear solvers or * preconditioners which require that the matrix is provided * explicitly use getIterationMatrix() instead/additionally. */ inline IterationOperator& getIterationOperator () { // return iteration operator return itOperator_; } /** * \brief Return the iteration matrix (m_ - mu_*I), provided * on demand when needed (e.g. for direct solvers or * preconditioning). * * The matrix returned by this method shall be used to create * the linear solver object if it requires that the matrix is * provided explicitly. For linear solvers which operate * completely matrix free use getIterationOperator() instead. * * \note Calling this method creates a new DUNE-ISTL * BCRSMatrix object which requires as much memory as * the matrix whose eigenvalues shall be considered. */ inline const BCRSMatrix& getIterationMatrix () const { // create iteration matrix on demand if (!itMatrix_) itMatrix_ = std::unique_ptr(new BCRSMatrix(m_)); // return iteration matrix return *itMatrix_; } /** * \brief Return the number of iterations in last application * of an algorithm. */ inline unsigned int getIterationCount () const { if (nIterations_ == 0) DUNE_THROW(Dune::ISTLError,"No algorithm applied, yet."); return nIterations_; } protected: /** * \brief Update shift mu_, i.e. update iteration operator/matrix * (m_ - mu_*I). * * \note Does nothing if new shift equals the old one. * * \tparam ISTLLinearSolver Type of a DUNE-ISTL InverseOperator * which is used as a linear solver. * * \param[in] mu The new shift. * \param[in] solver The DUNE-ISTL InverseOperator which is used * as a linear solver. * */ template inline void updateShiftMu (const Real& mu, ISTLLinearSolver& solver) const { // do nothing if new shift equals the old one if (mu == mu_) return; // update shift mu_, i.e. update iteration operator mu_ = mu; // update iteration matrix when needed if (itMatrix_) { // iterate over entries in iteration matrix diagonal constexpr int rowBlockSize = BCRSMatrix::block_type::rows; constexpr int colBlockSize = BCRSMatrix::block_type::cols; for (typename BCRSMatrix::size_type i = 0; i < itMatrix_->M()*rowBlockSize; ++i) { // access m_[i,i] where i is the flat index of a row/column const Real& m_entry = m_ [i/rowBlockSize][i/colBlockSize][i%rowBlockSize][i%colBlockSize]; // access *itMatrix[i,i] where i is the flat index of a row/column Real& entry = (*itMatrix_) [i/rowBlockSize][i/colBlockSize][i%rowBlockSize][i%colBlockSize]; // change current entry in iteration matrix diagonal entry = m_entry - mu_; } // notify linear solver about change of the iteration matrix object SolverHelper::setMatrix (solver,*itMatrix_); } } protected: // parameters related to iterative eigenvalue algorithms const BCRSMatrix& m_; const unsigned int nIterationsMax_; // verbosity setting const unsigned int verbosity_level_; // shift mu_ used by iteration operator/matrix (m_ - mu_*I) mutable Real mu_; // iteration operator (m_ - mu_*I), passing shift mu_ by reference const MatrixOperator matrixOperator_; const ScalingOperator scalingOperator_; OperatorSum itOperator_; // iteration matrix (m_ - mu_*I), provided on demand when needed // (e.g. for preconditioning) mutable std::unique_ptr itMatrix_; // memory for storing temporary variables (mutable as they shall // just be effectless auxiliary variables of the const apply*(...) // methods) mutable unsigned int nIterations_; // constants for printing verbosity information const std::string title_; const std::string blank_; }; } // namespace Dune #endif // DUNE_ISTL_EIGENVALUE_POWERITERATION_HH dune-istl-2.5.1/dune/istl/eigenvalue/test/000077500000000000000000000000001313314427100204335ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/eigenvalue/test/CMakeLists.txt000066400000000000000000000013571313314427100232010ustar00rootroot00000000000000add_executable(poweriterationtest cond2test.cc) target_link_libraries(poweriterationtest dunecommon) dune_add_test( TARGET poweriterationtest CMD_ARGS 40) if(SUPERLU_FOUND) add_executable(poweriterationsuperlutest cond2test.cc) add_dune_superlu_flags(poweriterationsuperlutest) dune_add_test( TARGET poweriterationsuperlutest CMD_ARGS 40) target_link_libraries(poweriterationsuperlutest dunecommon) endif() if(ARPACKPP_FOUND) add_executable(arpackpptest cond2test.cc) add_dune_arpackpp_flags(arpackpptest) target_link_libraries(arpackpptest dunecommon) dune_add_test(TARGET arpackpptest) endif() if(ARPACKPP_FOUND AND SUPERLU_FOUND) dune_add_test(NAME arpackppsuperlutest SOURCES cond2test.cc) endif() dune-istl-2.5.1/dune/istl/eigenvalue/test/cond2test.cc000066400000000000000000000026571313314427100226610ustar00rootroot00000000000000#include #include #include #include #include #include #include "../../test/laplacian.hh" #include "matrixinfo.hh" int main (int argc, char** argv) { try { typedef double FIELD_TYPE; static const int BS = 1; std::size_t N = 60; if (argc > 1) N = atoi(argv[1]); std::cout << "testing for N = " << N << ", BS = " << BS << std::endl; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; BCRSMat mat; setupLaplacian(mat,N); Dune::Timer watch; const bool verbose = true; const unsigned int arppp_a_verbosity_level = 2; const unsigned int pia_verbosity_level = 1; MatrixInfo matrixInfo (mat,verbose,arppp_a_verbosity_level,pia_verbosity_level); watch.reset(); matrixInfo.getCond2(true); std::cout << "computation of condition number took " << watch.elapsed() <<" seconds" << std::endl; watch.reset(); matrixInfo.getCond2(false); std::cout << "computation of condition number took " << watch.elapsed() <<" seconds" << std::endl; return 0; } catch (std::exception& e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Unknown exception thrown!" << std::endl; return 1; } } dune-istl-2.5.1/dune/istl/eigenvalue/test/matrixinfo.hh000066400000000000000000000345521313314427100231450ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_EIGENVALUE_TEST_MATRIXINFO_HH #define DUNE_ISTL_EIGENVALUE_TEST_MATRIXINFO_HH #include // provides std::abs and std::sqrt #include // provides assert #include // provides std::cout, std::endl #include // provides DUNE_THROW(...), Dune::Exception #include // provides Dune::FieldVector #include // provides Dune::BlockVector #include // provides Dune::SuperLU #include // provides Dune::SeqGS #include // provides Dune::BiCGSTABSolver #include // provides Dune::transposeMatMultMat(...) #include "../arpackpp.hh" // provides Dune::ArPackPlusPlus_Algorithms #include "../poweriteration.hh" // provides Dune::PowerIteration_Algorithms /** * \brief Class template which yields information related to a square * matrix like its spectral (i.e. 2-norm) condition number. * * \todo The current implementation is limited to DUNE-ISTL * BCRSMatrix types with blocklevel 2. An extension to * blocklevel >= 2 might be provided in a future version. * * \tparam BCRSMatrix Type of a DUNE-ISTL BCRSMatrix whose properties * shall be considered; is assumed to have blocklevel * 2 with square blocks. * * \author Sebastian Westerheide. */ template class MatrixInfo { public: //! Type of the underlying field of the matrix typedef typename BCRSMatrix::field_type Real; public: /** * \brief Construct from required parameters. * * \param[in] m The DUNE-ISTL BCRSMatrix * whose properties shall be * considered; is assumed to * be square. * \param[in] verbose Verbosity setting. * \param[in] arppp_a_verbosity_level Verbosity setting of the * underlying ARPACK++ algorithms. * \param[in] pia_verbosity_level Verbosity setting of the * underlying power iteration * based algorithms. */ MatrixInfo (const BCRSMatrix& m, const bool verbose = false, const unsigned int arppp_a_verbosity_level = 0, const unsigned int pia_verbosity_level = 0) : m_(m), verbose_(verbose), arppp_a_verbosity_level_(arppp_a_verbosity_level*verbose), pia_verbosity_level_(pia_verbosity_level*verbose), cond_2_(-1.0), symmetricity_assumed_(false) { // assert that BCRSMatrix type has blocklevel 2 static_assert (BCRSMatrix::blocklevel == 2, "Only BCRSMatrices with blocklevel 2 are supported."); // assert that BCRSMatrix type has square blocks static_assert (BCRSMatrix::block_type::rows == BCRSMatrix::block_type::cols, "Only BCRSMatrices with square blocks are supported."); // assert that m_ is square const int nrows = m_.M() * BCRSMatrix::block_type::rows; const int ncols = m_.N() * BCRSMatrix::block_type::cols; if (nrows != ncols) DUNE_THROW(Dune::Exception,"Matrix is not square (" << nrows << "x" << ncols << ")."); } //! return spectral (i.e. 2-norm) condition number of the matrix inline Real getCond2 (const bool assume_symmetric = true) const { if (cond_2_ == -1.0 || symmetricity_assumed_ != assume_symmetric) { if (verbose_) std::cout << " MatrixInfo: Computing 2-norm condition number" << (assume_symmetric ? " (assuming that matrix is symmetric)." : ".") << std::endl; if (assume_symmetric) cond_2_ = computeSymCond2(); // assume that m_ is symmetric else cond_2_ = computeNonSymCond2(); // don't assume that m_ is symmetric symmetricity_assumed_ = assume_symmetric; } return cond_2_; } protected: //! Type of block vectors compatible with the rows of a BCRSMatrix //! object and its columns static const int bvBlockSize = BCRSMatrix::block_type::rows; typedef Dune::FieldVector BlockVectorBlock; typedef Dune::BlockVector BlockVector; protected: //! compute spectral (i.e. 2-norm) condition number of the matrix, //! while assuming that it is symmetric such that its largest/smallest //! magnitude eigenvalue can be used instead of its largest/smallest //! singular value to compute the spectral condition number inline Real computeSymCond2 () const { // 1) allocate memory for largest and smallest magnitude eigenvalue // as well as the spectral (i.e. 2-norm) condition number Real lambda_max, lambda_min, cond_2; // 2) allocate memory for starting vectors and approximated // eigenvectors BlockVector x(m_.M()); #if HAVE_ARPACKPP // 3) setup ARPACK++ eigenvalue algorithms typedef Dune::ArPackPlusPlus_Algorithms ARPPP_A; const ARPPP_A arppp_a(m_,100000,arppp_a_verbosity_level_); #endif // HAVE_ARPACKPP // 4) setup power iteration based iterative eigenvalue algorithms typedef Dune::PowerIteration_Algorithms PIA; PIA pia(m_,20000,pia_verbosity_level_); static const bool avoidLinSolverCrime = true; #if HAVE_SUPERLU // 5) select a linear solver for power iteration based iterative // eigenvalue algorithms typedef Dune::SuperLU PIALS; const unsigned int piaLS_verbosity = 0; PIALS piaLS(pia.getIterationMatrix(),piaLS_verbosity); #else // 5) select a linear solver for power iteration based iterative // eigenvalue algorithms typedef Dune::SeqGS PIAPC; PIAPC piaPC(pia.getIterationMatrix(),2,1.0); const double piaLS_reduction = 1e-02; const unsigned int piaLS_max_iter = 1000; const unsigned int piaLS_verbosity = 0; typedef Dune::BiCGSTABSolver PIALS; PIALS piaLS(pia.getIterationOperator(),piaPC, piaLS_reduction,piaLS_max_iter,piaLS_verbosity); #endif // HAVE_SUPERLU #if HAVE_ARPACKPP // 6) get largest magnitude eigenvalue via ARPACK++ // (assume that m_ is symmetric) { const Real epsilon = 0.0; // x = 1.0; (not supported yet) arppp_a.computeSymMaxMagnitude(epsilon,x,lambda_max); } #else // 6) get largest magnitude eigenvalue via a combination of // power and TLIME iteration (assume that m_ is symmetric) { const Real epsilonPI = 1e-02; const Real epsilonTLIME = 1e-08; x = 1.0; // 6.1) perform power iteration for largest magnitude // eigenvalue (predictor) pia.applyPowerIteration(epsilonPI,x,lambda_max); // 6.2) perform TLIME iteration to improve result (corrector) const Real gamma = m_.infinity_norm(); const Real eta = 0.0; const Real delta = 1e-03; bool external; pia.template applyTLIMEIteration (gamma,eta,epsilonTLIME,piaLS,delta,2,external,x,lambda_max); assert(external); } #endif // HAVE_ARPACKPP // 7) get smallest magnitude eigenvalue via TLIME iteration // (assume that m_ is symmetric) { const Real epsilon = 1e-11; x = 1.0; // 7.1) perform TLIME iteration for smallest magnitude // eigenvalue const Real gamma = 0.0; const Real eta = 0.0; const Real delta = 1e-03; bool external; pia.template applyTLIMEIteration (gamma,eta,epsilon,piaLS,delta,2,external,x,lambda_min); assert(external); } // 8) check largest magnitude eigenvalue (we have // ||m|| >= |lambda| for each eigenvalue lambda // of a matrix m and each matrix norm ||.||) if (std::abs(lambda_max) > m_.infinity_norm()) DUNE_THROW(Dune::Exception,"Absolute value of approximated " << "largest magnitude eigenvalue is greater than " << "infinity norm of the matrix!"); // 9) output largest magnitude eigenvalue if (verbose_) std::cout << " Largest magnitude eigenvalue λ_max = " << lambda_max << std::endl; // 10) output smallest magnitude eigenvalue if (verbose_) std::cout << " Smallest magnitude eigenvalue λ_min = " << lambda_min << std::endl; // 11) compute spectral (i.e. 2-norm) condition number // (assume that m_ is symmetric) cond_2 = std::abs(lambda_max / lambda_min); // 12) output spectral (i.e. 2-norm) condition number if (verbose_) std::cout << " 2-norm condition number cond_2 = " << cond_2 << std::endl; // 13) return spectral (i.e. 2-norm) condition number return cond_2; } //! compute spectral (i.e. 2-norm) condition number of the matrix, //! without assuming that it is symmetric inline Real computeNonSymCond2 () const { // 1) allocate memory for largest and smallest singular value // as well as the spectral (i.e. 2-norm) condition number Real sigma_max, sigma_min, cond_2; // 2) allocate memory for starting vectors and approximated // eigenvectors respectively singular vectors BlockVector x(m_.M()); #if HAVE_ARPACKPP // 3) setup ARPACK++ eigenvalue algorithms typedef Dune::ArPackPlusPlus_Algorithms ARPPP_A; const ARPPP_A arppp_a(m_,100000,arppp_a_verbosity_level_); #endif // HAVE_ARPACKPP // 4) compute m^t*m BCRSMatrix mtm; Dune::transposeMatMultMat(mtm,m_,m_); // 5) allocate memory for largest and smallest magnitude // eigenvalue of m^t*m Real lambda_max, lambda_min; // 6) setup power iteration based iterative eigenvalue algorithms // for m^t*m typedef Dune::PowerIteration_Algorithms PIA; PIA pia(mtm,20000,pia_verbosity_level_); static const bool avoidLinSolverCrime = true; #if HAVE_SUPERLU // 7) select a linear solver for power iteration based iterative // eigenvalue algorithms for m^t*m typedef Dune::SuperLU PIALS; const unsigned int piaLS_verbosity = 0; PIALS piaLS(pia.getIterationMatrix(),piaLS_verbosity); #else // 7) select a linear solver for power iteration based iterative // eigenvalue algorithms for m^t*m typedef Dune::SeqGS PIAPC; PIAPC piaPC(pia.getIterationMatrix(),2,1.0); const double piaLS_reduction = 1e-02; const unsigned int piaLS_max_iter = 1000; const unsigned int piaLS_verbosity = 0; typedef Dune::BiCGSTABSolver PIALS; PIALS piaLS(pia.getIterationOperator(),piaPC, piaLS_reduction,piaLS_max_iter,piaLS_verbosity); #endif // HAVE_SUPERLU #if HAVE_ARPACKPP // 8) get largest singular value via ARPACK++ { const Real epsilon = 0.0; // x = 1.0; (not supported yet) arppp_a.computeNonSymMax(epsilon,x,sigma_max); } #else // 8) get largest singular value as square root of the largest // magnitude eigenvalue of m^t*m via a combination of power // and TLIME iteration { const Real epsilonPI = 1e-02; const Real epsilonTLIME = 1e-08; x = 1.0; // 8.1) perform power iteration for largest magnitude // eigenvalue of m^t*m (predictor) pia.applyPowerIteration(epsilonPI,x,lambda_max); // 8.2) perform TLIME iteration to improve result (corrector) const Real gamma = mtm.infinity_norm(); const Real eta = 0.0; const Real delta = 1e-03; bool external; pia.template applyTLIMEIteration (gamma,eta,epsilonTLIME,piaLS,delta,2,external,x,lambda_max); assert(external); // 8.3) get largest singular value sigma_max = std::sqrt(lambda_max); } #endif // HAVE_ARPACKPP // 9) get smallest singular value as square root of the smallest // magnitude eigenvalue of m^t*m via TLIME iteration { const Real epsilon = 1e-11; x = 1.0; // 9.1) perform TLIME iteration for smallest magnitude // eigenvalue of m^t*m const Real gamma = 0.0; const Real eta = 0.0; const Real delta = 1e-03; bool external; pia.template applyTLIMEIteration (gamma,eta,epsilon,piaLS,delta,2,external,x,lambda_min); assert(external); // 9.2) get smallest singular value sigma_min = std::sqrt(lambda_min); } // 10) check largest magnitude eigenvalue (we have // ||m|| >= |lambda| for each eigenvalue lambda // of a matrix m and each matrix norm ||.||) if (std::abs(lambda_max) > mtm.infinity_norm()) DUNE_THROW(Dune::Exception,"Absolute value of approximated " << "largest magnitude eigenvalue is greater than " << "infinity norm of the matrix!"); // 11) output largest singular value if (verbose_) std::cout << " Largest singular value σ_max = " << sigma_max << std::endl; // 12) output smallest singular value if (verbose_) std::cout << " Smallest singular value σ_min = " << sigma_min << std::endl; // 13) compute spectral (i.e. 2-norm) condition number cond_2 = sigma_max / sigma_min; // 14) output spectral (i.e. 2-norm) condition number if (verbose_) std::cout << " 2-norm condition number cond_2 = " << cond_2 << std::endl; // 15) return spectral (i.e. 2-norm) condition number return cond_2; } protected: // parameters related to computation of matrix information const BCRSMatrix& m_; // verbosity setting const bool verbose_; const unsigned int arppp_a_verbosity_level_; const unsigned int pia_verbosity_level_; // memory for storing matrix information // (mutable as matrix information is computed on demand) mutable Real cond_2_; mutable bool symmetricity_assumed_; }; #endif // DUNE_ISTL_EIGENVALUE_TEST_MATRIXINFO_HH dune-istl-2.5.1/dune/istl/gsetc.hh000066400000000000000000000466301313314427100167670ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_GSETC_HH #define DUNE_ISTL_GSETC_HH #include #include #include #include #include #include "multitypeblockvector.hh" #include "multitypeblockmatrix.hh" #include "istlexception.hh" /*! \file \brief Simple iterative methods like Jacobi, Gauss-Seidel, SOR, SSOR, etc. in a generic way */ namespace Dune { /** * @defgroup ISTL_Kernel Block Recursive Iterative Kernels * @ingroup ISTL_SPMV * * Generic iterative kernels for the solvers which work on the block recursive * structure of the matrices and vectors. * @addtogroup ISTL_Kernel * @{ */ //============================================================ // parameter types //============================================================ //! compile-time parameter for block recursion depth template struct BL { enum {recursion_level = l}; }; enum WithDiagType { withdiag=1, nodiag=0 }; enum WithRelaxType { withrelax=1, norelax=0 }; //============================================================ // generic triangular solves // consider block decomposition A = L + D + U // we can invert L, L+D, U, U+D // we can apply relaxation or not // we can recurse over a fixed number of levels //============================================================ // template meta program for triangular solves template struct algmeta_btsolve { template static void bltsolve (const M& A, X& v, const Y& d, const K& w) { // iterator types typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; // local solve at each block and immediate update rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { bblock rhs(d[i.index()]); coliterator j; for (j=(*i).begin(); j.index()::bltsolve(*j,v[i.index()],rhs,w); } } template static void butsolve (const M& A, X& v, const Y& d, const K& w) { // iterator types typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; // local solve at each block and immediate update rowiterator rendi=A.beforeBegin(); for (rowiterator i=A.beforeEnd(); i!=rendi; --i) { bblock rhs(d[i.index()]); coliterator j; for (j=(*i).beforeEnd(); j.index()>i.index(); --j) (*j).mmv(v[j.index()],rhs); algmeta_btsolve::butsolve(*j,v[i.index()],rhs,w); } } }; // recursion end ... template<> struct algmeta_btsolve<0,withdiag,withrelax> { template static void bltsolve (const M& A, X& v, const Y& d, const K& w) { A.solve(v,d); v *= w; } template static void butsolve (const M& A, X& v, const Y& d, const K& w) { A.solve(v,d); v *= w; } }; template<> struct algmeta_btsolve<0,withdiag,norelax> { template static void bltsolve (const M& A, X& v, const Y& d, const K& /*w*/) { A.solve(v,d); } template static void butsolve (const M& A, X& v, const Y& d, const K& /*w*/) { A.solve(v,d); } }; template<> struct algmeta_btsolve<0,nodiag,withrelax> { template static void bltsolve (const M& /*A*/, X& v, const Y& d, const K& w) { v = d; v *= w; } template static void butsolve (const M& /*A*/, X& v, const Y& d, const K& w) { v = d; v *= w; } }; template<> struct algmeta_btsolve<0,nodiag,norelax> { template static void bltsolve (const M& /*A*/, X& v, const Y& d, const K& /*w*/) { v = d; } template static void butsolve (const M& /*A*/, X& v, const Y& d, const K& /*w*/) { v = d; } }; // user calls // default block recursion level = 1 //! block lower triangular solve template void bltsolve (const M& A, X& v, const Y& d) { typename X::field_type w=1; algmeta_btsolve<1,withdiag,norelax>::bltsolve(A,v,d,w); } //! relaxed block lower triangular solve template void bltsolve (const M& A, X& v, const Y& d, const K& w) { algmeta_btsolve<1,withdiag,withrelax>::bltsolve(A,v,d,w); } //! unit block lower triangular solve template void ubltsolve (const M& A, X& v, const Y& d) { typename X::field_type w=1; algmeta_btsolve<1,nodiag,norelax>::bltsolve(A,v,d,w); } //! relaxed unit block lower triangular solve template void ubltsolve (const M& A, X& v, const Y& d, const K& w) { algmeta_btsolve<1,nodiag,withrelax>::bltsolve(A,v,d,w); } //! block upper triangular solve template void butsolve (const M& A, X& v, const Y& d) { typename X::field_type w=1; algmeta_btsolve<1,withdiag,norelax>::butsolve(A,v,d,w); } //! relaxed block upper triangular solve template void butsolve (const M& A, X& v, const Y& d, const K& w) { algmeta_btsolve<1,withdiag,withrelax>::butsolve(A,v,d,w); } //! unit block upper triangular solve template void ubutsolve (const M& A, X& v, const Y& d) { typename X::field_type w=1; algmeta_btsolve<1,nodiag,norelax>::butsolve(A,v,d,w); } //! relaxed unit block upper triangular solve template void ubutsolve (const M& A, X& v, const Y& d, const K& w) { algmeta_btsolve<1,nodiag,withrelax>::butsolve(A,v,d,w); } // general block recursion level >= 0 //! block lower triangular solve template void bltsolve (const M& A, X& v, const Y& d, BL /*bl*/) { typename X::field_type w=1; algmeta_btsolve::bltsolve(A,v,d,w); } //! relaxed block lower triangular solve template void bltsolve (const M& A, X& v, const Y& d, const K& w, BL /*bl*/) { algmeta_btsolve::bltsolve(A,v,d,w); } //! unit block lower triangular solve template void ubltsolve (const M& A, X& v, const Y& d, BL /*bl*/) { typename X::field_type w=1; algmeta_btsolve::bltsolve(A,v,d,w); } //! relaxed unit block lower triangular solve template void ubltsolve (const M& A, X& v, const Y& d, const K& w, BL /*bl*/) { algmeta_btsolve::bltsolve(A,v,d,w); } //! block upper triangular solve template void butsolve (const M& A, X& v, const Y& d, BL bl) { typename X::field_type w=1; algmeta_btsolve::butsolve(A,v,d,w); } //! relaxed block upper triangular solve template void butsolve (const M& A, X& v, const Y& d, const K& w, BL bl) { algmeta_btsolve::butsolve(A,v,d,w); } //! unit block upper triangular solve template void ubutsolve (const M& A, X& v, const Y& d, BL bl) { typename X::field_type w=1; algmeta_btsolve::butsolve(A,v,d,w); } //! relaxed unit block upper triangular solve template void ubutsolve (const M& A, X& v, const Y& d, const K& w, BL bl) { algmeta_btsolve::butsolve(A,v,d,w); } //============================================================ // generic block diagonal solves // consider block decomposition A = L + D + U // we can apply relaxation or not // we can recurse over a fixed number of levels //============================================================ // template meta program for diagonal solves template struct algmeta_bdsolve { template static void bdsolve (const M& A, X& v, const Y& d, const K& w) { // iterator types typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; // local solve at each block and immediate update rowiterator rendi=A.beforeBegin(); for (rowiterator i=A.beforeEnd(); i!=rendi; --i) { coliterator ii=(*i).find(i.index()); algmeta_bdsolve::bdsolve(*ii,v[i.index()],d[i.index()],w); } } }; // recursion end ... template<> struct algmeta_bdsolve<0,withrelax> { template static void bdsolve (const M& A, X& v, const Y& d, const K& w) { A.solve(v,d); v *= w; } }; template<> struct algmeta_bdsolve<0,norelax> { template static void bdsolve (const M& A, X& v, const Y& d, const K& /*w*/) { A.solve(v,d); } }; // user calls // default block recursion level = 1 //! block diagonal solve, no relaxation template void bdsolve (const M& A, X& v, const Y& d) { typename X::field_type w=1; algmeta_bdsolve<1,norelax>::bdsolve(A,v,d,w); } //! block diagonal solve, with relaxation template void bdsolve (const M& A, X& v, const Y& d, const K& w) { algmeta_bdsolve<1,withrelax>::bdsolve(A,v,d,w); } // general block recursion level >= 0 //! block diagonal solve, no relaxation template void bdsolve (const M& A, X& v, const Y& d, BL /*bl*/) { typename X::field_type w=1; algmeta_bdsolve::bdsolve(A,v,d,w); } //! block diagonal solve, with relaxation template void bdsolve (const M& A, X& v, const Y& d, const K& w, BL /*bl*/) { algmeta_bdsolve::bdsolve(A,v,d,w); } //============================================================ // generic steps of iteration methods // Jacobi, Gauss-Seidel, SOR, SSOR // work directly on Ax=b, ie solve M(x^{i+1}-x^i) = w (b-Ax^i) // we can recurse over a fixed number of levels //============================================================ // template meta program for iterative solver steps template struct algmeta_itsteps { template static void dbgs (const M& A, X& x, const Y& b, const K& w) { typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; bblock rhs; X xold(x); // remember old x rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { rhs = b[i.index()]; // rhs = b_i coliterator endj=(*i).end(); coliterator j=(*i).begin(); for (; j.index() i (*j).mmv(x[j.index()],rhs); // rhs -= sum_{j>i} a_ij * xold_j algmeta_itsteps::dbgs(*diag,x[i.index()],rhs,w); // if I==1: xnew_i = rhs/a_ii } // next two lines: xnew_i = w / a_ii * (b_i - sum_{j=i} a_ij * xold_j) + (1-w)*xold; x *= w; x.axpy(K(1)-w,xold); } template static void bsorf (const M& A, X& x, const Y& b, const K& w) { typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; typedef typename X::block_type xblock; bblock rhs; xblock v; // Initialize nested data structure if there are entries if(A.begin()!=A.end()) v=x[0]; rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { rhs = b[i.index()]; // rhs = b_i coliterator endj=(*i).end(); // iterate over a_ij with j < i coliterator j=(*i).begin(); for (; j.index()::bsorf(*diag,v,rhs,w); // if blocksize I==1: v = rhs/a_ii x[i.index()].axpy(w,v); // x_i = w / a_ii * (b_i - sum_{j=i} a_ij * xold_j) } } template static void bsorb (const M& A, X& x, const Y& b, const K& w) { typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; typedef typename X::block_type xblock; bblock rhs; xblock v; // Initialize nested data structure if there are entries if(A.begin()!=A.end()) v=x[0]; rowiterator endi=A.beforeBegin(); for (rowiterator i=A.beforeEnd(); i!=endi; --i) { rhs = b[i.index()]; coliterator endj=(*i).end(); coliterator j=(*i).begin(); for (; j.index()::bsorb(*diag,v,rhs,w); x[i.index()].axpy(w,v); } } template static void dbjac (const M& A, X& x, const Y& b, const K& w) { typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type bblock; bblock rhs; X v(x); // allocate with same size rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { rhs = b[i.index()]; coliterator endj=(*i).end(); coliterator j=(*i).begin(); for (; j.index()::dbjac(*diag,v[i.index()],rhs,w); } x.axpy(w,v); } }; // end of recursion template struct algmeta_itsteps<0,M> { template static void dbgs (const M& A, X& x, const Y& b, const K& /*w*/) { A.solve(x,b); } template static void bsorf (const M& A, X& x, const Y& b, const K& /*w*/) { A.solve(x,b); } template static void bsorb (const M& A, X& x, const Y& b, const K& /*w*/) { A.solve(x,b); } template static void dbjac (const M& A, X& x, const Y& b, const K& /*w*/) { A.solve(x,b); } }; template struct algmeta_itsteps> { template< typename... MultiTypeVectorArgs, class K> static void dbgs (const MultiTypeBlockMatrix& A, MultiTypeBlockVector& x, const MultiTypeBlockVector& b, const K& w) { static const int N = MultiTypeBlockMatrix::N(); Dune::MultiTypeBlockMatrix_Solver::dbgs(A, x, b, w); } template< typename... MultiTypeVectorArgs, class K> static void bsorf (const MultiTypeBlockMatrix& A, MultiTypeBlockVector& x, const MultiTypeBlockVector& b, const K& w) { static const int N = MultiTypeBlockMatrix::N(); Dune::MultiTypeBlockMatrix_Solver::bsorf(A, x, b, w); } template< typename... MultiTypeVectorArgs, class K> static void bsorb (const MultiTypeBlockMatrix& A, MultiTypeBlockVector& x, const MultiTypeBlockVector& b, const K& w) { static const int N = MultiTypeBlockMatrix::N(); Dune::MultiTypeBlockMatrix_Solver::bsorb(A, x, b, w); } template< typename... MultiTypeVectorArgs, class K > static void dbjac (const MultiTypeBlockMatrix& A, MultiTypeBlockVector& x, const MultiTypeBlockVector& b, const K& w) { static const int N = MultiTypeBlockMatrix::N(); Dune::MultiTypeBlockMatrix_Solver::dbjac(A, x, b, w); } }; // user calls //! GS step template void dbgs (const M& A, X& x, const Y& b, const K& w) { algmeta_itsteps<1,M>::dbgs(A,x,b,w); } //! GS step template void dbgs (const M& A, X& x, const Y& b, const K& w, BL /*bl*/) { algmeta_itsteps::dbgs(A,x,b,w); } //! SOR step template void bsorf (const M& A, X& x, const Y& b, const K& w) { algmeta_itsteps<1,M>::bsorf(A,x,b,w); } //! SOR step template void bsorf (const M& A, X& x, const Y& b, const K& w, BL /*bl*/) { algmeta_itsteps::bsorf(A,x,b,w); } //! SSOR step template void bsorb (const M& A, X& x, const Y& b, const K& w) { algmeta_itsteps<1,M>::bsorb(A,x,b,w); } //! Backward SOR step template void bsorb (const M& A, X& x, const Y& b, const K& w, BL /*bl*/) { algmeta_itsteps::type>::bsorb(A,x,b,w); } //! Jacobi step template void dbjac (const M& A, X& x, const Y& b, const K& w) { algmeta_itsteps<1,M>::dbjac(A,x,b,w); } //! Jacobi step template void dbjac (const M& A, X& x, const Y& b, const K& w, BL /*bl*/) { algmeta_itsteps::dbjac(A,x,b,w); } /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/ilu.hh000066400000000000000000000172461313314427100164540ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_ILU_HH #define DUNE_ISTL_ILU_HH #include #include #include #include #include #include #include #include #include "istlexception.hh" /** \file * \brief ??? */ namespace Dune { /** @addtogroup ISTL_Kernel @{ */ class MatrixBlockError : public virtual Dune::FMatrixError { public: int r, c; }; //! compute ILU decomposition of A. A is overwritten by its decomposition template void bilu0_decomposition (M& A) { // iterator types typedef typename M::RowIterator rowiterator; typedef typename M::ColIterator coliterator; typedef typename M::block_type block; // implement left looking variant with stored inverse rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { // coliterator is diagonal after the following loop coliterator endij=(*i).end(); // end of row i coliterator ij; // eliminate entries left of diagonal; store L factor for (ij=(*i).begin(); ij.index() void bilu_backsolve (const M& A, X& v, const Y& d) { // iterator types typedef typename M::ConstRowIterator rowiterator; typedef typename M::ConstColIterator coliterator; typedef typename Y::block_type dblock; typedef typename X::block_type vblock; // lower triangular solve rowiterator endi=A.end(); for (rowiterator i=A.begin(); i!=endi; ++i) { dblock rhs(d[i.index()]); for (coliterator j=(*i).begin(); j.index()i.index(); --j) (*j).mmv(v[j.index()],rhs); v[i.index()] = 0; (*j).umv(rhs,v[i.index()]); // diagonal stores inverse! } } // recursive function template to access first entry of a matrix template typename M::field_type& firstmatrixelement (M& A) { return firstmatrixelement(*(A.begin()->begin())); } template K& firstmatrixelement (FieldMatrix& A) { return A[0][0]; } template K& firstmatrixelement (FieldMatrix& A) { return A[0][0]; } /*! ILU decomposition of order n Computes ILU decomposition of order n. The matrix ILU should be an empty matrix in row_wise creation mode. This allows the user to either specify the number of nonzero elements or to determine it automatically at run-time. */ template void bilu_decomposition (const M& A, int n, M& ILU) { // iterator types typedef typename M::ColIterator coliterator; typedef typename M::ConstRowIterator crowiterator; typedef typename M::ConstColIterator ccoliterator; typedef typename M::CreateIterator createiterator; typedef typename M::field_type K; typedef std::map map; typedef typename map::iterator mapiterator; // symbolic factorization phase, store generation number in first matrix element crowiterator endi=A.end(); createiterator ci=ILU.createbegin(); for (crowiterator i=A.begin(); i!=endi; ++i) { // std::cout << "in row " << i.index() << std::endl; map rowpattern; // maps column index to generation // initialize pattern with row of A for (ccoliterator j=(*i).begin(); j!=(*i).end(); ++j) rowpattern[j.index()] = 0; // eliminate entries in row which are to the left of the diagonal for (mapiterator ik=rowpattern.begin(); (*ik).first #include #include "matrix.hh" #include #include namespace Dune { /** * @file * @brief Various local subdomain solvers based on ILU * for SeqOverlappingSchwarz. * @author Markus Blatt */ /** * @addtogroup ISTL * @{ */ /** * @brief base class encapsulating common algorithms of ILU0SubdomainSolver * and ILUNSubdomainSolver. * @tparam M The type of the matrix. * @tparam X The type of the vector for the domain. * @tparam X The type of the vector for the range. * */ template class ILUSubdomainSolver { public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; /** * @brief Apply the subdomain solver. * * On entry v=? and d=b-A(x) (although this might not be * computed in that way. On exit v contains the update */ virtual void apply (X& v, const Y& d) =0; virtual ~ILUSubdomainSolver() {} protected: /** * @brief Copy the local part of the global matrix to ILU. * @param A The global matrix. * @param rowset The global indices of the local problem. */ template std::size_t copyToLocalMatrix(const M& A, S& rowset); //! \brief The ILU0 decomposition of the matrix, or the local matrix // for ILUN matrix_type ILU; }; /** * @brief Exact subdomain solver using ILU(p) with appropriate p. * @tparam M The type of the matrix. * @tparam X The type of the vector for the domain. * @tparam X The type of the vector for the range. */ template class ILU0SubdomainSolver : public ILUSubdomainSolver{ public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; typedef typename std::remove_const::type rilu_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; /** * @brief Apply the subdomain solver. * @copydoc ILUSubdomainSolver::apply */ void apply (X& v, const Y& d) { bilu_backsolve(this->ILU,v,d); } /** * @brief Set the data of the local problem. * * @param A The global matrix. * @param rowset The global indices of the local problem. * @tparam S The type of the set with the indices. */ template void setSubMatrix(const M& A, S& rowset); }; template class ILUNSubdomainSolver : public ILUSubdomainSolver{ public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; typedef typename std::remove_const::type rilu_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; /** * @brief Apply the subdomain solver. * @copydoc ILUSubdomainSolver::apply */ void apply (X& v, const Y& d) { bilu_backsolve(RILU,v,d); } /** * @brief Set the data of the local problem. * * @param A The global matrix. * @param rowset The global indices of the local problem. * @tparam S The type of the set with the indices. */ template void setSubMatrix(const M& A, S& rowset); private: /** * @brief Storage for the ILUN decomposition. */ rilu_type RILU; }; template template std::size_t ILUSubdomainSolver::copyToLocalMatrix(const M& A, S& rowSet) { // Calculate consecutive indices for local problem // while perserving the ordering typedef typename M::size_type size_type; typedef std::map IndexMap; typedef typename IndexMap::iterator IMIter; IndexMap indexMap; IMIter guess = indexMap.begin(); size_type localIndex=0; typedef typename S::const_iterator SIter; for(SIter rowIdx = rowSet.begin(), rowEnd=rowSet.end(); rowIdx!= rowEnd; ++rowIdx, ++localIndex) guess = indexMap.insert(guess, std::make_pair(*rowIdx,localIndex)); // Build Matrix for local subproblem ILU.setSize(rowSet.size(),rowSet.size()); ILU.setBuildMode(matrix_type::row_wise); // Create sparsity pattern typedef typename matrix_type::CreateIterator CIter; CIter rowCreator = ILU.createbegin(); std::size_t offset=0; for(SIter rowIdx = rowSet.begin(), rowEnd=rowSet.end(); rowIdx!= rowEnd; ++rowIdx, ++rowCreator) { // See which row entries are in our subset and add them to // the sparsity pattern guess = indexMap.begin(); for(typename matrix_type::ConstColIterator col=A[*rowIdx].begin(), endcol=A[*rowIdx].end(); col != endcol; ++col) { // search for the entry in the row set guess = indexMap.find(col.index()); if(guess!=indexMap.end()) { // add local index to row rowCreator.insert(guess->second); offset=std::max(offset,(std::size_t)std::abs((int)(guess->second-rowCreator.index()))); } } } // Insert the matrix values for the local problem typename matrix_type::iterator iluRow=ILU.begin(); for(SIter rowIdx = rowSet.begin(), rowEnd=rowSet.end(); rowIdx!= rowEnd; ++rowIdx, ++iluRow) { // See which row entries are in our subset and add them to // the sparsity pattern typename matrix_type::ColIterator localCol=iluRow->begin(); for(typename matrix_type::ConstColIterator col=A[*rowIdx].begin(), endcol=A[*rowIdx].end(); col != endcol; ++col) { // search for the entry in the row set guess = indexMap.find(col.index()); if(guess!=indexMap.end()) { // set local value (*localCol)=(*col); ++localCol; } } } return offset; } template template void ILU0SubdomainSolver::setSubMatrix(const M& A, S& rowSet) { this->copyToLocalMatrix(A,rowSet); bilu0_decomposition(this->ILU); } template template void ILUNSubdomainSolver::setSubMatrix(const M& A, S& rowSet) { std::size_t offset=copyToLocalMatrix(A,rowSet); RILU.setSize(rowSet.size(),rowSet.size(), (1+2*offset)*rowSet.size()); RILU.setBuildMode(matrix_type::row_wise); bilu_decomposition(this->ILU, (offset+1)/2, RILU); } /** @} */ } // end name space DUNE #endif dune-istl-2.5.1/dune/istl/io.hh000066400000000000000000000447221313314427100162710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_IO_HH #define DUNE_ISTL_IO_HH #include #include #include #include #include #include #include #include "matrixutils.hh" #include "istlexception.hh" #include #include #include #include #include #include #include #include "bcrsmatrix.hh" namespace Dune { /** @addtogroup ISTL_IO @{ */ /** \file \brief Some generic functions for pretty printing vectors and matrices */ //////////////////////////////////////////////////////////////////////// // // pretty printing of vectors // /** * \brief Recursively print all the blocks * * \code * #include * \endcode */ template void recursive_printvector (std::ostream& s, const V& v, std::string rowtext, int& counter, int columns, int width, int precision) { for (typename V::ConstIterator i=v.begin(); i!=v.end(); ++i) recursive_printvector(s,*i,rowtext,counter,columns,width,precision); } /** * \brief Recursively print all the blocks -- specialization for FieldVector * * \code * #include * \endcode */ template void recursive_printvector (std::ostream& s, const FieldVector& v, std::string rowtext, int& counter, int columns, int width, int precision) { DUNE_UNUSED_PARAMETER(precision); // we now can print n numbers for (int i=0; i * \endcode */ template void printvector (std::ostream& s, const V& v, std::string title, std::string rowtext, int columns=1, int width=10, int precision=2) { // count the numbers printed to make columns int counter=0; // remember old flags std::ios_base::fmtflags oldflags = s.flags(); // set the output format s.setf(std::ios_base::scientific, std::ios_base::floatfield); int oldprec = s.precision(); s.precision(precision); // print title s << title << " [blocks=" << v.N() << ",dimension=" << v.dim() << "]" << std::endl; // print data from all blocks recursive_printvector(s,v,rowtext,counter,columns,width,precision); // check if new line is required if (counter%columns!=0) s << std::endl; // reset the output format s.flags(oldflags); s.precision(oldprec); } //////////////////////////////////////////////////////////////////////// // // pretty printing of matrices // /** * \brief Print a row of zeros for a non-existing block * * \code * #include * \endcode */ inline void fill_row (std::ostream& s, int m, int width, int precision) { DUNE_UNUSED_PARAMETER(precision); for (int j=0; j * \endcode */ template void print_row (std::ostream& s, const M& A, typename M::size_type I, typename M::size_type J, typename M::size_type therow, int width, int precision) { typename M::size_type i0=I; for (typename M::size_type i=0; i=i0 && therow::rowdim(A,i)) { // the row is in this block row ! typename M::size_type j0=J; for (typename M::size_type j=0; j::coldim(A,j),width,precision); // advance columns j0 += MatrixDimension::coldim(A,j); } } // advance rows i0 += MatrixDimension::rowdim(A,i); } } /** * \brief Print one row of a matrix, specialization for FieldMatrix * * \code * #include * \endcode */ template void print_row (std::ostream& s, const FieldMatrix& A, typename FieldMatrix::size_type I, typename FieldMatrix::size_type J, typename FieldMatrix::size_type therow, int width, int precision) { DUNE_UNUSED_PARAMETER(J); DUNE_UNUSED_PARAMETER(precision); typedef typename FieldMatrix::size_type size_type; for (size_type i=0; i * * \code * #include * \endcode */ template void print_row (std::ostream& s, const FieldMatrix& A, typename FieldMatrix::size_type I, typename FieldMatrix::size_type J, typename FieldMatrix::size_type therow, int width, int precision) { DUNE_UNUSED_PARAMETER(J); DUNE_UNUSED_PARAMETER(precision); if (I==therow) { s << " "; // space in front of each entry s.width(width); // set width for each entry anew s << static_cast(A); // yeah, the number ! } } /** * \brief Print a generic block matrix * * \code * #include * \endcode * \bug Empty rows and columns are omitted by this method. (FlySpray #7) */ template void printmatrix (std::ostream& s, const M& A, std::string title, std::string rowtext, int width=10, int precision=2) { // remember old flags std::ios_base::fmtflags oldflags = s.flags(); // set the output format s.setf(std::ios_base::scientific, std::ios_base::floatfield); int oldprec = s.precision(); s.precision(precision); // print title s << title << " [n=" << A.N() << ",m=" << A.M() << ",rowdim=" << MatrixDimension::rowdim(A) << ",coldim=" << MatrixDimension::coldim(A) << "]" << std::endl; // print all rows for (typename M::size_type i=0; i::rowdim(A); i++) { s << rowtext; // start a new row s << " "; // space in front of each entry s.width(4); // set width for counter s << i; // number of first entry in a line print_row(s,A,0,0,i,width,precision); // generic print s << std::endl; // start a new line } // reset the output format s.flags(oldflags); s.precision(oldprec); } /** * \brief Prints a BCRSMatrix with fixed sized blocks. * * \code * #include * \endcode * * Only the nonzero entries will be printed as matrix blocks * together with their * corresponding column index and all others will be omitted. * * This might be preferable over printmatrix in the case of big * sparse matrices with nonscalar blocks. * * @param s The ostream to print to. * @param mat The matrix to print. * @param title The title for the matrix. * @param rowtext The text to prepend to each print out of a matrix row. * @param width The number of nonzero blocks to print in one line. * @param precision The precision to use when printing the numbers. */ template void printSparseMatrix(std::ostream& s, const BCRSMatrix,A>& mat, std::string title, std::string rowtext, int width=3, int precision=2) { typedef BCRSMatrix,A> Matrix; // remember old flags std::ios_base::fmtflags oldflags = s.flags(); // set the output format s.setf(std::ios_base::scientific, std::ios_base::floatfield); int oldprec = s.precision(); s.precision(precision); // print title s << title << " [n=" << mat.N() << ",m=" << mat.M() << ",rowdim=" << MatrixDimension::rowdim(mat) << ",coldim=" << MatrixDimension::coldim(mat) << "]" << std::endl; typedef typename Matrix::ConstRowIterator Row; for(Row row=mat.begin(); row != mat.end(); ++row) { int skipcols=0; bool reachedEnd=false; while(!reachedEnd) { for(int innerrow=0; innerrowbegin(); for(; col != row->end(); ++col,++count) { if(count=skipcols+width) break; if(innerrow==0) { if(count==skipcols) { s << rowtext; // start a new row s << " "; // space in front of each entry s.width(4); // set width for counter s << row.index()<<": "; // number of first entry in a line } s.width(4); s<end()) reachedEnd = true; else s << std::endl; } skipcols += width; s << std::endl; } s << std::endl; } // reset the output format s.flags(oldflags); s.precision(oldprec); } namespace { template struct MatlabPODWriter { static std::ostream& write(const T& t, std::ostream& s) { s << t; return s; } }; template struct MatlabPODWriter > { static std::ostream& write(const std::complex& t, std::ostream& s) { s << t.real() << " " << t.imag(); return s; } }; } // anonymous namespace /** * \brief Helper method for the writeMatrixToMatlab routine. * * \code * #include * \endcode * * This specialization for DiagonalMatrices ends the recursion */ template void writeMatrixToMatlabHelper(const ScaledIdentityMatrix& matrix, int rowOffset, int colOffset, std::ostream& s) { for (int i=0; i::write(matrix.scalar(), s)<< std::endl; } } /** * \brief Helper method for the writeMatrixToMatlab routine. * * \code * #include * \endcode * * This specialization for DiagonalMatrices ends the recursion */ template void writeMatrixToMatlabHelper(const DiagonalMatrix& matrix, int rowOffset, int colOffset, std::ostream& s) { for (int i=0; i::write(matrix.diagonal(i), s)<< std::endl; } } /** * \brief Helper method for the writeMatrixToMatlab routine. * * \code * #include * \endcode * * This specialization for FieldMatrices ends the recursion */ template void writeMatrixToMatlabHelper ( const FieldMatrix& matrix, int rowOffset, int colOffset, std::ostream& s) { for (int i=0; i::write(matrix[i][j], s)<< std::endl; } } /** * \brief Helper method for the writeMatrixToMatlab routine. * * \code * #include * \endcode * * This specialization for DynamicMatrices ends the recursion */ template void writeMatrixToMatlabHelper(const DynamicMatrix& matrix, int rowOffset, int colOffset, std::ostream& s) { for (int i=0; i::write(matrix[i][j], s)<< std::endl; } } /** * \brief Helper method for the writeMatrixToMatlab routine. * * \code * #include * \endcode */ template void writeMatrixToMatlabHelper(const MatrixType& matrix, int externalRowOffset, int externalColOffset, std::ostream& s) { // Precompute the accumulated sizes of the columns std::vector colOffset(matrix.M()); if (colOffset.size() > 0) colOffset[0] = 0; for (typename MatrixType::size_type i=0; i::coldim(matrix,i); typename MatrixType::size_type rowOffset = 0; // Loop over all matrix rows for (typename MatrixType::size_type rowIdx=0; rowIdx::rowdim(matrix, rowIdx); } } /** * \brief Writes sparse matrix in a Matlab-readable format * * \code * #include * \endcode * This routine writes the argument BCRSMatrix to a file with the name given * by the filename argument. The file format is ASCII, with no header, and * three data columns. Each row describes a scalar matrix entry and * consists of the matrix row and column numbers (both counted starting from * 1), and the matrix entry. Such a file can be read from Matlab using the * command * \code * new_mat = spconvert(load('filename')); * \endcode * @param matrix reference to matrix * @param filename * @param outputPrecision (number of digits) which is used to write the output file */ template void writeMatrixToMatlab(const MatrixType& matrix, const std::string& filename, int outputPrecision = 18) { std::ofstream outStream(filename.c_str()); int oldPrecision = outStream.precision(); outStream.precision(outputPrecision); writeMatrixToMatlabHelper(matrix, 0, 0, outStream); outStream.precision(oldPrecision); } // Recursively print all the blocks template void writeVectorToMatlabHelper (const V& v, std::ostream& stream) { for (const auto& entry : v) writeVectorToMatlabHelper(entry, stream); } // Recursively print all the blocks -- specialization for FieldVector template void writeVectorToMatlabHelper (const FieldVector& v, std::ostream& s) { for (const auto& entry : v) { s << entry << std::endl; } } // Recursively print all the blocks -- specialization for std::vector template void writeVectorToMatlabHelper (const std::vector& v, std::ostream& s) { for (const auto& entry : v) { s << entry << std::endl; } } // Recursively print all the blocks -- specialization for std::array template void writeVectorToMatlabHelper (const std::array& v, std::ostream& s) { for (const auto& entry : v) { s << entry << std::endl; } } /** * \brief Writes vectors in a Matlab-readable format * * \code * #include * \endcode * This routine writes the argument block vector to a file with the name given * by the filename argument. The file format is ASCII, with no header, and * a single data column. Such a file can be read from Matlab using the * command * \code * new_vec = load('filename'); * \endcode * \param vector reference to vector to be printed to output file * \param filename filename of output file * \param outputPrecision (number of digits) which is used to write the output file */ template void writeVectorToMatlab(const VectorType& vector, const std::string& filename, int outputPrecision = 18) { std::ofstream outStream(filename.c_str()); int oldPrecision = outStream.precision(); outStream.precision(outputPrecision); writeVectorToMatlabHelper(vector, outStream); outStream.precision(oldPrecision); } /** @} end documentation */ } // namespace Dune #endif dune-istl-2.5.1/dune/istl/istlexception.hh000066400000000000000000000024621313314427100205470ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_ISTLEXCEPTION_HH #define DUNE_ISTL_ISTLEXCEPTION_HH #include namespace Dune { /** @addtogroup ISTL @{ */ //! derive error class from the base class in common class ISTLError : public Dune::MathError {}; //! Error specific to BCRSMatrix. class BCRSMatrixError : public ISTLError {}; //! The overflow error used during implicit BCRSMatrix construction was exhausted. /** * This error occurs if the overflow area of the BCRSMatrix * did not have room for another non-zero entry during implicit * mode construction. * * You can fix this problem by either increasing the average row size * or the overflow fraction. */ class ImplicitModeOverflowExhausted : public BCRSMatrixError {}; //! Thrown when a solver aborts due to some problem. /** * Problems that may cause the solver to abort include a NaN detected during * the convergence check (which may be caused by invalid input data), or * breakdown conditions (which can happen e.g. in BiCGSTABSolver or * RestartedGMResSolver). */ class SolverAbort : public ISTLError {}; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/ldl.hh000066400000000000000000000232541313314427100164320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_LDL_HH #define DUNE_ISTL_LDL_HH #if HAVE_SUITESPARSE_LDL || defined DOXYGEN #include #include #ifdef __cplusplus extern "C" { #include "ldl.h" #include "amd.h" } #endif #include #include #include #include #include namespace Dune { /** * @addtogroup ISTL * * @{ */ /** * @file * @author Marco Agnese, Andrea Sacconi * @brief Class for using LDL with ISTL matrices. */ // forward declarations template class SeqOverlappingSchwarz; template struct SeqOverlappingSchwarzAssemblerHelper; /** * @brief Use the %LDL package to directly solve linear systems -- empty default class * @tparam Matrix the matrix type defining the system * Details on UMFPack can be found on * http://www.cise.ufl.edu/research/sparse/ldl/ */ template class LDL {}; /** * @brief The %LDL direct sparse solver for matrices of type BCRSMatrix * * Specialization for the Dune::BCRSMatrix. %LDL will always go double * precision. * * \tparam T Number type. Only double is supported * \tparam A STL-compatible allocator type * \tparam n Number of rows in a matrix block * \tparam m Number of columns in a matrix block * * \note This will only work if dune-istl has been configured to use LDL */ template class LDL,A > > : public InverseOperator, typename A::template rebind >::other>, BlockVector, typename A::template rebind >::other> > { public: /** @brief The matrix type. */ typedef Dune::BCRSMatrix,A> Matrix; typedef Dune::BCRSMatrix,A> matrix_type; /** @brief The corresponding SuperLU Matrix type. */ typedef Dune::ColCompMatrix LDLMatrix; /** @brief Type of an associated initializer class. */ typedef ColCompMatrixInitializer,A> > MatrixInitializer; /** @brief The type of the domain of the solver. */ typedef Dune::BlockVector, typename A::template rebind >::other> domain_type; /** @brief The type of the range of the solver. */ typedef Dune::BlockVector, typename A::template rebind >::other> range_type; /** * @brief Construct a solver object from a BCRSMatrix. * * This computes the matrix decomposition, and may take a long time * (and use a lot of memory). * * @param matrix the matrix to solve for * @param verbose 0 or 1 set the verbosity level, defaults to 0 */ LDL(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false), verbose_(verbose) { //check whether T is a supported type static_assert(std::is_same::value,"Unsupported Type in LDL (only double supported)"); setMatrix(matrix); } /** * @brief Constructor for compatibility with SuperLU standard constructor * * This computes the matrix decomposition, and may take a long time * (and use a lot of memory). * * @param matrix the matrix to solve for * @param verbose 0 or 1 set the verbosity level, defaults to 0 */ LDL(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false), verbose_(verbose) { //check whether T is a supported type static_assert(std::is_same::value,"Unsupported Type in LDL (only double supported)"); setMatrix(matrix); } /** @brief Default constructor. */ LDL() : matrixIsLoaded_(false), verbose_(0) {} /** @brief Default constructor. */ virtual ~LDL() { if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_) free(); } /** \copydoc InverseOperator::apply(X&, Y&, InverseOperatorResult&) */ virtual void apply(domain_type& x, range_type& b, InverseOperatorResult& res) { const int dimMat(ldlMatrix_.N()); ldl_perm(dimMat, Y_, reinterpret_cast(&b[0]), P_); ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_); ldl_dsolve(dimMat, Y_, D_); ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_); ldl_permt(dimMat, reinterpret_cast(&x[0]), Y_, P_); // this is a direct solver res.iterations = 1; res.converged = true; } /** \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) */ virtual void apply(domain_type& x, range_type& b, double reduction, InverseOperatorResult& res) { DUNE_UNUSED_PARAMETER(reduction); apply(x,b,res); } /** * @brief Additional apply method with c-arrays in analogy to superlu. * @param x solution array * @param b rhs array */ void apply(T* x, T* b) { const int dimMat(ldlMatrix_.N()); ldl_perm(dimMat, Y_, b, P_); ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_); ldl_dsolve(dimMat, Y_, D_); ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_); ldl_permt(dimMat, x, Y_, P_); } void setOption(unsigned int option, double value) { DUNE_UNUSED_PARAMETER(option); DUNE_UNUSED_PARAMETER(value); } /** @brief Initialize data from given matrix. */ void setMatrix(const Matrix& matrix) { if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_) free(); ldlMatrix_ = matrix; decompose(); } template void setSubMatrix(const Matrix& matrix, const S& rowIndexSet) { if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_) free(); ldlMatrix_.setMatrix(matrix,rowIndexSet); decompose(); } /** * @brief Sets the verbosity level for the solver. * @param v verbosity level: 0 only error messages, 1 a bit of statistics. */ inline void setVerbosity(int v) { verbose_=v; } /** * @brief Return the column compress matrix. * @warning It is up to the user to keep consistency. */ inline LDLMatrix& getInternalMatrix() { return ldlMatrix_; } /** * @brief Free allocated space. * @warning Later calling apply will result in an error. */ void free() { delete [] D_; delete [] Y_; delete [] Lp_; delete [] Lx_; delete [] Li_; delete [] P_; delete [] Pinv_; ldlMatrix_.free(); matrixIsLoaded_ = false; } /** @brief Get method name. */ inline const char* name() { return "LDL"; } /** * @brief Get factorization diagonal matrix D. * @warning It is up to the user to preserve consistency. */ inline double* getD() { return D_; } /** * @brief Get factorization Lp. * @warning It is up to the user to preserve consistency. */ inline int* getLp() { return Lp_; } /** * @brief Get factorization Li. * @warning It is up to the user to preserve consistency. */ inline int* getLi() { return Li_; } /** * @brief Get factorization Lx. * @warning It is up to the user to preserve consistency. */ inline double* getLx() { return Lx_; } private: template friend class SeqOverlappingSchwarz; friend struct SeqOverlappingSchwarzAssemblerHelper,true>; /** @brief Computes the LDL decomposition. */ void decompose() { // allocate vectors const int dimMat(ldlMatrix_.N()); D_ = new double [dimMat]; Y_ = new double [dimMat]; Lp_ = new int [dimMat + 1]; Parent_ = new int [dimMat]; Lnz_ = new int [dimMat]; Flag_ = new int [dimMat]; Pattern_ = new int [dimMat]; P_ = new int [dimMat]; Pinv_ = new int [dimMat]; double Info [AMD_INFO]; if(amd_order (dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), P_, (double *) NULL, Info) < AMD_OK) DUNE_THROW(InvalidStateException,"Error: AMD failed!"); if(verbose_ > 0) amd_info (Info); // compute the symbolic factorisation ldl_symbolic(dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), Lp_, Parent_, Lnz_, Flag_, P_, Pinv_); // initialise those entries of additionalVectors_ whose dimension is known only now Lx_ = new double [Lp_[dimMat]]; Li_ = new int [Lp_[dimMat]]; // compute the numeric factorisation const int rank(ldl_numeric(dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), ldlMatrix_.getValues(), Lp_, Parent_, Lnz_, Li_, Lx_, D_, Y_, Pattern_, Flag_, P_, Pinv_)); // free temporary vectors delete [] Flag_; delete [] Pattern_; delete [] Parent_; delete [] Lnz_; if(rank!=dimMat) DUNE_THROW(InvalidStateException,"Error: LDL factorisation failed!"); } LDLMatrix ldlMatrix_; bool matrixIsLoaded_; int verbose_; int* Lp_; int* Parent_; int* Lnz_; int* Flag_; int* Pattern_; int* P_; int* Pinv_; double* D_; double* Y_; double* Lx_; int* Li_; }; template struct IsDirectSolver,A> > > { enum {value = true}; }; template struct StoresColumnCompressed,A> > > { enum {value = true}; }; } #endif //HAVE_SUITESPARSE_LDL #endif //DUNE_ISTL_LDL_HH dune-istl-2.5.1/dune/istl/matrix.hh000066400000000000000000000714501313314427100171640ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIX_HH #define DUNE_ISTL_MATRIX_HH /** \file \brief A dynamic dense block matrix class */ #include #include #include #include #include namespace Dune { namespace MatrixImp { /** \brief A Vector of blocks with different blocksizes. This class started as a copy of VariableBlockVector, which used to be used for the internal memory managerment of the 'Matrix' class. However, that mechanism stopped working when I started using the RandomAccessIteratorFacade in VariableBlockVector (308dd85483108f8baaa4051251e2c75e2a9aed32, to make VariableBlockVector pass a number of tightened interface compliance tests), and I couldn't quite figure out how to fix that. However, using VariableBlockVector in Matrix internally was a hack anyway, so I simply took the working version of VariableBlockVector and copied it here under the new name of DenseMatrixBase. This is still hacky, but one step closer to an elegant solution. */ template > class DenseMatrixBase : public block_vector_unmanaged // this derivation gives us all the blas level 1 and norms // on the large array. However, access operators have to be // overwritten. { public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the allocator type typedef A allocator_type; //! The size type for the index access typedef typename A::size_type size_type; /** \brief Type of the elements of the outer vector, i.e., dynamic vectors of B * * Note that this is *not* the type referred to by the iterators and random access operators, * which return proxy objects. */ typedef BlockVector value_type; /** \brief Same as value_type, here for historical reasons */ typedef BlockVector block_type; // just a shorthand typedef BlockVectorWindow window_type; typedef window_type reference; typedef const window_type const_reference; //===== constructors and such /** constructor without arguments makes empty vector, object cannot be used yet */ DenseMatrixBase () : block_vector_unmanaged() { // nothing is known ... rows_ = 0; columns_ = 0; } /** make vector with given number of blocks each having a constant size, object is fully usable then. \param _nblocks Number of blocks \param m Number of elements in each block */ DenseMatrixBase (size_type rows, size_type columns) : block_vector_unmanaged() { // and we can allocate the big array in the base class this->n = rows*columns; columns_ = columns; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = 0; } // we can allocate the windows now rows_ = rows; } //! copy constructor, has copy semantics DenseMatrixBase (const DenseMatrixBase& a) { // allocate the big array in the base class this->n = a.n; columns_ = a.columns_; if (this->n>0) { // allocate and construct objects this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now rows_ = a.rows_; } //! free dynamic memory ~DenseMatrixBase () { if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } } //! same effect as constructor with same argument void resize (size_type rows, size_type columns) { // deconstruct objects and deallocate memory if necessary if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } // and we can allocate the big array in the base class this->n = rows*columns; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now rows_ = rows; columns_ = columns; } //! assignment DenseMatrixBase& operator= (const DenseMatrixBase& a) { if (&a!=this) // check if this and a are different objects { columns_ = a.columns_; // reallocate arrays if necessary // Note: still the block sizes may vary ! if (this->n!=a.n || rows_!=a.rows_) { // deconstruct objects and deallocate memory if necessary if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } // allocate the big array in the base class this->n = a.n; if (this->n>0) { // allocate and construct objects this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = nullptr; } // Copy number of rows rows_ = a.rows_; } // and copy the data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } return *this; } //===== assignment from scalar //! assign from scalar DenseMatrixBase& operator= (const field_type& k) { (static_cast&>(*this)) = k; return *this; } //===== access to components // has to be overwritten from base class because it must // return access to the windows //! random access to blocks reference operator[] (size_type i) { #ifdef DUNE_ISTL_WITH_CHECKING if (i>=rows_) DUNE_THROW(ISTLError,"index out of range"); #endif return window_type(this->p + i*columns_, columns_); } //! same for read only access const_reference operator[] (size_type i) const { #ifdef DUNE_ISTL_WITH_CHECKING if (i<0 || i>=rows_) DUNE_THROW(ISTLError,"index out of range"); #endif return window_type(this->p + i*columns_, columns_); } // forward declaration class ConstIterator; //! Iterator class for sequential access class Iterator { public: //! constructor, no arguments Iterator () : window_(nullptr,0) { i = 0; } Iterator (Iterator& other) = default; Iterator (Iterator&& other) = default; //! constructor Iterator (B* data, size_type columns, size_type _i) : i(_i), window_(data + _i*columns, columns) {} /** \brief Move assignment */ Iterator& operator=(Iterator&& other) { i = other.i; // Do NOT use window_.operator=, because that copies the window content, not just the window! window_.set(other.window_.getsize(),other.window_.getptr()); return *this; } /** \brief Copy assignment */ Iterator& operator=(Iterator& other) { i = other.i; // Do NOT use window_.operator=, because that copies the window content, not just the window! window_.set(other.window_.getsize(),other.window_.getptr()); return *this; } //! prefix increment Iterator& operator++() { ++i; window_.setptr(window_.getptr()+window_.getsize()); return *this; } //! prefix decrement Iterator& operator--() { --i; window_.setptr(window_.getptr()-window_.getsize()); return *this; } //! equality bool operator== (const Iterator& it) const { return window_.getptr() == it.window_.getptr(); } //! inequality bool operator!= (const Iterator& it) const { return window_.getptr() != it.window_.getptr(); } //! equality bool operator== (const ConstIterator& it) const { return window_.getptr() == it.window_.getptr(); } //! inequality bool operator!= (const ConstIterator& it) const { return window_.getptr() != it.window_.getptr(); } //! dereferencing window_type& operator* () const { return window_; } //! arrow window_type* operator-> () const { return &window_; } // return index corresponding to pointer size_type index () const { return i; } friend class ConstIterator; private: size_type i; mutable window_type window_; }; //! begin Iterator Iterator begin () { return Iterator(this->p, columns_, 0); } //! end Iterator Iterator end () { return Iterator(this->p, columns_, rows_); } //! @returns an iterator that is positioned before //! the end iterator of the vector, i.e. at the last entry. Iterator beforeEnd () { return Iterator(this->p, columns_, rows_-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. Iterator beforeBegin () const { return Iterator(this->p, columns_, -1); } //! random access returning iterator (end if not contained) Iterator find (size_type i) { return Iterator(this->p, columns_, std::min(i,rows_)); } //! random access returning iterator (end if not contained) ConstIterator find (size_type i) const { return ConstIterator(this->p, columns_, std::min(i,rows_)); } //! ConstIterator class for sequential access class ConstIterator { public: //! constructor ConstIterator () : window_(nullptr,0) { i = 0; } //! constructor from pointer ConstIterator (const B* data, size_type columns, size_type _i) : i(_i), window_(const_cast(data + _i * columns), columns) {} //! constructor from non_const iterator ConstIterator (const Iterator& it) : i(it.i), window_(it.window_.getptr(),it.window_.getsize()) {} ConstIterator& operator=(Iterator&& other) { i = other.i; // Do NOT use window_.operator=, because that copies the window content, not just the window! window_.set(other.window_.getsize(),other.window_.getptr()); return *this; } ConstIterator& operator=(Iterator& other) { i = other.i; // Do NOT use window_.operator=, because that copies the window content, not just the window! window_.set(other.window_.getsize(),other.window_.getptr()); return *this; } //! prefix increment ConstIterator& operator++() { ++i; window_.setptr(window_.getptr()+window_.getsize()); return *this; } //! prefix decrement ConstIterator& operator--() { --i; window_.setptr(window_.getptr()-window_.getsize()); return *this; } //! equality bool operator== (const ConstIterator& it) const { return window_.getptr() == it.window_.getptr(); } //! inequality bool operator!= (const ConstIterator& it) const { return window_.getptr() != it.window_.getptr(); } //! equality bool operator== (const Iterator& it) const { return window_.getptr() == it.window_.getptr(); } //! inequality bool operator!= (const Iterator& it) const { return window_.getptr() != it.window_.getptr(); } //! dereferencing const window_type& operator* () const { return window_; } //! arrow const window_type* operator-> () const { return &window_; } // return index corresponding to pointer size_type index () const { return i; } friend class Iterator; private: size_type i; mutable window_type window_; }; /** \brief Export the iterator type using std naming rules */ using iterator = Iterator; /** \brief Export the const iterator type using std naming rules */ using const_iterator = ConstIterator; //! begin ConstIterator ConstIterator begin () const { return ConstIterator(this->p, columns_, 0); } //! end ConstIterator ConstIterator end () const { return ConstIterator(this->p, columns_, rows_); } //! @returns an iterator that is positioned before //! the end iterator of the vector. i.e. at the last element. ConstIterator beforeEnd() const { return ConstIterator(this->p, columns_, rows_-1); } //! end ConstIterator ConstIterator rend () const { return ConstIterator(this->p, columns_, -1); } //===== sizes //! number of blocks in the vector (are of variable size here) size_type N () const { return rows_; } private: size_type rows_; // number of matrix rows size_type columns_; // number of matrix columns A allocator_; }; } // namespace MatrixImp /** \addtogroup ISTL_SPMV \{ */ /** \brief A generic dynamic dense matrix */ template > class Matrix { public: /** \brief Export the type representing the underlying field */ typedef typename T::field_type field_type; /** \brief Export the type representing the components */ typedef T block_type; /** \brief Export the allocator */ typedef A allocator_type; /** \brief The type implementing a matrix row */ typedef typename MatrixImp::DenseMatrixBase::window_type row_type; /** \brief Type for indices and sizes */ typedef typename A::size_type size_type; /** \brief Iterator over the matrix rows */ typedef typename MatrixImp::DenseMatrixBase::Iterator RowIterator; /** \brief Iterator for the entries of each row */ typedef typename row_type::iterator ColIterator; /** \brief Const iterator over the matrix rows */ typedef typename MatrixImp::DenseMatrixBase::ConstIterator ConstRowIterator; /** \brief Const iterator for the entries of each row */ typedef typename row_type::const_iterator ConstColIterator; enum { //! The number of nesting levels the matrix contains. blocklevel = T::blocklevel+1 }; /** \brief Create empty matrix */ Matrix() : data_(0,0), cols_(0) {} /** \brief Create uninitialized matrix of size rows x cols */ Matrix(size_type rows, size_type cols) : data_(rows,cols), cols_(cols) {} /** \brief Change the matrix size * * The way the data is handled is unpredictable. */ void setSize(size_type rows, size_type cols) { data_.resize(rows,cols); cols_ = cols; } /** \brief Get iterator to first row */ RowIterator begin() { return data_.begin(); } /** \brief Get iterator to one beyond last row */ RowIterator end() { return data_.end(); } //! @returns an iterator that is positioned before //! the end iterator of the rows, i.e. at the last row. RowIterator beforeEnd () { return data_.beforeEnd(); } //! @returns an iterator that is positioned before //! the first row of the matrix. RowIterator beforeBegin () { return data_.beforeBegin(); } /** \brief Get const iterator to first row */ ConstRowIterator begin() const { return data_.begin(); } /** \brief Get const iterator to one beyond last row */ ConstRowIterator end() const { return data_.end(); } //! @returns an iterator that is positioned before //! the end iterator of the rows. i.e. at the last row. ConstRowIterator beforeEnd() const { return data_.beforeEnd(); } //! @returns an iterator that is positioned before //! the first row if the matrix. ConstRowIterator beforeBegin () const { return data_.beforeBegin(); } /** \brief Assignment from scalar */ Matrix& operator= (const field_type& t) { data_ = t; return *this; } /** \brief The index operator */ row_type operator[](size_type row) { #ifdef DUNE_ISTL_WITH_CHECKING if (row<0) DUNE_THROW(ISTLError, "Can't access negative rows!"); if (row>=N()) DUNE_THROW(ISTLError, "Row index out of range!"); #endif return data_[row]; } /** \brief The const index operator */ const row_type operator[](size_type row) const { #ifdef DUNE_ISTL_WITH_CHECKING if (row<0) DUNE_THROW(ISTLError, "Can't access negative rows!"); if (row>=N()) DUNE_THROW(ISTLError, "Row index out of range!"); #endif return data_[row]; } /** \brief Return the number of rows */ size_type N() const { return data_.N(); } /** \brief Return the number of columns */ size_type M() const { return cols_; } /** \brief Multiplication with a scalar */ Matrix& operator*=(const field_type& scalar) { data_ *= scalar; return (*this); } /** \brief Division by a scalar */ Matrix& operator/=(const field_type& scalar) { data_ /= scalar; return (*this); } /*! \brief Add the entries of another matrix to this one. * * \param b The matrix to add to this one. Its size has to * be the same as the size of this matrix. */ Matrix& operator+= (const Matrix& b) { #ifdef DUNE_ISTL_WITH_CHECKING if(N()!=b.N() || M() != b.M()) DUNE_THROW(RangeError, "Matrix sizes do not match!"); #endif data_ += b.data_; return (*this); } /*! \brief Subtract the entries of another matrix from this one. * * \param b The matrix to subtract from this one. Its size has to * be the same as the size of this matrix. */ Matrix& operator-= (const Matrix& b) { #ifdef DUNE_ISTL_WITH_CHECKING if(N()!=b.N() || M() != b.M()) DUNE_THROW(RangeError, "Matrix sizes do not match!"); #endif data_ -= b.data_; return (*this); } /** \brief Return the transpose of the matrix */ Matrix transpose() const { Matrix out(M(), N()); for (size_type i=0; i operator*(const Matrix& m1, const Matrix& m2) { Matrix out(m1.N(), m2.M()); out = 0; for (size_type i=0; i friend Y operator*(const Matrix& m, const X& vec) { #ifdef DUNE_ISTL_WITH_CHECKING if (m.M()!=vec.size()) DUNE_THROW(ISTLError, "Vector size doesn't match the number of matrix columns!"); #endif Y out(m.N()); out = 0; for (size_type i=0; i void mv(const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif for (size_type i=0; i void mtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range"); if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range"); #endif for(size_type i=0; i void umv(const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif for (size_type i=0; i void mmv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmv(x[j.index()],y[i.index()]); } } /** \brief \f$ y += \alpha A x \f$ */ template void usmv(const field_type& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif for (size_type i=0; i void umtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umtv(x[i.index()],y[j.index()]); } } //! y -= A^T x template void mmtv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmtv(x[i.index()],y[j.index()]); } } //! y += alpha A^T x template void usmtv (const field_type& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).usmtv(alpha,x[i.index()],y[j.index()]); } } //! y += A^H x template void umhv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).umhv(x[i.index()],y[j.index()]); } } //! y -= A^H x template void mmhv (const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).mmhv(x[i.index()],y[j.index()]); } } //! y += alpha A^H x template void usmhv (const field_type& alpha, const X& x, Y& y) const { #ifdef DUNE_ISTL_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!"); #endif ConstRowIterator endi=end(); for (ConstRowIterator i=begin(); i!=endi; ++i) { ConstColIterator endj = (*i).end(); for (ConstColIterator j=(*i).begin(); j!=endj; ++j) (*j).usmhv(alpha,x[i.index()],y[j.index()]); } } //===== norms //! frobenius norm: sqrt(sum over squared values of entries) typename FieldTraits::real_type frobenius_norm () const { return std::sqrt(frobenius_norm2()); } //! square of frobenius norm, need for block recursion typename FieldTraits::real_type frobenius_norm2 () const { double sum=0; for (size_type i=0; i::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm(); norm = max(sum, norm); } return norm; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm_real(); norm = max(sum, norm); } return norm; } //! infinity norm (row sum norm, how to generalize for blocks?) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm(); norm = max(sum, norm); isNaN += sum; } isNaN /= isNaN; return norm * isNaN; } //! simplified infinity norm (uses Manhattan norm for complex values) template ::value, int>::type = 0> typename FieldTraits::real_type infinity_norm_real() const { using real_type = typename FieldTraits::real_type; using std::max; real_type norm = 0; real_type isNaN = 1; for (auto const &x : *this) { real_type sum = 0; for (auto const &y : x) sum += y.infinity_norm_real(); norm = max(sum, norm); isNaN += sum; } isNaN /= isNaN; return norm * isNaN; } //===== query //! return true if (i,j) is in pattern bool exists (size_type i, size_type j) const { #ifdef DUNE_ISTL_WITH_CHECKING if (i<0 || i>=N()) DUNE_THROW(ISTLError,"row index out of range"); if (j<0 || i>=M()) DUNE_THROW(ISTLError,"column index out of range"); #else DUNE_UNUSED_PARAMETER(i); DUNE_UNUSED_PARAMETER(j); #endif return true; } protected: /** \brief Abuse DenseMatrixBase as an engine for a 2d array ISTL-style */ MatrixImp::DenseMatrixBase data_; /** \brief Number of columns of the matrix In general you can extract the same information from the data_ member. However if you want to be able to properly handle 0xn matrices then you need a separate member. */ size_type cols_; }; /** \} */ } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/matrixindexset.hh000066400000000000000000000057701313314427100207320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIXINDEXSET_HH #define DUNE_ISTL_MATRIXINDEXSET_HH #include #include namespace Dune { /** \brief Stores the nonzero entries in a sparse matrix */ class MatrixIndexSet { public: typedef std::size_t size_type; /** \brief Default constructor */ MatrixIndexSet() : rows_(0), cols_(0) {} /** \brief Constructor setting the matrix size */ MatrixIndexSet(size_type rows, size_type cols) : rows_(rows), cols_(cols) { indices_.resize(rows_); } /** \brief Reset the size of an index set */ void resize(size_type rows, size_type cols) { rows_ = rows; cols_ = cols; indices_.resize(rows_); } /** \brief Add an index to the index set */ void add(size_type i, size_type j) { indices_[i].insert(j); } /** \brief Return the number of entries */ size_type size() const { size_type entries = 0; for (size_type i=0; i \param m reference to the MatrixType object \param rowOffset don't write to rows void import(const MatrixType& m, size_type rowOffset=0, size_type colOffset=0) { typedef typename MatrixType::row_type RowType; typedef typename RowType::ConstIterator ColumnIterator; for (size_type rowIdx=0; rowIdx \param matrix reference to the MatrixType object */ template void exportIdx(MatrixType& matrix) const { matrix.setSize(rows_, cols_); matrix.setBuildMode(MatrixType::random); for (size_type i=0; i::iterator it = indices_[i].begin(); for (; it!=indices_[i].end(); ++it) matrix.addindex(i, *it); } matrix.endindices(); } private: std::vector > indices_; size_type rows_, cols_; }; } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/matrixmarket.hh000066400000000000000000000763031313314427100203720ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIXMARKET_HH #define DUNE_ISTL_MATRIXMARKET_HH #include #include #include #include #include #include #include #include "matrixutils.hh" #include "bcrsmatrix.hh" #include "owneroverlapcopy.hh" #include #include namespace Dune { /** * @defgroup ISTL_IO IO for matrices and vectors. * @ingroup ISTL_SPMV * @brief Provides methods for reading and writing matrices and vectors * in various formats. * * * Routine printmatrix prints a (sparse matrix with all entries (even zeroes). * Function printvector prints a vector to a stream. * PrintSparseMatrix prints a sparse matrix omitting all nonzeroes. * With writeMatrixToMatlab one can write a matrix in a Matlab readable format. * Using storeMartrixMarket and loadMatrixMarket one can store and load a parallel ISTL * matrix in MatrixMarket format. The latter can even read a matrix written with * writeMatrixToMatlab. * * * @addtogroup ISTL_IO * @{ */ /** @file * @author Markus Blatt * @brief Provides classes for reading and writing MatrixMarket Files with * an extension for parallel matrices. */ namespace MatrixMarketImpl { /** * @brief Helper metaprogram to get * the matrix market string representation * of the numeric type. * * Member function mm_numeric_type::c_str() * returns the string representation of * the type. */ template struct mm_numeric_type { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=false }; }; template<> struct mm_numeric_type { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=true }; static std::string str() { return "integer"; } }; template<> struct mm_numeric_type { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=true }; static std::string str() { return "real"; } }; template<> struct mm_numeric_type { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=true }; static std::string str() { return "real"; } }; template<> struct mm_numeric_type > { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=true }; static std::string str() { return "complex"; } }; template<> struct mm_numeric_type > { enum { /** * @brief Whether T is a supported numeric type. */ is_numeric=true }; static std::string str() { return "complex"; } }; /** * @brief Meta program to write the correct Matrix Market * header. * * Member function mm_header::operator() writes the header. * * @tparam M The matrix type. */ template struct mm_header_printer; template struct mm_header_printer,A> > { static void print(std::ostream& os) { os<<"%%MatrixMarket matrix coordinate "; os<::str()<<" general"< struct mm_header_printer > { static void print(std::ostream& os) { os<<"%%MatrixMarket matrix array "; os<::str()<<" general"< struct mm_header_printer > { static void print(std::ostream& os) { os<<"%%MatrixMarket matrix array "; os<::str()<<" general"< struct mm_header_printer > { static void print(std::ostream& os) { os<<"%%MatrixMarket matrix array "; os<::str()<<" general"< struct mm_block_structure_header; template struct mm_block_structure_header,A> > { typedef BlockVector,A> M; static void print(std::ostream& os, const M&) { os<<"% ISTL_STRUCT blocked "; os< struct mm_block_structure_header,A> > { typedef BCRSMatrix,A> M; static void print(std::ostream& os, const M&) { os<<"% ISTL_STRUCT blocked "; os< struct mm_block_structure_header > { typedef FieldMatrix M; static void print(std::ostream& os, const M& m) {} }; template struct mm_block_structure_header > { typedef FieldVector M; static void print(std::ostream& os, const M& m) {} }; enum LineType { MM_HEADER, MM_ISTLSTRUCT, DATA }; enum { MM_MAX_LINE_LENGTH=1025 }; enum MM_TYPE { coordinate_type, array_type, unknown_type }; enum MM_CTYPE { integer_type, double_type, complex_type, pattern, unknown_ctype }; enum MM_STRUCTURE { general, symmetric, skew_symmetric, hermitian, unknown_structure }; struct MMHeader { MMHeader() : type(coordinate_type), ctype(double_type), structure(general) {} MM_TYPE type; MM_CTYPE ctype; MM_STRUCTURE structure; }; inline bool lineFeed(std::istream& file) { char c; if(!file.eof()) c=file.peek(); else return false; // ignore whitespace while(c==' ') { file.get(); if(file.eof()) return false; c=file.peek(); } if(c=='\n') { /* eat the line feed */ file.get(); return true; } return false; } inline void skipComments(std::istream& file) { lineFeed(file); char c=file.peek(); // ignore comment lines while(c=='%') { /* discard the rest of the line */ file.ignore(std::numeric_limits::max(),'\n'); c=file.peek(); } } inline bool readMatrixMarketBanner(std::istream& file, MMHeader& mmHeader) { std::string buffer; char c; file >> buffer; c=buffer[0]; mmHeader=MMHeader(); if(c!='%') return false; std::cout<::max(),'\n'); return false; } if(lineFeed(file)) /* premature end of line */ return false; /* read the matrix_type */ file >> buffer; if(buffer != "matrix") { /* discard the rest of the line */ file.ignore(std::numeric_limits::max(),'\n'); return false; } if(lineFeed(file)) /* premature end of line */ return false; /* The type of the matrix */ file >> buffer; if(buffer.empty()) return false; std::transform(buffer.begin(), buffer.end(), buffer.begin(), tolower); switch(buffer[0]) { case 'a' : /* sanity check */ if(buffer != "array") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.type=array_type; break; case 'c' : /* sanity check */ if(buffer != "coordinate") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.type=coordinate_type; break; default : file.ignore(std::numeric_limits::max(),'\n'); return false; } if(lineFeed(file)) /* premature end of line */ return false; /* The numeric type used. */ file >> buffer; if(buffer.empty()) return false; std::transform(buffer.begin(), buffer.end(), buffer.begin(), tolower); switch(buffer[0]) { case 'i' : /* sanity check */ if(buffer != "integer") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.ctype=integer_type; break; case 'r' : /* sanity check */ if(buffer != "real") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.ctype=double_type; break; case 'c' : /* sanity check */ if(buffer != "complex") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.ctype=complex_type; break; case 'p' : /* sanity check */ if(buffer != "pattern") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.ctype=pattern; break; default : file.ignore(std::numeric_limits::max(),'\n'); return false; } if(lineFeed(file)) return false; file >> buffer; std::transform(buffer.begin(), buffer.end(), buffer.begin(), tolower); switch(buffer[0]) { case 'g' : /* sanity check */ if(buffer != "general") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.structure=general; break; case 'h' : /* sanity check */ if(buffer != "hermitian") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.structure=hermitian; break; case 's' : if(buffer.size()==1) { file.ignore(std::numeric_limits::max(),'\n'); return false; } switch(buffer[1]) { case 'y' : /* sanity check */ if(buffer != "symmetric") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.structure=symmetric; break; case 'k' : /* sanity check */ if(buffer != "skew-symmetric") { file.ignore(std::numeric_limits::max(),'\n'); return false; } mmHeader.structure=skew_symmetric; break; default : file.ignore(std::numeric_limits::max(),'\n'); return false; } default : file.ignore(std::numeric_limits::max(),'\n'); return false; } file.ignore(std::numeric_limits::max(),'\n'); c=file.peek(); return true; } template std::tuple calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries, const MMHeader& header) { std::size_t blockrows=rows/brows; std::size_t blockcols=cols/bcols; std::size_t blocksize=brows*bcols; std::size_t blockentries=0; switch(header.structure) { case general : blockentries = entries/blocksize; break; case skew_symmetric : blockentries = 2*entries/blocksize; break; case symmetric : blockentries = (2*entries-rows)/blocksize; break; case hermitian : blockentries = (2*entries-rows)/blocksize; break; default : throw Dune::NotImplemented(); } return std::make_tuple(blockrows, blockcols, blockentries); } /* * @brief Storage class for the column index and the numeric value. * * \tparam T Either a NumericWrapper of the numeric type or PatternDummy * for MatrixMarket pattern case. */ template struct IndexData : public T { std::size_t index; }; /** * @brief a wrapper class of numeric values. * * Use for template specialization to catch the pattern * type MatrixMarket matrices. Uses Empty base class optimization * in the pattern case. * * @tparam T Either a NumericWrapper of the numeric type or PatternDummy * for MatrixMarket pattern case. */ template struct NumericWrapper { T number; operator T&() { return number; } }; /** * @brief Utility class for marking the pattern type of the MatrixMarket matrices. */ struct PatternDummy {}; template<> struct NumericWrapper {}; template std::istream& operator>>(std::istream& is, NumericWrapper& num) { return is>>num.number; } inline std::istream& operator>>(std::istream& is, NumericWrapper& num) { DUNE_UNUSED_PARAMETER(num); return is; } /** * @brief LessThan operator. * * It simply compares the index. */ template bool operator<(const IndexData& i1, const IndexData& i2) { return i1.index std::istream& operator>>(std::istream& is, IndexData& data) { is>>data.index; /* MatrixMarket indices are one based. Decrement for C++ */ --data.index; return is>>data.number; } /** * @brief Functor to the data values of the matrix. * * This is specialized for PatternDummy. The specialization does not * set anything. */ template struct MatrixValuesSetter { /** * @brief Sets the matrixvalues. * @param row The row data as read from file. * @param matrix The matrix whose data we set. */ template void operator()(const std::vector > >& rows, M& matrix) { for(typename M::RowIterator iter=matrix.begin(); iter!= matrix.end(); ++iter) { for(typename M::size_type brow=iter.index()*brows, browend=iter.index()*brows+brows; brow >::const_iterator Siter; for(Siter siter=rows[brow].begin(), send=rows[brow].end(); siter != send; ++siter) (*iter)[siter->index/bcols][brow%brows][siter->index%bcols]=siter->number; } } } }; template struct MatrixValuesSetter { template void operator()(const std::vector > >& rows, M& matrix) {} }; template void readSparseEntries(Dune::BCRSMatrix,A>& matrix, std::istream& file, std::size_t entries, const MMHeader& mmHeader, const D&) { typedef Dune::BCRSMatrix,A> Matrix; // First path // store entries together with column index in a speparate // data structure std::vector > > rows(matrix.N()*brows); for(; entries>0; --entries) { std::size_t row; IndexData data; skipComments(file); file>>row; --row; // Index was 1 based. assert(row/bcols>data; assert(data.index/bcols >::const_iterator Siter; for(Siter siter=rows[brow].begin(), send=rows[brow].end(); siter != send; ++siter, ++nnz) iter.insert(siter->index/bcols); } } //Set the matrix values matrix=0; MatrixValuesSetter Setter; Setter(rows, matrix); } } // end namespace MatrixMarketImpl class MatrixMarketFormatError : public Dune::Exception {}; inline void mm_read_header(std::size_t& rows, std::size_t& cols, MatrixMarketImpl::MMHeader& header, std::istream& istr, bool isVector) { using namespace MatrixMarketImpl; if(!readMatrixMarketBanner(istr, header)) { std::cerr << "First line was not a correct Matrix Market banner. Using default:\n" << "%%MatrixMarket matrix coordinate real general"<> rows; if(lineFeed(istr)) throw MatrixMarketFormatError(); istr >> cols; } template void mm_read_vector_entries(Dune::BlockVector,A>& vector, std::size_t size, std::istream& istr) { for(int i=0; size>0; ++i, --size) { T val; istr>>val; vector[i/entries][i%entries]=val; } } /** * @brief Reads a BlockVector from a matrix market file. * @param vector The vector to store the data in. * @param istr The input stream to read the data from. * @warning Not all formats are supported! */ template void readMatrixMarket(Dune::BlockVector,A>& vector, std::istream& istr) { using namespace MatrixMarketImpl; MMHeader header; std::size_t rows, cols; mm_read_header(rows,cols,header,istr, true); if(cols!=1) DUNE_THROW(MatrixMarketFormatError, "cols!=1, therefore this is no vector!"); if(header.type!=array_type) DUNE_THROW(MatrixMarketFormatError, "Vectors have to be stored in array format!"); std::size_t size=rows/entries; if(size*entries!=rows) DUNE_THROW(MatrixMarketFormatError, "Block size of vector is not correct!"); vector.resize(size); istr.ignore(std::numeric_limits::max(),'\n'); mm_read_vector_entries(vector, rows, istr); } /** * @brief Reads a sparse matrix from a matrix market file. * @param matrix The matrix to store the data in. * @param istr The input stream to read the data from. * @warning Not all formats are supported! */ template void readMatrixMarket(Dune::BCRSMatrix,A>& matrix, std::istream& istr) { using namespace MatrixMarketImpl; MMHeader header; if(!readMatrixMarketBanner(istr, header)) { std::cerr << "First line was not a correct Matrix Market banner. Using default:\n" << "%%MatrixMarket matrix coordinate real general"<> rows; if(lineFeed(istr)) throw MatrixMarketFormatError(); istr >> cols; if(lineFeed(istr)) throw MatrixMarketFormatError(); istr >>entries; std::size_t nnz, blockrows, blockcols; std::tie(blockrows, blockcols, nnz) = calculateNNZ(rows, cols, entries, header); istr.ignore(std::numeric_limits::max(),'\n'); matrix.setSize(blockrows, blockcols); matrix.setBuildMode(Dune::BCRSMatrix,A>::row_wise); if(header.type==array_type) DUNE_THROW(Dune::NotImplemented, "Array format currently not supported for matrices!"); readSparseEntries(matrix, istr, entries, header, NumericWrapper()); } template struct mm_multipliers {}; template struct mm_multipliers,A> > { enum { rows = i, cols = j }; }; template void mm_print_entry(const FieldMatrix& entry, typename FieldMatrix::size_type rowidx, typename FieldMatrix::size_type colidx, std::ostream& ostr) { typedef typename FieldMatrix::const_iterator riterator; typedef typename FieldMatrix::ConstColIterator citerator; for(riterator row=entry.begin(); row != entry.end(); ++row, ++rowidx) { int coli=colidx; for(citerator col = row->begin(); col != row->end(); ++col, ++coli) ostr<< rowidx<<" "< void mm_print_vector_entry(const V& entry, std::ostream& ostr, const std::integral_constant&) { ostr< void mm_print_vector_entry(const V& vector, std::ostream& ostr, const std::integral_constant&) { using namespace MatrixMarketImpl; // Is the entry a supported numeric type? const int isnumeric = mm_numeric_type::is_numeric; typedef typename V::const_iterator VIter; for(VIter i=vector.begin(); i != vector.end(); ++i) mm_print_vector_entry(*i, ostr, std::integral_constant()); } template std::size_t countEntries(const BlockVector,A>& vector) { return vector.size()*i; } // Version for writing vectors. template void writeMatrixMarket(const V& vector, std::ostream& ostr, const std::integral_constant&) { using namespace MatrixMarketImpl; ostr<::is_numeric; mm_print_vector_entry(vector,ostr, std::integral_constant()); } // Versions for writing matrices template void writeMatrixMarket(const M& matrix, std::ostream& ostr, const std::integral_constant&) { ostr<::rows<<" " <::cols<<" " <begin(); col != row->end(); ++col) // Matrix Market indexing start with 1! mm_print_entry(*col, row.index()*mm_multipliers::rows+1, col.index()*mm_multipliers::cols+1, ostr); } /** * @brief writes a ISTL matrix or vector to a stream in matrix market format. */ template void writeMatrixMarket(const M& matrix, std::ostream& ostr) { using namespace MatrixMarketImpl; // Write header information mm_header_printer::print(ostr); mm_block_structure_header::print(ostr,matrix); // Choose the correct function for matrix and vector writeMatrixMarket(matrix,ostr,std::integral_constant::value>()); } /** * @brief Stores a parallel matrix/vector in matrix market format in a file. * * More about the matrix market exchange format can be found * here. * * @param matrix The matrix/vector to store. * @param filename the name of the filename (without suffix and rank!) * rank i will write the file filename_i.mm */ template void storeMatrixMarket(const M& matrix, std::string filename) { std::ofstream file(filename.c_str()); file.setf(std::ios::scientific,std::ios::floatfield); writeMatrixMarket(matrix, file); file.close(); } #if HAVE_MPI /** * @brief Stores a parallel matrix/vector in matrix market format in a file. * * More about the matrix market exchange format can be found * here. * * @param matrix The matrix/vector to store. * @param filename the name of the filename (without suffix and rank!) * rank i will write the file filename_i.mm * @param comm The information about the data distribution. * @param storeIndices Whether to store the parallel index information. * If true rank i writes the index information to file filename_i.idx. */ template void storeMatrixMarket(const M& matrix, std::string filename, const OwnerOverlapCopyCommunication& comm, bool storeIndices=true) { // Get our rank int rank = comm.communicator().rank(); // Write the local matrix std::ostringstream rfilename; rfilename<::ParallelIndexSet IndexSet; typedef typename IndexSet::const_iterator Iterator; for(Iterator iter = comm.indexSet().begin(); iter != comm.indexSet().end(); ++iter) { file << iter->global()<<" "<<(std::size_t)iter->local()<<" " <<(int)iter->local().attribute()<<" "<<(int)iter->local().isPublic()<& neighbours=comm.remoteIndices().getNeighbours(); typedef std::set::const_iterator SIter; for(SIter neighbour=neighbours.begin(); neighbour != neighbours.end(); ++neighbour) { file<<" "<< *neighbour; } file.close(); } /** * @brief Load a parallel matrix/vector stored in matrix market format. * * More about the matrix market exchange format can be found * here. * * @param matrix Where to store the matrix/vector. * @param filename the name of the filename (without suffix and rank!) * rank i will read the file filename_i.mm * @param comm The information about the data distribution. * @param readIndices Whether to read the parallel index information. * If true rank i reads the index information form file filename_i.idx * And builds the remote indices information. */ template void loadMatrixMarket(M& matrix, const std::string& filename, OwnerOverlapCopyCommunication& comm, bool readIndices=true) { using namespace MatrixMarketImpl; typedef typename OwnerOverlapCopyCommunication::ParallelIndexSet::LocalIndex LocalIndex; typedef typename LocalIndex::Attribute Attribute; // Get our rank int rank = comm.communicator().rank(); // load local matrix std::ostringstream rfilename; rfilename<::ParallelIndexSet IndexSet; IndexSet& pis=comm.pis; rfilename.str(""); rfilename<>g; std::size_t l; file >>l; int c; file >>c; bool b; file >> b; pis.add(g,LocalIndex(l,Attribute(c),b)); lineFeed(file); } pis.endResize(); if(!file.eof()) { // read neighbours std::string s; file>>s; if(s!="neighbours:") DUNE_THROW(MatrixMarketFormatError, "was expecting the string: \"neighbours:\""); std::set nb; while(!file.eof()) { int i; file >> i; nb.insert(i); } file.close(); comm.ri.setNeighbours(nb); } comm.ri.template rebuild(); } #endif /** * @brief Load a matrix/vector stored in matrix market format. * * More about the matrix market exchange format can be found * here. * * @param matrix Where to store the matrix/vector. * @param filename the name of the filename (without suffix and rank!) * rank i will read the file filename_i.mm */ template void loadMatrixMarket(M& matrix, const std::string& filename) { std::ifstream file; file.open(filename.c_str(), std::ios::in); if(!file) DUNE_THROW(IOError, "Could not open file: " << filename); readMatrixMarket(matrix,file); file.close(); } /** @} */ } #endif dune-istl-2.5.1/dune/istl/matrixmatrix.hh000066400000000000000000000462211313314427100204070ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIXMATRIX_HH #define DUNE_ISTL_MATRIXMATRIX_HH #include #include #include #include namespace Dune { /** * @addtogroup ISTL_SPMV * * @{ */ /** @file * @author Markus Blatt * @brief provides functions for sparse matrix matrix multiplication. */ namespace { /** * @brief Traverses over the nonzero pattern of the matrix-matrix product. * * Template parameter b is used to select the matrix product: *
0
\f$A\cdot B\f$
*
1
\f$A^T\cdot B\f$
*
2
\f$A\cdot B^T\f$
*/ template struct NonzeroPatternTraverser {}; template<> struct NonzeroPatternTraverser<0> { template static void traverse(const Dune::BCRSMatrix,A1>& A, const Dune::BCRSMatrix,A2>& B, F& func) { if(A.M()!=B.N()) DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<,A1>::ConstRowIterator Row; typedef typename Dune::BCRSMatrix,A1>::ConstColIterator Col; typedef typename Dune::BCRSMatrix,A2>::ConstColIterator BCol; for(Row row= A.begin(); row != A.end(); ++row) { // Loop over all column entries for(Col col = row->begin(); col != row->end(); ++col) { // entry at i,k // search for all nonzeros in row k for(BCol bcol = B[col.index()].begin(); bcol != B[col.index()].end(); ++bcol) { func(*col, *bcol, row.index(), bcol.index()); } } } } }; template<> struct NonzeroPatternTraverser<1> { template static void traverse(const Dune::BCRSMatrix,A1>& A, const Dune::BCRSMatrix,A2>& B, F& func) { if(A.N()!=B.N()) DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<,A1>::ConstRowIterator Row; typedef typename Dune::BCRSMatrix,A1>::ConstColIterator Col; typedef typename Dune::BCRSMatrix,A2>::ConstColIterator BCol; for(Row row=A.begin(); row!=A.end(); ++row) { for(Col col=row->begin(); col!=row->end(); ++col) { for(BCol bcol = B[row.index()].begin(); bcol != B[row.index()].end(); ++bcol) { func(*col, *bcol, col.index(), bcol.index()); } } } } }; template<> struct NonzeroPatternTraverser<2> { template static void traverse(const BCRSMatrix,A1>& mat, const BCRSMatrix,A2>& matt, F& func) { if(mat.M()!=matt.M()) DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<,A1>::ConstRowIterator row_iterator; typedef typename BCRSMatrix,A1>::ConstColIterator col_iterator; typedef typename BCRSMatrix,A2>::ConstRowIterator row_iterator_t; typedef typename BCRSMatrix,A2>::ConstColIterator col_iterator_t; for(row_iterator mrow=mat.begin(); mrow != mat.end(); ++mrow) { //iterate over the column entries // mt is a transposed matrix crs therefore it is treated as a ccs matrix // and the row_iterator iterates over the columns of the transposed matrix. // search the row of the transposed matrix for an entry with the same index // as the mcol iterator for(row_iterator_t mtcol=matt.begin(); mtcol != matt.end(); ++mtcol) { //Search for col entries in mat that have a corrsponding row index in matt // (i.e. corresponding col index in the as this is the transposed matrix col_iterator_t mtrow=mtcol->begin(); bool funcCalled = false; for(col_iterator mcol=mrow->begin(); mcol != mrow->end(); ++mcol) { // search // TODO: This should probably be substituted by a binary search for( ; mtrow != mtcol->end(); ++mtrow) if(mtrow.index()>=mcol.index()) break; if(mtrow != mtcol->end() && mtrow.index()==mcol.index()) { func(*mcol, *mtrow, mtcol.index()); funcCalled = true; // In some cases we only search for one pair, then we break here // and continue with the next column. if(F::do_break) break; } } // move on with func only if func was called, otherwise they might // get out of sync if (funcCalled) func.nextCol(); } func.nextRow(); } } }; template class SparsityPatternInitializer { public: enum {do_break=true}; typedef typename BCRSMatrix,A>::CreateIterator CreateIterator; typedef typename BCRSMatrix,A>::size_type size_type; SparsityPatternInitializer(CreateIterator iter) : rowiter(iter) {} template void operator()(const T1&, const T2&, size_type j) { rowiter.insert(j); } void nextRow() { ++rowiter; } void nextCol() {} private: CreateIterator rowiter; }; template class MatrixInitializer { public: enum {do_break=true}; typedef typename Dune::BCRSMatrix,TA> Matrix; typedef typename Matrix::CreateIterator CreateIterator; typedef typename Matrix::size_type size_type; MatrixInitializer(Matrix& A_, size_type) : count(0), A(A_) {} template void operator()(const T1&, const T2&, int) { ++count; } void nextCol() {} void nextRow() {} std::size_t nonzeros() { return count; } template void initPattern(const BCRSMatrix,A1>& mat1, const BCRSMatrix,A2>& mat2) { SparsityPatternInitializer sparsity(A.createbegin()); NonzeroPatternTraverser::traverse(mat1,mat2,sparsity); } private: std::size_t count; Matrix& A; }; template class MatrixInitializer<1,T,TA,n,m> { public: enum {do_break=false}; typedef Dune::BCRSMatrix,TA> Matrix; typedef typename Matrix::CreateIterator CreateIterator; typedef typename Matrix::size_type size_type; MatrixInitializer(Matrix& A_, size_type rows) : A(A_), entries(rows) {} template void operator()(const T1&, const T2&, size_type i, size_type j) { entries[i].insert(j); } void nextCol() {} size_type nonzeros() { size_type nnz=0; typedef typename std::vector >::const_iterator Iter; for(Iter iter = entries.begin(); iter != entries.end(); ++iter) nnz+=(*iter).size(); return nnz; } template void initPattern(const BCRSMatrix,A1>&, const BCRSMatrix,A2>&) { typedef typename std::vector >::const_iterator Iter; CreateIterator citer = A.createbegin(); for(Iter iter = entries.begin(); iter != entries.end(); ++iter, ++citer) { typedef std::set::const_iterator SetIter; for(SetIter index=iter->begin(); index != iter->end(); ++index) citer.insert(*index); } } private: Matrix& A; std::vector > entries; }; template struct MatrixInitializer<0,T,TA,n,m> : public MatrixInitializer<1,T,TA,n,m> { MatrixInitializer(Dune::BCRSMatrix,TA>& A_, typename Dune::BCRSMatrix,TA>::size_type rows) : MatrixInitializer<1,T,TA,n,m>(A_,rows) {} }; template void addMatMultTransposeMat(FieldMatrix& res, const FieldMatrix& mat, const FieldMatrix& matt) { typedef typename FieldMatrix::size_type size_type; for(size_type row=0; row void addTransposeMatMultMat(FieldMatrix& res, const FieldMatrix& mat, const FieldMatrix& matt) { typedef typename FieldMatrix::size_type size_type; for(size_type i=0; i void addMatMultMat(FieldMatrix& res, const FieldMatrix& mat, const FieldMatrix& matt) { typedef typename FieldMatrix::size_type size_type; for(size_type row=0; row class EntryAccumulatorFather { public: enum {do_break=false}; typedef BCRSMatrix,A> Matrix; typedef typename Matrix::RowIterator Row; typedef typename Matrix::ColIterator Col; EntryAccumulatorFather(Matrix& mat_) : mat(mat_), row(mat.begin()) { mat=0; col=row->begin(); } void nextRow() { ++row; if(row!=mat.end()) col=row->begin(); } void nextCol() { ++this->col; } protected: Matrix& mat; private: Row row; protected: Col col; }; template class EntryAccumulator : public EntryAccumulatorFather { public: typedef BCRSMatrix,A> Matrix; typedef typename Matrix::size_type size_type; EntryAccumulator(Matrix& mat_) : EntryAccumulatorFather(mat_) {} template void operator()(const T1& t1, const T2& t2, size_type i) { assert(this->col.index()==i); addMatMultMat(*(this->col),t1,t2); } }; template class EntryAccumulator : public EntryAccumulatorFather { public: typedef BCRSMatrix,A> Matrix; typedef typename Matrix::size_type size_type; EntryAccumulator(Matrix& mat_) : EntryAccumulatorFather(mat_) {} template void operator()(const T1& t1, const T2& t2, size_type i, size_type j) { addMatMultMat(this->mat[i][j], t1, t2); } }; template class EntryAccumulator : public EntryAccumulatorFather { public: typedef BCRSMatrix,A> Matrix; typedef typename Matrix::size_type size_type; EntryAccumulator(Matrix& mat_) : EntryAccumulatorFather(mat_) {} template void operator()(const T1& t1, const T2& t2, size_type i, size_type j) { addTransposeMatMultMat(this->mat[i][j], t1, t2); } }; template class EntryAccumulator : public EntryAccumulatorFather { public: typedef BCRSMatrix,A> Matrix; typedef typename Matrix::size_type size_type; EntryAccumulator(Matrix& mat_) : EntryAccumulatorFather(mat_) {} template void operator()(const T1& t1, const T2& t2, size_type i) { DUNE_UNUSED_PARAMETER(i); assert(this->col.index()==i); addMatMultTransposeMat(*this->col,t1,t2); } }; template struct SizeSelector {}; template<> struct SizeSelector<0> { template static std::tuple size(const M1& m1, const M2& m2) { return std::make_tuple(m1.N(), m2.M()); } }; template<> struct SizeSelector<1> { template static std::tuple size(const M1& m1, const M2& m2) { return std::make_tuple(m1.M(), m2.M()); } }; template<> struct SizeSelector<2> { template static std::tuple size(const M1& m1, const M2& m2) { return std::make_tuple(m1.N(), m2.N()); } }; template void matMultMat(BCRSMatrix,A>& res, const BCRSMatrix,A1>& mat1, const BCRSMatrix,A2>& mat2) { // First step is to count the number of nonzeros typename BCRSMatrix,A>::size_type rows, cols; std::tie(rows,cols)=SizeSelector::size(mat1, mat2); MatrixInitializer patternInit(res, rows); Timer timer; NonzeroPatternTraverser::traverse(mat1,mat2,patternInit); res.setSize(rows, cols, patternInit.nonzeros()); res.setBuildMode(BCRSMatrix,A>::row_wise); //std::cout<<"Counting nonzeros took "< entriesAccu(res); NonzeroPatternTraverser::traverse(mat1,mat2,entriesAccu); //std::cout<<"Calculating entries took "< struct MatMultMatResult {}; template struct MatMultMatResult,FieldMatrix > { typedef FieldMatrix type; }; template struct MatMultMatResult,A >,BCRSMatrix,A1 > > { typedef BCRSMatrix,FieldMatrix >::type, std::allocator,FieldMatrix >::type> > type; }; /** * @brief Helper TMP to get the result type of a sparse matrix matrix multiplication (\f$C=A*B\f$) * * The type of matrix C will be stored as the associated type MatMultMatResult::type. * @tparam M1 The type of matrix A. * @tparam M2 The type of matrix B. */ template struct TransposedMatMultMatResult {}; template struct TransposedMatMultMatResult,FieldMatrix > { typedef FieldMatrix type; }; template struct TransposedMatMultMatResult,A >,BCRSMatrix,A1 > > { typedef BCRSMatrix,FieldMatrix >::type, std::allocator,FieldMatrix >::type> > type; }; /** * @brief Calculate product of a sparse matrix with a transposed sparse matrices (\f$C=A*B^T\f$). * * @param res Matrix for the result of the computation. * @param mat Matrix A. * @param matt Matrix B, which will be transposed before the multiplication. * @param tryHard ignored */ template void matMultTransposeMat(BCRSMatrix,A>& res, const BCRSMatrix,A1>& mat, const BCRSMatrix,A2>& matt, bool tryHard=false) { DUNE_UNUSED_PARAMETER(tryHard); matMultMat<2>(res,mat, matt); } /** * @brief Calculate product of two sparse matrices (\f$C=A*B\f$). * * @param res Matrix for the result of the computation. * @param mat Matrix A. * @param matt Matrix B. * @param tryHard ignored */ template void matMultMat(BCRSMatrix,A>& res, const BCRSMatrix,A1>& mat, const BCRSMatrix,A2>& matt, bool tryHard=false) { matMultMat<0>(res,mat, matt); } /** * @brief Calculate product of a transposed sparse matrix with another sparse matrices (\f$C=A^T*B\f$). * * @param res Matrix for the result of the computation. * @param mat Matrix A, which will be transposed before the multiplication. * @param matt Matrix B. * @param tryHard ignored */ template void transposeMatMultMat(BCRSMatrix,A>& res, const BCRSMatrix,A1>& mat, const BCRSMatrix,A2>& matt, bool tryHard=false) { DUNE_UNUSED_PARAMETER(tryHard); matMultMat<1>(res,mat, matt); } } #endif dune-istl-2.5.1/dune/istl/matrixredistribute.hh000066400000000000000000000710451313314427100216120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIXREDISTRIBUTE_HH #define DUNE_ISTL_MATRIXREDISTRIBUTE_HH #include #include "repartition.hh" #include #include #include #include #include /** * @file * @brief Functionality for redistributing a sparse matrix. * @author Markus Blatt */ namespace Dune { template struct RedistributeInformation { bool isSetup() const { return false; } template void redistribute(const D& from, D& to) const { DUNE_UNUSED_PARAMETER(from); DUNE_UNUSED_PARAMETER(to); } template void redistributeBackward(D& from, const D& to) const { DUNE_UNUSED_PARAMETER(from); DUNE_UNUSED_PARAMETER(to); } void resetSetup() {} void setNoRows(std::size_t size) { DUNE_UNUSED_PARAMETER(size); } void setNoCopyRows(std::size_t size) { DUNE_UNUSED_PARAMETER(size); } void setNoBackwardsCopyRows(std::size_t size) { DUNE_UNUSED_PARAMETER(size); } std::size_t getRowSize(std::size_t index) const { DUNE_UNUSED_PARAMETER(index); return -1; } std::size_t getCopyRowSize(std::size_t index) const { DUNE_UNUSED_PARAMETER(index); return -1; } std::size_t getBackwardsCopyRowSize(std::size_t index) const { DUNE_UNUSED_PARAMETER(index); return -1; } }; #if HAVE_MPI template class RedistributeInformation > { public: typedef OwnerOverlapCopyCommunication Comm; RedistributeInformation() : interface(), setup_(false) {} RedistributeInterface& getInterface() { return interface; } template void checkInterface(const IS& source, const IS& target, MPI_Comm comm) { auto ri = std::make_unique >(source, target, comm); ri->template rebuild(); Interface inf; typename OwnerOverlapCopyCommunication::OwnerSet flags; int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); inf.free(); inf.build(*ri, flags, flags); #ifdef DEBUG_REPART if(inf!=interface) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); if(rank==0) std::cout<<"Interfaces do not match!"< void redistribute(const D& from, D& to) const { BufferedCommunicator communicator; communicator.template build(from,to, interface); communicator.template forward(from, to); communicator.free(); } template void redistributeBackward(D& from, const D& to) const { BufferedCommunicator communicator; communicator.template build(from,to, interface); communicator.template backward(from, to); communicator.free(); } template void redistribute(const D& from, D& to) const { redistribute >(from,to); } template void redistributeBackward(D& from, const D& to) const { redistributeBackward >(from,to); } bool isSetup() const { return setup_; } void reserve(std::size_t size) {} std::size_t& getRowSize(std::size_t index) { return rowSize[index]; } std::size_t getRowSize(std::size_t index) const { return rowSize[index]; } std::size_t& getCopyRowSize(std::size_t index) { return copyrowSize[index]; } std::size_t getCopyRowSize(std::size_t index) const { return copyrowSize[index]; } std::size_t& getBackwardsCopyRowSize(std::size_t index) { return backwardscopyrowSize[index]; } std::size_t getBackwardsCopyRowSize(std::size_t index) const { return backwardscopyrowSize[index]; } void setNoRows(std::size_t rows) { rowSize.resize(rows, 0); } void setNoCopyRows(std::size_t rows) { copyrowSize.resize(rows, 0); } void setNoBackwardsCopyRows(std::size_t rows) { backwardscopyrowSize.resize(rows, 0); } private: std::vector rowSize; std::vector copyrowSize; std::vector backwardscopyrowSize; RedistributeInterface interface; bool setup_; }; /** * @brief Utility class to communicate and set the row sizes * of a redistributed matrix. * * @tparam M The type of the matrix that the row size * is communicated of. * @tparam RI The type of class for redistribution information */ template struct CommMatrixRowSize { // Make the default communication policy work. typedef typename M::size_type value_type; typedef typename M::size_type size_type; /** * @brief Constructor. * @param m_ The matrix whose sparsity pattern is communicated. * @param[out] rowsize_ RedistributeInformation object */ CommMatrixRowSize(const M& m_, RI& rowsize_) : matrix(m_), rowsize(rowsize_) {} const M& matrix; RI& rowsize; }; /** * @brief Utility class to communicate and build the sparsity pattern * of a redistributed matrix. * * @tparam M The type of the matrix that the sparsity pattern * is communicated of. * @tparam I The type of the index set. */ template struct CommMatrixSparsityPattern { typedef typename M::size_type size_type; /** * @brief Constructor for the original side * @param m_ The matrix whose sparsity pattern is communicated. * @param idxset_ The index set corresponding to the local matrix. * @param aggidxset_ The index set corresponding to the redistributed matrix. */ CommMatrixSparsityPattern(const M& m_, const Dune::GlobalLookupIndexSet& idxset_, const I& aggidxset_) : matrix(m_), idxset(idxset_), aggidxset(aggidxset_), rowsize() {} /** * @brief Constructor for the redistruted side. * @param m_ The matrix whose sparsity pattern is communicated. * @param idxset_ The index set corresponding to the local matrix. * @param aggidxset_ The index set corresponding to the redistributed matrix. * @param rowsize_ The row size for the redistributed owner rows. */ CommMatrixSparsityPattern(const M& m_, const Dune::GlobalLookupIndexSet& idxset_, const I& aggidxset_, const std::vector& rowsize_) : matrix(m_), idxset(idxset_), aggidxset(aggidxset_), sparsity(aggidxset_.size()), rowsize(&rowsize_) {} /** * @brief Creates and stores the sparsity pattern of the redistributed matrix. * * After the pattern is communicated this function can be used. * @param m The matrix to build. */ void storeSparsityPattern(M& m) { // insert diagonal to overlap rows typedef typename Dune::GlobalLookupIndexSet::const_iterator IIter; typedef typename Dune::OwnerOverlapCopyCommunication::OwnerSet OwnerSet; std::size_t nnz=0; #ifdef DEBUG_REPART int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); #endif for(IIter i= aggidxset.begin(), end=aggidxset.end(); i!=end; ++i) { if(!OwnerSet::contains(i->local().attribute())) { #ifdef DEBUG_REPART std::cout<local()<local()].insert(i->local()); } nnz+=sparsity[i->local()].size(); } assert( aggidxset.size()==sparsity.size()); if(nnz>0) { m.setSize(aggidxset.size(), aggidxset.size(), nnz); m.setBuildMode(M::row_wise); typename M::CreateIterator citer=m.createbegin(); #ifdef DEBUG_REPART std::size_t idx=0; bool correct=true; Dune::GlobalLookupIndexSet global(aggidxset); #endif typedef typename std::vector >::const_iterator Iter; for(Iter i=sparsity.begin(), end=sparsity.end(); i!=end; ++i, ++citer) { typedef typename std::set::const_iterator SIter; for(SIter si=i->begin(), send=i->end(); si!=send; ++si) citer.insert(*si); #ifdef DEBUG_REPART if(i->find(idx)==i->end()) { const typename I::IndexPair* gi=global.pair(idx); assert(gi); std::cout<local().attribute())<< " row size="<size()< > add_sparsity) { for (unsigned int i = 0; i != sparsity.size(); ++i) { if (add_sparsity[i].size() != 0) { typedef std::set Set; Set tmp_set; std::insert_iterator tmp_insert (tmp_set, tmp_set.begin()); std::set_union(add_sparsity[i].begin(), add_sparsity[i].end(), sparsity[i].begin(), sparsity[i].end(), tmp_insert); sparsity[i].swap(tmp_set); } } } const M& matrix; typedef Dune::GlobalLookupIndexSet LookupIndexSet; const Dune::GlobalLookupIndexSet& idxset; const I& aggidxset; std::vector > sparsity; const std::vector* rowsize; }; template struct CommPolicy > { typedef CommMatrixSparsityPattern Type; /** * @brief The indexed type we send. * This is the global index indentitfying the column. */ typedef typename I::GlobalIndex IndexedType; /** @brief Each row varies in size. */ typedef VariableSize IndexedTypeFlag; static typename M::size_type getSize(const Type& t, std::size_t i) { if(!t.rowsize) return t.matrix[i].size(); else { assert((*t.rowsize)[i]>0); return (*t.rowsize)[i]; } } }; /** * @brief Utility class for comunicating the matrix entries. * * @tparam M The type of the matrix. * @tparam I The type of the ParallelIndexSet. */ template struct CommMatrixRow { /** * @brief Constructor. * @param m_ The matrix to communicate the values. That is the local original matrix * as the source of the communication and the redistributed at the target of the * communication. * @param idxset_ The index set for the original matrix. * @param aggidxset_ The index set for the redistributed matrix. */ CommMatrixRow(M& m_, const Dune::GlobalLookupIndexSet& idxset_, const I& aggidxset_) : matrix(m_), idxset(idxset_), aggidxset(aggidxset_), rowsize() {} /** * @brief Constructor. */ CommMatrixRow(M& m_, const Dune::GlobalLookupIndexSet& idxset_, const I& aggidxset_, std::vector& rowsize_) : matrix(m_), idxset(idxset_), aggidxset(aggidxset_), rowsize(&rowsize_) {} /** * @brief Sets the non-owner rows correctly as Dirichlet boundaries. * * This should be called after the communication. */ void setOverlapRowsToDirichlet() { typedef typename Dune::GlobalLookupIndexSet::const_iterator Iter; typedef typename Dune::OwnerOverlapCopyCommunication::OwnerSet OwnerSet; for(Iter i= aggidxset.begin(), end=aggidxset.end(); i!=end; ++i) if(!OwnerSet::contains(i->local().attribute())) { // Set to Dirchlet typedef typename M::ColIterator CIter; for(CIter c=matrix[i->local()].begin(), cend= matrix[i->local()].end(); c!= cend; ++c) { *c=0; if(c.index()==i->local()) { typedef typename M::block_type::RowIterator RIter; for(RIter r=c->begin(), rend=c->end(); r != rend; ++r) (*r)[r.index()]=1; } } } } /** @brief The matrix to communicate the values of. */ M& matrix; /** @brief Index set for the original matrix. */ const Dune::GlobalLookupIndexSet& idxset; /** @brief Index set for the redistributed matrix. */ const I& aggidxset; /** @brief row size information for the receiving side. */ std::vector* rowsize; // row sizes differ from sender side in overlap! }; template struct CommPolicy > { typedef CommMatrixRow Type; /** * @brief The indexed type we send. * This is the pair of global index indentitfying the column and the value itself. */ typedef std::pair IndexedType; /** @brief Each row varies in size. */ typedef VariableSize IndexedTypeFlag; static std::size_t getSize(const Type& t, std::size_t i) { if(!t.rowsize) return t.matrix[i].size(); else { assert((*t.rowsize)[i]>0); return (*t.rowsize)[i]; } } }; template struct MatrixRowSizeGatherScatter { typedef CommMatrixRowSize Container; static const typename M::size_type gather(const Container& cont, std::size_t i) { return cont.matrix[i].size(); } static void scatter(Container& cont, const typename M::size_type& rowsize, std::size_t i) { assert(rowsize); cont.rowsize.getRowSize(i)=rowsize; } }; template struct MatrixCopyRowSizeGatherScatter { typedef CommMatrixRowSize Container; static const typename M::size_type gather(const Container& cont, std::size_t i) { return cont.matrix[i].size(); } static void scatter(Container& cont, const typename M::size_type& rowsize, std::size_t i) { assert(rowsize); if (rowsize > cont.rowsize.getCopyRowSize(i)) cont.rowsize.getCopyRowSize(i)=rowsize; } }; template struct MatrixSparsityPatternGatherScatter { typedef typename I::GlobalIndex GlobalIndex; typedef CommMatrixSparsityPattern Container; typedef typename M::ConstColIterator ColIter; static ColIter col; static GlobalIndex numlimits; static const GlobalIndex& gather(const Container& cont, std::size_t i, std::size_t j) { if(j==0) col=cont.matrix[i].begin(); else if (col!=cont.matrix[i].end()) ++col; //copy communication: different row sizes for copy rows with the same global index //are possible. If all values of current matrix row are sent, send //std::numeric_limits::max() //and receiver will ignore it. if (col==cont.matrix[i].end()) { numlimits = std::numeric_limits::max(); return numlimits; } else { const typename I::IndexPair* index=cont.idxset.pair(col.index()); assert(index); // Only send index if col is no ghost if ( index->local().attribute() != 2) return index->global(); else { numlimits = std::numeric_limits::max(); return numlimits; } } } static void scatter(Container& cont, const GlobalIndex& gi, std::size_t i, std::size_t j) { DUNE_UNUSED_PARAMETER(j); try{ if (gi != std::numeric_limits::max()) { const typename I::IndexPair& ip=cont.aggidxset.at(gi); assert(ip.global()==gi); std::size_t column = ip.local(); cont.sparsity[i].insert(column); typedef typename Dune::OwnerOverlapCopyCommunication::OwnerSet OwnerSet; if(!OwnerSet::contains(ip.local().attribute())) // preserve symmetry for overlap cont.sparsity[column].insert(i); } } catch(Dune::RangeError er) { // Entry not present in the new index set. Ignore! #ifdef DEBUG_REPART typedef typename Container::LookupIndexSet GlobalLookup; typedef typename GlobalLookup::IndexPair IndexPair; typedef typename Dune::OwnerOverlapCopyCommunication::OwnerSet OwnerSet; GlobalLookup lookup(cont.aggidxset); const IndexPair* pi=lookup.pair(i); assert(pi); if(OwnerSet::contains(pi->local().attribute())) { int rank; MPI_Comm_rank(MPI_COMM_WORLD,&rank); std::cout<global()< typename MatrixSparsityPatternGatherScatter::ColIter MatrixSparsityPatternGatherScatter::col; template typename MatrixSparsityPatternGatherScatter::GlobalIndex MatrixSparsityPatternGatherScatter::numlimits; template struct MatrixRowGatherScatter { typedef typename I::GlobalIndex GlobalIndex; typedef CommMatrixRow Container; typedef typename M::ConstColIterator ColIter; typedef typename std::pair Data; static ColIter col; static Data datastore; static GlobalIndex numlimits; static const Data& gather(const Container& cont, std::size_t i, std::size_t j) { if(j==0) col=cont.matrix[i].begin(); else if (col!=cont.matrix[i].end()) ++col; // copy communication: different row sizes for copy rows with the same global index // are possible. If all values of current matrix row are sent, send // std::numeric_limits::max() // and receiver will ignore it. if (col==cont.matrix[i].end()) { numlimits = std::numeric_limits::max(); datastore = std::make_pair(numlimits,*col); return datastore; } else { // convert local column index to global index const typename I::IndexPair* index=cont.idxset.pair(col.index()); assert(index); // Store the data to prevent reference to temporary // Only send index if col is no ghost if ( index->local().attribute() != 2) datastore = std::make_pair(index->global(),*col); else { numlimits = std::numeric_limits::max(); datastore = std::make_pair(numlimits,*col); } return datastore; } } static void scatter(Container& cont, const Data& data, std::size_t i, std::size_t j) { DUNE_UNUSED_PARAMETER(j); try{ if (data.first != std::numeric_limits::max()) { typename M::size_type column=cont.aggidxset.at(data.first).local(); cont.matrix[i][column]=data.second; } } catch(Dune::RangeError er) { // This an overlap row and might therefore lack some entries! } } }; template typename MatrixRowGatherScatter::ColIter MatrixRowGatherScatter::col; template typename MatrixRowGatherScatter::Data MatrixRowGatherScatter::datastore; template typename MatrixRowGatherScatter::GlobalIndex MatrixRowGatherScatter::numlimits; template void redistributeSparsityPattern(M& origMatrix, M& newMatrix, C& origComm, C& newComm, RedistributeInformation& ri) { typename C::CopySet copyflags; typename C::OwnerSet ownerflags; typedef typename C::ParallelIndexSet IndexSet; typedef RedistributeInformation RI; std::vector rowsize(newComm.indexSet().size(), 0); std::vector copyrowsize(newComm.indexSet().size(), 0); std::vector backwardscopyrowsize(origComm.indexSet().size(), 0); // get owner rowsizes CommMatrixRowSize commRowSize(origMatrix, ri); ri.template redistribute >(commRowSize,commRowSize); origComm.buildGlobalLookup(); for (std::size_t i=0; i < newComm.indexSet().size(); i++) { rowsize[i] = ri.getRowSize(i); } // get sparsity pattern from owner rows CommMatrixSparsityPattern origsp(origMatrix, origComm.globalLookup(), newComm.indexSet()); CommMatrixSparsityPattern newsp(origMatrix, origComm.globalLookup(), newComm.indexSet(), rowsize); ri.template redistribute >(origsp,newsp); // build copy to owner interface to get missing matrix values for novlp case if (origComm.getSolverCategory() == SolverCategory::nonoverlapping) { RemoteIndices *ris = new RemoteIndices(origComm.indexSet(), newComm.indexSet(), origComm.communicator()); ris->template rebuild(); ri.getInterface().free(); ri.getInterface().build(*ris,copyflags,ownerflags); // get copy rowsizes CommMatrixRowSize commRowSize_copy(origMatrix, ri); ri.template redistribute >(commRowSize_copy, commRowSize_copy); for (std::size_t i=0; i < newComm.indexSet().size(); i++) { copyrowsize[i] = ri.getCopyRowSize(i); } //get copy rowsizes for sender ri.redistributeBackward(backwardscopyrowsize,copyrowsize); for (std::size_t i=0; i < origComm.indexSet().size(); i++) { ri.getBackwardsCopyRowSize(i) = backwardscopyrowsize[i]; } // get sparsity pattern from copy rows CommMatrixSparsityPattern origsp_copy(origMatrix, origComm.globalLookup(), newComm.indexSet(), backwardscopyrowsize); CommMatrixSparsityPattern newsp_copy(origMatrix, origComm.globalLookup(), newComm.indexSet(), copyrowsize); ri.template redistribute >(origsp_copy, newsp_copy); newsp.completeSparsityPattern(newsp_copy.sparsity); newsp.storeSparsityPattern(newMatrix); } else newsp.storeSparsityPattern(newMatrix); #ifdef DUNE_ISTL_WITH_CHECKING // Check for symmetry int ret=0; typedef typename M::ConstRowIterator RIter; for(RIter row=newMatrix.begin(), rend=newMatrix.end(); row != rend; ++row) { typedef typename M::ConstColIterator CIter; for(CIter col=row->begin(), cend=row->end(); col!=cend; ++col) { try{ newMatrix[col.index()][row.index()]; }catch(Dune::ISTLError e) { std::cerr< void redistributeMatrixEntries(M& origMatrix, M& newMatrix, C& origComm, C& newComm, RedistributeInformation& ri) { typedef typename C::ParallelIndexSet IndexSet; typename C::OwnerSet ownerflags; std::vector rowsize(newComm.indexSet().size(), 0); std::vector copyrowsize(newComm.indexSet().size(), 0); std::vector backwardscopyrowsize(origComm.indexSet().size(), 0); for (std::size_t i=0; i < newComm.indexSet().size(); i++) { rowsize[i] = ri.getRowSize(i); if (origComm.getSolverCategory() == SolverCategory::nonoverlapping) { copyrowsize[i] = ri.getCopyRowSize(i); } } for (std::size_t i=0; i < origComm.indexSet().size(); i++) if (origComm.getSolverCategory() == SolverCategory::nonoverlapping) backwardscopyrowsize[i] = ri.getBackwardsCopyRowSize(i); if (origComm.getSolverCategory() == SolverCategory::nonoverlapping) { // fill sparsity pattern from copy rows CommMatrixRow origrow_copy(origMatrix, origComm.globalLookup(), newComm.indexSet(), backwardscopyrowsize); CommMatrixRow newrow_copy(newMatrix, origComm.globalLookup(), newComm.indexSet(),copyrowsize); ri.template redistribute >(origrow_copy, newrow_copy); ri.getInterface().free(); RemoteIndices *ris = new RemoteIndices(origComm.indexSet(), newComm.indexSet(), origComm.communicator()); ris->template rebuild(); ri.getInterface().build(*ris,ownerflags,ownerflags); } CommMatrixRow origrow(origMatrix, origComm.globalLookup(), newComm.indexSet()); CommMatrixRow newrow(newMatrix, origComm.globalLookup(), newComm.indexSet(),rowsize); ri.template redistribute >(origrow,newrow); if (origComm.getSolverCategory() != static_cast(SolverCategory::nonoverlapping)) newrow.setOverlapRowsToDirichlet(); } /** * @brief Redistribute a matrix according to given domain decompositions. * * All the parameters for this function can be obtained by calling * graphRepartition with the graph of the original matrix. * * @param origMatrix The matrix on the original partitioning. * @param newMatrix An empty matrix to store the new redistributed matrix in. * @param origComm The parallel information of the original partitioning. * @param newComm The parallel information of the new partitioning. * @param ri The remote index information between the original and the new partitioning. * Upon exit of this method it will be prepared for copying from owner to owner vertices * for data redistribution. * @tparam M The matrix type. It is assumed to be sparse. E.g. BCRSMatrix. * @tparam C The type of the parallel information, see OwnerOverlapCopyCommunication. */ template void redistributeMatrix(M& origMatrix, M& newMatrix, C& origComm, C& newComm, RedistributeInformation& ri) { ri.setNoRows(newComm.indexSet().size()); ri.setNoCopyRows(newComm.indexSet().size()); ri.setNoBackwardsCopyRows(origComm.indexSet().size()); redistributeSparsityPattern(origMatrix, newMatrix, origComm, newComm, ri); redistributeMatrixEntries(origMatrix, newMatrix, origComm, newComm, ri); } #endif template void redistributeMatrixEntries(M& origMatrix, M& newMatrix, Dune::Amg::SequentialInformation& origComm, Dune::Amg::SequentialInformation& newComm, RedistributeInformation& ri) { DUNE_THROW(InvalidStateException, "Trying to redistribute in sequential program!"); } template void redistributeMatrix(M& origMatrix, M& newMatrix, Dune::Amg::SequentialInformation& origComm, Dune::Amg::SequentialInformation& newComm, RedistributeInformation& ri) { DUNE_THROW(InvalidStateException, "Trying to redistribute in sequential program!"); } } #endif dune-istl-2.5.1/dune/istl/matrixutils.hh000066400000000000000000000307761313314427100202530ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MATRIXUTILS_HH #define DUNE_ISTL_MATRIXUTILS_HH #include #include #include #include #include #include #include #include #include #include "istlexception.hh" namespace Dune { #ifndef DOYXGEN template class BCRSMatrix; template class FieldMatrix; template class Matrix; #endif /** * @addtogroup ISTL_SPMV * @{ */ /** * @file * @brief Some handy generic functions for ISTL matrices. * @author Markus Blatt */ namespace { template struct NonZeroCounter { template static typename M::size_type count(const M& matrix) { typedef typename M::ConstRowIterator RowIterator; RowIterator endRow = matrix.end(); typename M::size_type nonZeros = 0; for(RowIterator row = matrix.begin(); row != endRow; ++row) { typedef typename M::ConstColIterator Entry; Entry endEntry = row->end(); for(Entry entry = row->begin(); entry != endEntry; ++entry) { nonZeros += NonZeroCounter::count(*entry); } } return nonZeros; } }; template<> struct NonZeroCounter<1> { template static typename M::size_type count(const M& matrix) { return matrix.N()*matrix.M(); } }; } /** * @brief Check whether the a matrix has diagonal values * on blocklevel recursion levels. */ template struct CheckIfDiagonalPresent { /** * @brief Check whether the a matrix has diagonal values * on blocklevel recursion levels. */ static void check(const Matrix& mat) { DUNE_UNUSED_PARAMETER(mat); #ifdef DUNE_ISTL_WITH_CHECKING typedef typename Matrix::ConstRowIterator Row; typedef typename Matrix::ConstColIterator Entry; for(Row row = mat.begin(); row!=mat.end(); ++row) { Entry diagonal = row->find(row.index()); if(diagonal==row->end()) DUNE_THROW(ISTLError, "Missing diagonal value in row "<::check(*diagonal); } #endif } }; template struct CheckIfDiagonalPresent { static void check(const Matrix& mat) { typedef typename Matrix::ConstRowIterator Row; for(Row row = mat.begin(); row!=mat.end(); ++row) { if(row->find(row.index())==row->end()) DUNE_THROW(ISTLError, "Missing diagonal value in row "< class MultiTypeBlockMatrix; template struct CheckIfDiagonalPresent, blocklevel,l> { typedef MultiTypeBlockMatrix Matrix; /** * @brief Check whether the a matrix has diagonal values * on blocklevel recursion levels. */ static void check(const Matrix& /* mat */) { #ifdef DUNE_ISTL_WITH_CHECKING // TODO Implement check #endif } }; /** * @brief Get the number of nonzero fields in the matrix. * * This is not the number of nonzero blocks, but the number of non * zero scalar entries (on blocklevel 1) if the matrix is viewed as * a flat matrix. * * For FieldMatrix this is simply the number of columns times the * number of rows, for a BCRSMatrix> this is the * number of nonzero blocks time n*m. */ template inline int countNonZeros(const M& matrix) { return NonZeroCounter::count(matrix); } /* template struct ProcessOnFieldsOfMatrix */ /** @} */ namespace { struct CompPair { template bool operator()(const std::pair& p1, const std::pair& p2) { return p1.first void printGlobalSparseMatrix(const M& mat, C& ooc, std::ostream& os) { typedef typename C::ParallelIndexSet::const_iterator IIter; typedef typename C::OwnerSet OwnerSet; typedef typename C::ParallelIndexSet::GlobalIndex GlobalIndex; GlobalIndex gmax=0; for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end(); idx!=eidx; ++idx) gmax=std::max(gmax,idx->global()); gmax=ooc.communicator().max(gmax); ooc.buildGlobalLookup(); for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end(); idx!=eidx; ++idx) { if(OwnerSet::contains(idx->local().attribute())) { typedef typename M::block_type Block; std::set,CompPair> entries; // sort rows typedef typename M::ConstColIterator CIter; for(CIter c=mat[idx->local()].begin(), cend=mat[idx->local()].end(); c!=cend; ++c) { const typename C::ParallelIndexSet::IndexPair* pair =ooc.globalLookup().pair(c.index()); assert(pair); entries.insert(std::make_pair(pair->global(), *c)); } //wait until its the rows turn. GlobalIndex rowidx = idx->global(); GlobalIndex cur=std::numeric_limits::max(); while(cur!=rowidx) cur=ooc.communicator().min(rowidx); // print rows typedef typename std::set,CompPair>::iterator SIter; for(SIter s=entries.begin(), send=entries.end(); s!=send; ++s) os<global()<<" "<first<<" "<second<::max(); while(cur!=ooc.communicator().min(cur)) ; } template struct MatrixDimension {}; template struct MatrixDimension > { typedef BCRSMatrix Matrix; typedef typename Matrix::block_type block_type; typedef typename Matrix::size_type size_type; static size_type rowdim (const Matrix& A, size_type i) { const B* row = A.r[i].getptr(); if(row) return MatrixDimension::rowdim(*row); else return 0; } static size_type coldim (const Matrix& A, size_type c) { // find an entry in column c if (A.nnz_ > 0) { for (size_type k=0; k::coldim(A.a[k]); } } } else { for (size_type i=0; i::coldim(a[k]); } } } // not found return 0; } static size_type rowdim (const Matrix& A){ size_type nn=0; for (size_type i=0; i coldims(A.M(), std::numeric_limits::max()); for (ConstRowIterator row=A.begin(); row!=A.end(); ++row) for (ConstColIterator col=row->begin(); col!=row->end(); ++col) // only compute blocksizes we don't already have if (coldims[col.index()]==std::numeric_limits::max()) coldims[col.index()] = MatrixDimension::coldim(*col); size_type sum = 0; for (typename std::vector::iterator it=coldims.begin(); it!=coldims.end(); ++it) // skip rows for which no coldim could be determined if ((*it)>=0) sum += *it; return sum; } }; template struct MatrixDimension ,TA> > { typedef BCRSMatrix ,TA> Matrix; typedef typename Matrix::size_type size_type; static size_type rowdim (const Matrix& /*A*/, size_type /*i*/) { return n; } static size_type coldim (const Matrix& /*A*/, size_type /*c*/) { return m; } static size_type rowdim (const Matrix& A) { return A.N()*n; } static size_type coldim (const Matrix& A) { return A.M()*m; } }; template struct MatrixDimension > { typedef FieldMatrix Matrix; typedef typename Matrix::size_type size_type; static size_type rowdim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type coldim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type rowdim(const Matrix& /*A*/) { return n; } static size_type coldim(const Matrix& /*A*/) { return m; } }; template struct MatrixDimension > { typedef Dune::DynamicMatrix MatrixType; typedef typename MatrixType::size_type size_type; static size_type rowdim(const MatrixType& /*A*/, size_type /*r*/) { return 1; } static size_type coldim(const MatrixType& /*A*/, size_type /*r*/) { return 1; } static size_type rowdim(const MatrixType& A) { return A.N(); } static size_type coldim(const MatrixType& A) { return A.M(); } }; template struct MatrixDimension, TA> > { typedef Matrix, TA> ThisMatrix; typedef typename ThisMatrix::size_type size_type; static size_type rowdim(const ThisMatrix& /*A*/, size_type /*r*/) { return n; } static size_type coldim(const ThisMatrix& /*A*/, size_type /*r*/) { return m; } static size_type rowdim(const ThisMatrix& A) { return A.N()*n; } static size_type coldim(const ThisMatrix& A) { return A.M()*m; } }; template struct MatrixDimension > { typedef DiagonalMatrix Matrix; typedef typename Matrix::size_type size_type; static size_type rowdim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type coldim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type rowdim(const Matrix& /*A*/) { return n; } static size_type coldim(const Matrix& /*A*/) { return n; } }; template struct MatrixDimension > { typedef ScaledIdentityMatrix Matrix; typedef typename Matrix::size_type size_type; static size_type rowdim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type coldim(const Matrix& /*A*/, size_type /*r*/) { return 1; } static size_type rowdim(const Matrix& /*A*/) { return n; } static size_type coldim(const Matrix& /*A*/) { return n; } }; /** * @brief Test whether a type is an ISTL Matrix */ template struct IsMatrix { enum { /** * @brief True if T is an ISTL matrix */ value = false }; }; template struct IsMatrix > { enum { /** * @brief True if T is an ISTL matrix */ value = true }; }; template struct IsMatrix > { enum { /** * @brief True if T is an ISTL matrix */ value = true }; }; template struct PointerCompare { bool operator()(const T* l, const T* r) { return *l < *r; } }; } #endif dune-istl-2.5.1/dune/istl/multitypeblockmatrix.hh000066400000000000000000000326521313314427100221550ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MULTITYPEBLOCKMATRIX_HH #define DUNE_ISTL_MULTITYPEBLOCKMATRIX_HH #include #include #include #include #include "istlexception.hh" // forward declaration namespace Dune { template class MultiTypeBlockMatrix; template class MultiTypeBlockMatrix_Solver; } #include "gsetc.hh" namespace Dune { /** @addtogroup ISTL_SPMV @{ */ /** @brief A Matrix class to support different block types This matrix class combines MultiTypeBlockVector elements as rows. */ template class MultiTypeBlockMatrix : public std::tuple { public: /** * own class' type */ typedef MultiTypeBlockMatrix type; typedef typename FirstRow::field_type field_type; /** \brief Return the number of matrix rows */ static constexpr std::size_t N() { return 1+sizeof...(Args); } /** \brief Return the number of matrix rows */ static constexpr std::size_t size() { return 1+sizeof...(Args); } /** \brief Return the number of matrix columns */ static constexpr std::size_t M() { return FirstRow::size(); } /** \brief Random-access operator * * This method mimicks the behavior of normal vector access with square brackets like, e.g., m[5] = .... * The problem is that the return type is different for each value of the argument in the brackets. * Therefore we implement a trick using std::integral_constant. To access the first row of * a MultiTypeBlockMatrix named m write * \code * std::integral_constant _0; * m[_0] = ... * \endcode * The name '_0' used here as a static replacement of the integer number zero is arbitrary. * Any other variable name can be used. If you don't like the separate variable, you can write * \code * m[std::integral_constant()] = ... * \endcode */ template< std::size_t index > auto operator[] ( const std::integral_constant< std::size_t, index > indexVariable ) -> decltype(std::get(*this)) { DUNE_UNUSED_PARAMETER(indexVariable); return std::get(*this); } /** \brief Const random-access operator * * This is the const version of the random-access operator. See the non-const version for a full * explanation of how to use it. */ template< std::size_t index > auto operator[] ( const std::integral_constant< std::size_t, index > indexVariable ) const -> decltype(std::get(*this)) { DUNE_UNUSED_PARAMETER(indexVariable); return std::get(*this); } /** * assignment operator */ template void operator= (const T& newval) { using namespace Dune::Hybrid; auto size = index_constant<1+sizeof...(Args)>(); // Since Dune::Hybrid::size(MultiTypeBlockMatrix) is not implemented, // we cannot use a plain forEach(*this, ...). This could be achieved, // e.g., by implementing a static size() method. forEach(integralRange(size), [&](auto&& i) { (*this)[i] = newval; }); } /** \brief y = A x */ template void mv (const X& x, Y& y) const { static_assert(X::size() == M(), "length of x does not match row length"); static_assert(Y::size() == N(), "length of y does not match row count"); y = 0; //reset y (for mv uses umv) umv(x,y); } /** \brief y += A x */ template void umv (const X& x, Y& y) const { static_assert(X::size() == M(), "length of x does not match row length"); static_assert(Y::size() == N(), "length of y does not match row count"); using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(y)), [&](auto&& i) { forEach(integralRange(Hybrid::size(x)), [&](auto&& j) { (*this)[i][j].umv(x[j], y[i]); }); }); } /** \brief y -= A x */ template void mmv (const X& x, Y& y) const { static_assert(X::size() == M(), "length of x does not match row length"); static_assert(Y::size() == N(), "length of y does not match row count"); using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(y)), [&](auto&& i) { forEach(integralRange(Hybrid::size(x)), [&](auto&& j) { (*this)[i][j].mmv(x[j], y[i]); }); }); } /** \brief y += alpha A x */ template void usmv (const AlphaType& alpha, const X& x, Y& y) const { static_assert(X::size() == M(), "length of x does not match row length"); static_assert(Y::size() == N(), "length of y does not match row count"); using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(y)), [&](auto&& i) { forEach(integralRange(Hybrid::size(x)), [&](auto&& j) { (*this)[i][j].usmv(alpha, x[j], y[i]); }); }); } }; /** @brief << operator for a MultiTypeBlockMatrix operator<< for printing out a MultiTypeBlockMatrix */ template std::ostream& operator<< (std::ostream& s, const MultiTypeBlockMatrix& m) { auto N = index_constant::N()>(); auto M = index_constant::M()>(); using namespace Dune::Hybrid; forEach(integralRange(N), [&](auto&& i) { forEach(integralRange(M), [&](auto&& j) { s << "\t(" << i << ", " << j << "): \n" << m[i][j]; }); }); s << std::endl; return s; } //make algmeta_itsteps known template struct algmeta_itsteps; /** @brief part of solvers for MultiTypeBlockVector & MultiTypeBlockMatrix types For the given row (index "crow") each element is used to calculate the equation's right side. */ template //MultiTypeBlockMatrix_Solver_Col: iterating over one row class MultiTypeBlockMatrix_Solver_Col { //calculating b- A[i][j]*x[j] public: /** * iterating over one row in MultiTypeBlockMatrix to calculate right side b-A[i][j]*x[j] */ template static void calc_rhs(const TMatrix& A, TVector& x, TVector& v, Trhs& b, const K& w) { std::get( std::get(A) ).mmv( std::get(x), b ); MultiTypeBlockMatrix_Solver_Col::calc_rhs(A,x,v,b,w); //next column element } }; template //MultiTypeBlockMatrix_Solver_Col recursion end class MultiTypeBlockMatrix_Solver_Col { public: template static void calc_rhs(const TMatrix&, TVector&, TVector&, Trhs&, const K&) {} }; /** @brief solver for MultiTypeBlockVector & MultiTypeBlockMatrix types The methods of this class are called by the solver specializations for MultiTypeBlockVector & MultiTypeBlockMatrix types (dbgs, bsorf, bsorb, dbjac). */ template class MultiTypeBlockMatrix_Solver { public: /** * Gauss-Seidel solver for MultiTypeBlockMatrix & MultiTypeBlockVector types */ template static void dbgs(const TMatrix& A, TVector& x, const TVector& b, const K& w) { TVector xold(x); xold=x; //store old x values MultiTypeBlockMatrix_Solver::dbgs(A,x,x,b,w); x *= w; x.axpy(1-w,xold); //improve x } template static void dbgs(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) { auto rhs = std::get (b); MultiTypeBlockMatrix_Solver_Col::calc_rhs(A,x,v,rhs,w); // calculate right side of equation //solve on blocklevel I-1 using M = typename std::remove_cv< typename std::remove_reference< decltype(std::get( std::get(A))) >::type >::type; algmeta_itsteps::dbgs(std::get( std::get(A)), std::get(x),rhs,w); MultiTypeBlockMatrix_Solver::dbgs(A,x,v,b,w); //next row } /** * bsorf for MultiTypeBlockMatrix & MultiTypeBlockVector types */ template static void bsorf(const TMatrix& A, TVector& x, const TVector& b, const K& w) { TVector v; v=x; //use latest x values in right side calculation MultiTypeBlockMatrix_Solver::bsorf(A,x,v,b,w); } template //recursion over all matrix rows (A) static void bsorf(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) { auto rhs = std::get (b); MultiTypeBlockMatrix_Solver_Col::calc_rhs(A,x,v,rhs,w); // calculate right side of equation //solve on blocklevel I-1 using M = typename std::remove_cv< typename std::remove_reference< decltype(std::get( std::get(A))) >::type >::type; algmeta_itsteps::bsorf(std::get( std::get(A)), std::get(v),rhs,w); std::get(x).axpy(w,std::get(v)); MultiTypeBlockMatrix_Solver::bsorf(A,x,v,b,w); //next row } /** * bsorb for MultiTypeBlockMatrix & MultiTypeBlockVector types */ template static void bsorb(const TMatrix& A, TVector& x, const TVector& b, const K& w) { TVector v; v=x; //use latest x values in right side calculation MultiTypeBlockMatrix_Solver::bsorb(A,x,v,b,w); } template //recursion over all matrix rows (A) static void bsorb(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) { auto rhs = std::get (b); MultiTypeBlockMatrix_Solver_Col::calc_rhs(A,x,v,rhs,w); // calculate right side of equation //solve on blocklevel I-1 using M = typename std::remove_cv< typename std::remove_reference< decltype(std::get( std::get(A))) >::type >::type; algmeta_itsteps::bsorb(std::get( std::get(A)), std::get(v),rhs,w); std::get(x).axpy(w,std::get(v)); MultiTypeBlockMatrix_Solver::bsorb(A,x,v,b,w); //next row } /** * Jacobi solver for MultiTypeBlockMatrix & MultiTypeBlockVector types */ template static void dbjac(const TMatrix& A, TVector& x, const TVector& b, const K& w) { TVector v(x); v=0; //calc new x in v MultiTypeBlockMatrix_Solver::dbjac(A,x,v,b,w); x.axpy(w,v); //improve x } template static void dbjac(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) { auto rhs = std::get (b); MultiTypeBlockMatrix_Solver_Col::calc_rhs(A,x,v,rhs,w); // calculate right side of equation //solve on blocklevel I-1 using M = typename std::remove_cv< typename std::remove_reference< decltype(std::get( std::get(A))) >::type >::type; algmeta_itsteps::dbjac(std::get( std::get(A)), std::get(v),rhs,w); MultiTypeBlockMatrix_Solver::dbjac(A,x,v,b,w); //next row } }; template //recursion end for remain_row = 0 class MultiTypeBlockMatrix_Solver { public: template static void dbgs(const TMatrix&, TVector&, TVector&, const TVector&, const K&) {} template static void bsorf(const TMatrix&, TVector&, TVector&, const TVector&, const K&) {} template static void bsorb(const TMatrix&, TVector&, TVector&, const TVector&, const K&) {} template static void dbjac(const TMatrix&, TVector&, TVector&, const TVector&, const K&) {} }; } // end namespace #endif dune-istl-2.5.1/dune/istl/multitypeblockvector.hh000066400000000000000000000170671313314427100221560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_MULTITYPEBLOCKVECTOR_HH #define DUNE_ISTL_MULTITYPEBLOCKVECTOR_HH #include #include #include #include #include #include #include "istlexception.hh" // forward declaration namespace Dune { template < typename... Args > class MultiTypeBlockVector; } #include "gsetc.hh" namespace Dune { /** @addtogroup ISTL_SPMV @{ */ /** @addtogroup DenseMatVec @{ */ template struct FieldTraits< MultiTypeBlockVector > { typedef typename FieldTraits::field_type field_type; typedef typename FieldTraits::real_type real_type; }; /** @} */ /** @brief A Vector class to support different block types This vector class combines elements of different types known at compile-time. */ template < typename... Args > class MultiTypeBlockVector : public std::tuple { /** \brief Helper type */ typedef std::tuple tupleType; public: /** * own class' type */ typedef MultiTypeBlockVector type; /** \brief The type used for scalars * * The current code hardwires it to 'double', which is far from nice. * On the other hand, it is not clear what the correct type is. If the MultiTypeBlockVector class * is instantiated with several vectors of different field_types, what should the resulting * field_type be? */ typedef double field_type; /** \brief Return the number of vector entries */ static constexpr std::size_t size() { return sizeof...(Args); } /** * number of elements */ int count() { return sizeof...(Args); } /** \brief Random-access operator * * This method mimicks the behavior of normal vector access with square brackets like, e.g., v[5] = 1. * The problem is that the return type is different for each value of the argument in the brackets. * Therefore we implement a trick using std::integral_constant. To access the first entry of * a MultiTypeBlockVector named v write * \code * MultiTypeBlockVector v; * std::integral_constant _0; * v[_0] = ... * \endcode * The name '_0' used here as a static replacement of the integer number zero is arbitrary. * Any other variable name can be used. If you don't like the separate variable, you can writee * \code * MultiTypeBlockVector v; * v[std::integral_constant()] = ... * \endcode */ template< std::size_t index > typename std::tuple_element::type& operator[] ( const std::integral_constant< std::size_t, index > indexVariable ) { DUNE_UNUSED_PARAMETER(indexVariable); return std::get(*this); } /** \brief Const random-access operator * * This is the const version of the random-access operator. See the non-const version for a full * explanation of how to use it. */ template< std::size_t index > const typename std::tuple_element::type& operator[] ( const std::integral_constant< std::size_t, index > indexVariable ) const { DUNE_UNUSED_PARAMETER(indexVariable); return std::get(*this); } /** \brief Assignment operator */ template void operator= (const T& newval) { Dune::Hybrid::forEach(*this, [&](auto&& entry) { entry = newval; }); } /** * operator for MultiTypeBlockVector += MultiTypeBlockVector operations */ void operator+= (const type& newv) { using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) { (*this)[i] += newv[i]; }); } /** * operator for MultiTypeBlockVector -= MultiTypeBlockVector operations */ void operator-= (const type& newv) { using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) { (*this)[i] -= newv[i]; }); } // Once we have the IsNumber traits class the following // three implementations could be replaced by: // // template::value, int> = 0> // void operator*= (const T& w) { // Dune::Hybrid::forEach(*this, [&](auto&& entry) { // entry *= w; // }); // } void operator*= (const int& w) { Dune::Hybrid::forEach(*this, [&](auto&& entry) { entry *= w; }); } void operator*= (const float& w) { Dune::Hybrid::forEach(*this, [&](auto&& entry) { entry *= w; }); } void operator*= (const double& w) { Dune::Hybrid::forEach(*this, [&](auto&& entry) { entry *= w; }); } field_type operator* (const type& newv) const { using namespace Dune::Hybrid; return accumulate(integralRange(Hybrid::size(*this)), field_type(0), [&](auto&& a, auto&& i) { return a + (*this)[i]*newv[i]; }); } field_type dot (const type& newv) const { using namespace Dune::Hybrid; return accumulate(integralRange(Hybrid::size(*this)), field_type(0), [&](auto&& a, auto&& i) { return a + (*this)[i].dot(newv[i]); }); } /** \brief Compute the squared Euclidean norm */ typename FieldTraits::real_type two_norm2() const { using namespace Dune::Hybrid; return accumulate(*this, typename FieldTraits::real_type(0), [&](auto&& a, auto&& entry) { return a + entry.two_norm2(); }); } /** \brief Compute the Euclidean norm */ typename FieldTraits::real_type two_norm() const {return sqrt(this->two_norm2());} /** \brief Compute the maximum norm */ typename FieldTraits::real_type infinity_norm() const { using namespace Dune::Hybrid; using std::max; using real_type = typename FieldTraits::real_type; real_type result = 0.0; // Compute max norm tracking appearing nan values // if the field type supports nan. ifElse(has_nan(), [&](auto&& id) { // This variable will preserve any nan value real_type nanTracker = 1.0; forEach(*this, [&](auto&& entry) { real_type entryNorm = entry.infinity_norm(); result = max(entryNorm, result); nanTracker += entryNorm; }); // Incorporate possible nan value into result result *= (nanTracker / nanTracker); }, [&](auto&& id) { forEach(*this, [&](auto&& entry) { result = max(entry.infinity_norm(), result); }); }); return result; } /** \brief Axpy operation on this vector (*this += a * y) * * \tparam Ta Type of the scalar 'a' */ template void axpy (const Ta& a, const type& y) { using namespace Dune::Hybrid; forEach(integralRange(Hybrid::size(*this)), [&](auto&& i) { (*this)[i].axpy(a, y[i]); }); } }; /** \brief Send MultiTypeBlockVector to an outstream */ template std::ostream& operator<< (std::ostream& s, const MultiTypeBlockVector& v) { using namespace Dune::Hybrid; forEach(integralRange(size(v)), [&](auto&& i) { s << "\t(" << i << "):\n" << v[i] << "\n"; }); return s; } } // end namespace #endif dune-istl-2.5.1/dune/istl/novlpschwarz.hh000066400000000000000000000340121313314427100204110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_NOVLPSCHWARZ_HH #define DUNE_ISTL_NOVLPSCHWARZ_HH #include // for input/output to shell #include // for input/output to files #include // STL vector class #include #include // Yes, we do some math here #include #include "io.hh" #include "bvector.hh" #include "vbvector.hh" #include "bcrsmatrix.hh" #include "io.hh" #include "gsetc.hh" #include "ilu.hh" #include "operators.hh" #include "solvers.hh" #include "preconditioners.hh" #include "scalarproducts.hh" #include "owneroverlapcopy.hh" namespace Dune { /** * @defgroup ISTL_Parallel Parallel Solvers * @ingroup ISTL_Solvers * Instead of using parallel data structures (matrices and vectors) that * (implicitly) know the data distribution and communication patterns, * there is a clear separation of the parallel data composition together * with the communication APIs from the data structures. This allows for * implementing overlapping and nonoverlapping domain decompositions as * well as data parallel parallelisation approaches. * * The \ref ISTL_Solvers "solvers" can easily be turned into parallel solvers * initializing them with matching parallel subclasses of the base classes * ScalarProduct, Preconditioner and LinearOperator. * * The information of the data distribution is provided by OwnerOverlapCopyCommunication * of \ref ISTL_Comm "communication API". * * Currently only data parallel versions are shipped with dune-istl. Domain * decomposition can be found in module dune-dd. */ /** @addtogroup ISTL_Operators @{ */ /** * @brief A nonoverlapping operator with communication object. */ template class NonoverlappingSchwarzOperator : public AssembledLinearOperator { public: //! \brief The type of the matrix we operate on. typedef M matrix_type; //! \brief The type of the domain. typedef X domain_type; //! \brief The type of the range. typedef Y range_type; //! \brief The field type of the range typedef typename X::field_type field_type; //! \brief The type of the communication object typedef C communication_type; typedef typename C::PIS PIS; typedef typename C::RI RI; typedef typename RI::RemoteIndexList RIL; typedef typename RI::const_iterator RIIterator; typedef typename RIL::const_iterator RILIterator; typedef typename M::ConstColIterator ColIterator; typedef typename M::ConstRowIterator RowIterator; typedef std::multimap MM; typedef std::multimap > RIMap; typedef typename RIMap::iterator RIMapit; enum { //! \brief The solver category. category=SolverCategory::nonoverlapping }; /** * @brief constructor: just store a reference to a matrix. * * @param A The assembled matrix. * @param com The communication object for syncing owner and copy * data points. (E.~g. OwnerOverlapCommunication ) */ NonoverlappingSchwarzOperator (const matrix_type& A, const communication_type& com) : _A_(A), communication(com), buildcomm(true) {} //! apply operator to x: \f$ y = A(x) \f$ virtual void apply (const X& x, Y& y) const { y = 0; novlp_op_apply(x,y,1); communication.addOwnerCopyToOwnerCopy(y,y); } //! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$ virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const { // only apply communication to alpha*A*x to make it consistent, // y already has to be consistent. Y y1(y); y = 0; novlp_op_apply(x,y,alpha); communication.addOwnerCopyToOwnerCopy(y,y); y += y1; } //! get matrix via * virtual const matrix_type& getmat () const { return _A_; } void novlp_op_apply (const X& x, Y& y, field_type alpha) const { //get index sets const PIS& pis=communication.indexSet(); const RI& ri = communication.remoteIndices(); // at the beginning make a multimap "bordercontribution". // process has i and j as border dofs but is not the owner // => only contribute to Ax if i,j is in bordercontribution if (buildcomm == true) { // set up mask vector if (mask.size()!=static_cast::size_type>(x.size())) { mask.resize(x.size()); for (typename std::vector::size_type i=0; ilocal().attribute()==OwnerOverlapCopyAttributeSet::copy) mask[i->local().local()] = 0; else if (i->local().attribute()==OwnerOverlapCopyAttributeSet::overlap) mask[i->local().local()] = 2; } for (MM::iterator iter = bordercontribution.begin(); iter != bordercontribution.end(); ++iter) bordercontribution.erase(iter); std::map owner; //key: local index i, value: process, that owns i RIMap rimap; // for each local index make multimap rimap: // key: local index i, data: pair of process that knows i and pointer to RI entry for (RowIterator i = _A_.begin(); i != _A_.end(); ++i) if (mask[i.index()] == 0) for (RIIterator remote = ri.begin(); remote != ri.end(); ++remote) { RIL& ril = *(remote->second.first); for (RILIterator rindex = ril.begin(); rindex != ril.end(); ++rindex) if (rindex->attribute() != OwnerOverlapCopyAttributeSet::overlap) if (rindex->localIndexPair().local().local() == i.index()) { rimap.insert (std::make_pair(i.index(), std::pair(remote->first, rindex))); if(rindex->attribute()==OwnerOverlapCopyAttributeSet::owner) owner.insert(std::make_pair(i.index(),remote->first)); } } int iowner = 0; for (RowIterator i = _A_.begin(); i != _A_.end(); ++i) { if (mask[i.index()] == 0) { std::map::iterator it = owner.find(i.index()); iowner = it->second; std::pair foundiit = rimap.equal_range(i.index()); for (ColIterator j = _A_[i.index()].begin(); j != _A_[i.index()].end(); ++j) { if (mask[j.index()] == 0) { bool flag = true; for (RIMapit foundi = foundiit.first; foundi != foundiit.second; ++foundi) { std::pair foundjit = rimap.equal_range(j.index()); for (RIMapit foundj = foundjit.first; foundj != foundjit.second; ++foundj) if (foundj->second.first == foundi->second.first) if (foundj->second.second->attribute() == OwnerOverlapCopyAttributeSet::owner || foundj->second.first == iowner || foundj->second.first < communication.communicator().rank()) { flag = false; continue; } if (flag == false) continue; } // don´t contribute to Ax if // 1. the owner of j has i as interior/border dof // 2. iowner has j as interior/border dof // 3. there is another process with smaller rank that has i and j // as interor/border dofs // if the owner of j does not have i as interior/border dof, // it will not be taken into account if (flag==true) bordercontribution.insert(std::pair(i.index(),j.index())); } } } } buildcomm = false; } //compute alpha*A*x nonoverlapping case for (RowIterator i = _A_.begin(); i != _A_.end(); ++i) { if (mask[i.index()] == 0) { //dof doesn't belong to process but is border (not ghost) for (ColIterator j = _A_[i.index()].begin(); j != _A_[i.index()].end(); ++j) { if (mask[j.index()] == 1) //j is owner => then sum entries (*j).usmv(alpha,x[j.index()],y[i.index()]); else if (mask[j.index()] == 0) { std::pair itp = bordercontribution.equal_range(i.index()); for (MM::iterator it = itp.first; it != itp.second; ++it) if ((*it).second == (int)j.index()) (*j).usmv(alpha,x[j.index()],y[i.index()]); } } } else if (mask[i.index()] == 1) { for (ColIterator j = _A_[i.index()].begin(); j != _A_[i.index()].end(); ++j) if (mask[j.index()] != 2) (*j).usmv(alpha,x[j.index()],y[i.index()]); } } } private: const matrix_type& _A_; const communication_type& communication; mutable bool buildcomm; mutable std::vector mask; mutable std::multimap bordercontribution; }; /** @} */ /** * @addtogroup ISTL_SP * @{ */ /** * \brief Nonoverlapping Scalar Product with communication object. * * Consistent vectors in interior and border are assumed. */ template class NonoverlappingSchwarzScalarProduct : public ScalarProduct { public: //! \brief The type of the domain. typedef X domain_type; //! \brief The type of the range typedef typename X::field_type field_type; //! \brief The real-type of the range typedef typename FieldTraits::real_type real_type; //! \brief The type of the communication object typedef C communication_type; //! define the category enum {category=SolverCategory::nonoverlapping}; /*! \brief Constructor * \param com The communication object for syncing owner and copy * data points. (E.~g. OwnerOverlapCommunication ) */ NonoverlappingSchwarzScalarProduct (const communication_type& com) : communication(com) {} /*! \brief Dot product of two vectors. It is assumed that the vectors are consistent on the interior+border partition. */ virtual field_type dot (const X& x, const X& y) { field_type result; communication.dot(x,y,result); return result; } /*! \brief Norm of a right-hand side vector. The vector must be consistent on the interior+border partition */ virtual real_type norm (const X& x) { return communication.norm(x); } /*! \brief make additive vector consistent */ void make_consistent (X& x) const { communication.copyOwnerToAll(x,x); } private: const communication_type& communication; }; template struct ScalarProductChooser { /** @brief The type of the scalar product for the nonoverlapping case. */ typedef NonoverlappingSchwarzScalarProduct ScalarProduct; /** @brief The type of the communication object to use. */ typedef C communication_type; enum { /** @brief The solver category. */ solverCategory=SolverCategory::nonoverlapping }; static ScalarProduct* construct(const communication_type& comm) { return new ScalarProduct(comm); } }; namespace Amg { template class ConstructionTraits; } /** * @brief Nonoverlapping parallel preconditioner. * * This is essentially a wrapper that take a sequential * preconditoner. In each step the sequential preconditioner * is applied and then all owner data points are updated on * all other processes. */ template class NonoverlappingBlockPreconditioner : public Dune::Preconditioner { friend class Amg::ConstructionTraits >; public: //! \brief The domain type of the preconditioner. typedef typename P::domain_type domain_type; //! \brief The range type of the preconditioner. typedef typename P::range_type range_type; //! \brief The type of the communication object. typedef C communication_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::nonoverlapping }; /*! \brief Constructor. constructor gets all parameters to operate the prec. \param prec The sequential preconditioner. \param c The communication object for syncing owner and copy data points. (E.~g. OwnerOverlapCommunication ) */ NonoverlappingBlockPreconditioner (P& prec, const communication_type& c) : preconditioner(prec), communication(c) {} /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(domain_type&,range_type&) */ virtual void pre (domain_type& x, range_type& b) { preconditioner.pre(x,b); } /*! \brief Apply the preconditioner \copydoc Preconditioner::apply(domain_type&,const range_type&) */ virtual void apply (domain_type& v, const range_type& d) { // block preconditioner equivalent to WrappedPreconditioner from // pdelab/backend/ovlpistsolverbackend.hh, // but not to BlockPreconditioner from schwarz.hh preconditioner.apply(v,d); communication.addOwnerCopyToOwnerCopy(v,v); } /*! \brief Clean up. \copydoc Preconditioner::post(domain_type&) */ virtual void post (domain_type& x) { preconditioner.post(x); } private: //! \brief a sequential preconditioner P& preconditioner; //! \brief the communication object const communication_type& communication; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/operators.hh000066400000000000000000000110211313314427100176620ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_OPERATORS_HH #define DUNE_ISTL_OPERATORS_HH #include #include #include #include #include #include "solvercategory.hh" namespace Dune { /** * @defgroup ISTL_Operators Operator concept * @ingroup ISTL_Solvers * * The solvers in ISTL do not work on matrices directly. Instead we use * an abstract operator concept. This allows for using matrix-free * operators, i.e. operators that are not stored as matrices in any * form. Thus our solver algorithms can easily be turned into matrix-free * solvers just by plugging in matrix-free representations of linear * operators and preconditioners. */ /** @addtogroup ISTL_Operators @{ */ /** \file \brief Define general, extensible interface for operators. The available implementation wraps a matrix. */ //===================================================================== // Abstract operator interface //===================================================================== /*! @brief A linear operator. Abstract base class defining a linear operator \f$ A : X\to Y\f$, i.e. \f$ A(\alpha x) = \alpha A(x) \f$ and \f$ A(x+y) = A(x)+A(y)\f$ hold. The simplest solvers just need the application \f$ A(x)\f$ of the operator. - enables on the fly computation through operator concept. If explicit representation of the operator is required use AssembledLinearOperator - Some inverters may need an explicit formation of the operator as a matrix, e.g. BiCGStab, ILU, AMG, etc. In that case use the derived class */ template class LinearOperator { public: //! The type of the domain of the operator. typedef X domain_type; //! The type of the range of the operator. typedef Y range_type; //! The field type of the operator. typedef typename X::field_type field_type; /*! \brief apply operator to x: \f$ y = A(x) \f$ The input vector is consistent and the output must also be consistent on the interior+border partition. */ virtual void apply (const X& x, Y& y) const = 0; //! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$ virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const = 0; //! every abstract base class has a virtual destructor virtual ~LinearOperator () {} }; /*! \brief A linear operator exporting itself in matrix form. Linear Operator that exports the operator in matrix form. This is needed for certain solvers, such as LU decomposition, ILU preconditioners or BiCG-Stab (because of multiplication with A^T). */ template class AssembledLinearOperator : public LinearOperator { public: //! export types, usually they come from the derived class typedef M matrix_type; typedef X domain_type; typedef Y range_type; typedef typename X::field_type field_type; //! get matrix via * virtual const M& getmat () const = 0; //! every abstract base class has a virtual destructor virtual ~AssembledLinearOperator () {} }; //===================================================================== // Implementation for ISTL-matrix based operator //===================================================================== /*! \brief Adapter to turn a matrix into a linear operator. Adapts a matrix to the assembled linear operator interface */ template class MatrixAdapter : public AssembledLinearOperator { public: //! export types typedef M matrix_type; typedef X domain_type; typedef Y range_type; typedef typename X::field_type field_type; //! define the category enum {category=SolverCategory::sequential}; //! constructor: just store a reference to a matrix explicit MatrixAdapter (const M& A) : _A_(A) {} //! apply operator to x: \f$ y = A(x) \f$ virtual void apply (const X& x, Y& y) const { _A_.mv(x,y); } //! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$ virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const { _A_.usmv(alpha,x,y); } //! get matrix via * virtual const M& getmat () const { return _A_; } private: const M& _A_; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/overlappingschwarz.hh000066400000000000000000001460521313314427100216110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_OVERLAPPINGSCHWARZ_HH #define DUNE_ISTL_OVERLAPPINGSCHWARZ_HH #include #include #include #include #include #include #include #include #include "preconditioners.hh" #include "superlu.hh" #include "umfpack.hh" #include "bvector.hh" #include "bcrsmatrix.hh" #include "ilusubdomainsolver.hh" #include namespace Dune { /** * @addtogroup ISTL_Prec * * @{ */ /** * @file * @author Markus Blatt * @brief Contains one level overlapping Schwarz preconditioners */ template class SeqOverlappingSchwarz; /** * @brief Initializer for SuperLU Matrices representing the subdomains. */ template class OverlappingSchwarzInitializer { public: /** @brief The vector type containing the subdomain to row index mapping. */ typedef D subdomain_vector; typedef I InitializerList; typedef typename InitializerList::value_type AtomInitializer; typedef typename AtomInitializer::Matrix Matrix; typedef typename Matrix::const_iterator Iter; typedef typename Matrix::row_type::const_iterator CIter; typedef S IndexSet; typedef typename IndexSet::size_type size_type; OverlappingSchwarzInitializer(InitializerList& il, const IndexSet& indices, const subdomain_vector& domains); void addRowNnz(const Iter& row); void allocate(); void countEntries(const Iter& row, const CIter& col) const; void calcColstart() const; void copyValue(const Iter& row, const CIter& col) const; void createMatrix() const; private: class IndexMap { public: typedef typename S::size_type size_type; typedef std::map Map; typedef typename Map::iterator iterator; typedef typename Map::const_iterator const_iterator; IndexMap(); void insert(size_type grow); const_iterator find(size_type grow) const; iterator find(size_type grow); iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; private: std::map map_; size_type row; }; typedef typename InitializerList::iterator InitIterator; typedef typename IndexSet::const_iterator IndexIteratur; InitializerList* initializers; const IndexSet *indices; mutable std::vector indexMaps; const subdomain_vector& domains; }; /** * @brief Tag that the tells the schwarz method to be additive. */ struct AdditiveSchwarzMode {}; /** * @brief Tag that tells the Schwarz method to be multiplicative. */ struct MultiplicativeSchwarzMode {}; /** * @brief Tag that tells the Schwarz method to be multiplicative * and symmetric. */ struct SymmetricMultiplicativeSchwarzMode {}; /** * @brief Exact subdomain solver using Dune::DynamicMatrix::solve * @tparam M The type of the matrix. */ template class DynamicMatrixSubdomainSolver; // Specialization for BCRSMatrix template class DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y > { typedef BCRSMatrix< FieldMatrix, Al> M; public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; typedef K field_type; typedef typename std::remove_const::type rilu_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; /** * @brief Apply the subdomain solver. * @copydoc ILUSubdomainSolver::apply */ void apply (DynamicVector& v, DynamicVector& d) { assert(v.size() > 0); assert(v.size() == d.size()); assert(A.rows() <= v.size()); assert(A.cols() <= v.size()); size_t sz = A.rows(); v.resize(sz); d.resize(sz); A.solve(v,d); v.resize(v.capacity()); d.resize(d.capacity()); } /** * @brief Set the data of the local problem. * * @param BCRS The global matrix. * @param rowset The global indices of the local problem. * @tparam S The type of the set with the indices. */ template void setSubMatrix(const M& BCRS, S& rowset) { size_t sz = rowset.size(); A.resize(sz*n,sz*n); typedef typename S::const_iterator SIter; size_t r = 0, c = 0; for(SIter rowIdx = rowset.begin(), rowEnd=rowset.end(); rowIdx!= rowEnd; ++rowIdx, r++) { c = 0; for(SIter colIdx = rowset.begin(), colEnd=rowset.end(); colIdx!= colEnd; ++colIdx, c++) { if (BCRS[*rowIdx].find(*colIdx) == BCRS[*rowIdx].end()) continue; for (size_t i=0; i A; }; template class OverlappingAssignerHelper {}; template using OverlappingAssigner = OverlappingAssignerHelper::value>; // specialization for DynamicMatrix template class OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> { public: typedef BCRSMatrix< FieldMatrix, Al> matrix_type; typedef K field_type; typedef Y range_type; typedef typename range_type::block_type block_type; typedef typename matrix_type::size_type size_type; /** * @brief Constructor. * @param maxlength The maximum entries over all subdomains. * @param mat_ The global matrix. * @param b_ the global right hand side. * @param x_ the global left hand side. */ OverlappingAssignerHelper(std::size_t maxlength, const BCRSMatrix, Al>& mat_, const X& b_, Y& x_); /** * @brief Deallocates memory of the local vector. */ inline void deallocate(); /** * @brief Resets the local index to zero. */ inline void resetIndexForNextDomain(); /** * @brief Get the local left hand side. * @return The local left hand side. */ inline DynamicVector & lhs(); /** * @brief Get the local right hand side. * @return The local right hand side. */ inline DynamicVector & rhs(); /** * @brief relax the result. * @param relax The relaxation parameter. */ inline void relaxResult(field_type relax); /** * @brief calculate one entry of the local defect. * @param domainIndex One index of the domain. */ void operator()(const size_type& domainIndex); /** * @brief Assigns the block to the current local * index. * At the same time the local defect is calculated * for the index and stored in the rhs. * Afterwards the is incremented for the next block. */ inline void assignResult(block_type& res); private: /** * @brief The global matrix for the defect calculation. */ const matrix_type* mat; /** @brief The local right hand side. */ // we need a pointer, because we have to avoid deep copies DynamicVector * rhs_; /** @brief The local left hand side. */ // we need a pointer, because we have to avoid deep copies DynamicVector * lhs_; /** @brief The global right hand side for the defect calculation. */ const range_type* b; /** @brief The global right hand side for adding the local update to. */ range_type* x; /** @brief The current local index. */ std::size_t i; /** @brief The maximum entries over all subdomains. */ std::size_t maxlength_; }; #if HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK template class S, int n, int m, typename T, typename A> struct OverlappingAssignerHelper, A> >, true> { typedef BCRSMatrix, A> matrix_type; typedef typename S, A> >::range_type range_type; typedef typename range_type::field_type field_type; typedef typename range_type::block_type block_type; typedef typename matrix_type::size_type size_type; /** * @brief Constructor. * @param maxlength The maximum entries over all subdomains. * @param mat The global matrix. * @param b the global right hand side. * @param x the global left hand side. */ OverlappingAssignerHelper(std::size_t maxlength, const matrix_type& mat, const range_type& b, range_type& x); /** * @brief Deallocates memory of the local vector. * @warning memory is released by the destructor as this Functor * is copied and the copy needs to still have the data. */ void deallocate(); /* * @brief Resets the local index to zero. */ void resetIndexForNextDomain(); /** * @brief Get the local left hand side. * @return The local left hand side. */ field_type* lhs(); /** * @brief Get the local right hand side. * @return The local right hand side. */ field_type* rhs(); /** * @brief relax the result. * @param relax The relaxation parameter. */ void relaxResult(field_type relax); /** * @brief calculate one entry of the local defect. * @param domain One index of the domain. */ void operator()(const size_type& domain); /** * @brief Assigns the block to the current local * index. * At the same time the local defect is calculated * for the index and stored in the rhs. * Afterwards the is incremented for the next block. */ void assignResult(block_type& res); private: /** * @brief The global matrix for the defect calculation. */ const matrix_type* mat; /** @brief The local right hand side. */ field_type* rhs_; /** @brief The local left hand side. */ field_type* lhs_; /** @brief The global right hand side for the defect calculation. */ const range_type* b; /** @brief The global right hand side for adding the local update to. */ range_type* x; /** @brief The current local index. */ std::size_t i; /** @brief The maximum entries over all subdomains. */ std::size_t maxlength_; }; #endif // HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK template class OverlappingAssignerILUBase { public: typedef M matrix_type; typedef typename M::field_type field_type; typedef typename Y::block_type block_type; typedef typename matrix_type::size_type size_type; /** * @brief Constructor. * @param maxlength The maximum entries over all subdomains. * @param mat The global matrix. * @param b the global right hand side. * @param x the global left hand side. */ OverlappingAssignerILUBase(std::size_t maxlength, const M& mat, const Y& b, X& x); /** * @brief Deallocates memory of the local vector. * @warning memory is released by the destructor as this Functor * is copied and the copy needs to still have the data. */ void deallocate(); /** * @brief Resets the local index to zero. */ void resetIndexForNextDomain(); /** * @brief Get the local left hand side. * @return The local left hand side. */ X& lhs(); /** * @brief Get the local right hand side. * @return The local right hand side. */ Y& rhs(); /** * @brief relax the result. * @param relax The relaxation parameter. */ void relaxResult(field_type relax); /** * @brief calculate one entry of the local defect. * @param domain One index of the domain. */ void operator()(const size_type& domain); /** * @brief Assigns the block to the current local * index. * At the same time the local defect is calculated * for the index and stored in the rhs. * Afterwards the is incremented for the next block. */ void assignResult(block_type& res); private: /** * @brief The global matrix for the defect calculation. */ const M* mat; /** @brief The local left hand side. */ X* lhs_; /** @brief The local right hand side. */ Y* rhs_; /** @brief The global right hand side for the defect calculation. */ const Y* b; /** @brief The global left hand side for adding the local update to. */ X* x; /** @brief The maximum entries over all subdomains. */ size_type i; }; // specialization for ILU0 template class OverlappingAssignerHelper, false> : public OverlappingAssignerILUBase { public: /** * @brief Constructor. * @param maxlength The maximum entries over all subdomains. * @param mat The global matrix. * @param b the global right hand side. * @param x the global left hand side. */ OverlappingAssignerHelper(std::size_t maxlength, const M& mat, const Y& b, X& x) : OverlappingAssignerILUBase(maxlength, mat,b,x) {} }; // specialization for ILUN template class OverlappingAssignerHelper,false> : public OverlappingAssignerILUBase { public: /** * @brief Constructor. * @param maxlength The maximum entries over all subdomains. * @param mat The global matrix. * @param b the global right hand side. * @param x the global left hand side. */ OverlappingAssignerHelper(std::size_t maxlength, const M& mat, const Y& b, X& x) : OverlappingAssignerILUBase(maxlength, mat,b,x) {} }; template struct AdditiveAdder {}; template struct AdditiveAdder,A> > { typedef typename A::size_type size_type; AdditiveAdder(BlockVector,A>& v, BlockVector,A>& x, OverlappingAssigner& assigner, const T& relax_); void operator()(const size_type& domain); void axpy(); private: BlockVector,A>* v; BlockVector,A>* x; OverlappingAssigner* assigner; T relax; }; template struct MultiplicativeAdder {}; template struct MultiplicativeAdder,A> > { typedef typename A::size_type size_type; MultiplicativeAdder(BlockVector,A>& v, BlockVector,A>& x, OverlappingAssigner& assigner_, const T& relax_); void operator()(const size_type& domain); void axpy(); private: BlockVector,A>* x; OverlappingAssigner* assigner; T relax; }; /** * @brief template meta program for choosing how to add the correction. * * There are specialization for the additive, the multiplicative, and the symmetric multiplicative mode. * * \tparam T The Schwarz mode (either AdditiveSchwarzMode or MuliplicativeSchwarzMode or * SymmetricMultiplicativeSchwarzMode) * \tparam X The vector field type */ template struct AdderSelector {}; template struct AdderSelector { typedef AdditiveAdder Adder; }; template struct AdderSelector { typedef MultiplicativeAdder Adder; }; template struct AdderSelector { typedef MultiplicativeAdder Adder; }; /** * @brief Helper template meta program for application of overlapping schwarz. * * The is needed because when using the multiplicative schwarz version one * might still want to make multigrid symmetric, i.e. forward sweep when pre- * and backward sweep when post-smoothing. * * @tparam T1 type of the vector with the subdomain solvers. * @tparam T2 type of the vector with the subdomain vector fields. * @tparam forward If true apply in a forward sweep. */ template struct IteratorDirectionSelector { typedef T1 solver_vector; typedef typename solver_vector::iterator solver_iterator; typedef T2 subdomain_vector; typedef typename subdomain_vector::const_iterator domain_iterator; static solver_iterator begin(solver_vector& sv) { return sv.begin(); } static solver_iterator end(solver_vector& sv) { return sv.end(); } static domain_iterator begin(const subdomain_vector& sv) { return sv.begin(); } static domain_iterator end(const subdomain_vector& sv) { return sv.end(); } }; template struct IteratorDirectionSelector { typedef T1 solver_vector; typedef typename solver_vector::reverse_iterator solver_iterator; typedef T2 subdomain_vector; typedef typename subdomain_vector::const_reverse_iterator domain_iterator; static solver_iterator begin(solver_vector& sv) { return sv.rbegin(); } static solver_iterator end(solver_vector& sv) { return sv.rend(); } static domain_iterator begin(const subdomain_vector& sv) { return sv.rbegin(); } static domain_iterator end(const subdomain_vector& sv) { return sv.rend(); } }; /** * @brief Helper template meta program for application of overlapping schwarz. * * The is needed because when using the multiplicative schwarz version one * might still want to make multigrid symmetric, i.e. forward sweep when pre- * and backward sweep when post-smoothing. * @tparam T The smoother to apply. */ template struct SeqOverlappingSchwarzApplier { typedef T smoother; typedef typename smoother::range_type range_type; static void apply(smoother& sm, range_type& v, const range_type& b) { sm.template apply(v, b); } }; template struct SeqOverlappingSchwarzApplier > { typedef SeqOverlappingSchwarz smoother; typedef typename smoother::range_type range_type; static void apply(smoother& sm, range_type& v, const range_type& b) { sm.template apply(v, b); sm.template apply(v, b); } }; template struct SeqOverlappingSchwarzAssemblerHelper {}; template using SeqOverlappingSchwarzAssembler = SeqOverlappingSchwarzAssemblerHelper::value>; template struct SeqOverlappingSchwarzAssemblerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> { typedef BCRSMatrix< FieldMatrix, Al> matrix_type; template static std::size_t assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& domains, bool onTheFly); }; template class S, typename T, typename A, int m, int n> struct SeqOverlappingSchwarzAssemblerHelper,A> >,true> { typedef BCRSMatrix,A> matrix_type; template static std::size_t assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& domains, bool onTheFly); }; template struct SeqOverlappingSchwarzAssemblerILUBase { typedef M matrix_type; template static std::size_t assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& domains, bool onTheFly); }; template struct SeqOverlappingSchwarzAssemblerHelper,false> : public SeqOverlappingSchwarzAssemblerILUBase {}; template struct SeqOverlappingSchwarzAssemblerHelper,false> : public SeqOverlappingSchwarzAssemblerILUBase {}; /** * @brief Sequential overlapping Schwarz preconditioner * * @tparam M The matrix type. * @tparam X The range and domain type. * @tparam TM The Schwarz mode. Currently supported modes are AdditiveSchwarzMode, * MultiplicativeSchwarzMode, and SymmetricMultiplicativeSchwarzMode. (Default values is AdditiveSchwarzMode) * @tparam TD The type of the local subdomain solver to be used. * @tparam TA The type of the allocator to use. */ template, class TA=std::allocator > class SeqOverlappingSchwarz : public Preconditioner { public: /** * @brief The type of the matrix to precondition. */ typedef M matrix_type; /** * @brief The domain type of the preconditioner */ typedef X domain_type; /** * @brief The range type of the preconditioner. */ typedef X range_type; /** * @brief The mode (additive or multiplicative) of the Schwarz * method. * * Either AdditiveSchwarzMode or MultiplicativeSchwarzMode */ typedef TM Mode; /** * @brief The field type of the preconditioner. */ typedef typename X::field_type field_type; /** @brief The return type of the size method. */ typedef typename matrix_type::size_type size_type; /** @brief The allocator to use. */ typedef TA allocator; /** @brief The type for the subdomain to row index mapping. */ typedef std::set, typename TA::template rebind::other> subdomain_type; /** @brief The vector type containing the subdomain to row index mapping. */ typedef std::vector::other> subdomain_vector; /** @brief The type for the row to subdomain mapping. */ typedef SLList::other> subdomain_list; /** @brief The vector type containing the row index to subdomain mapping. */ typedef std::vector::other > rowtodomain_vector; /** @brief The type for the subdomain solver in use. */ typedef TD slu; /** @brief The vector type containing subdomain solvers. */ typedef std::vector::other> slu_vector; enum { //! \brief The category the precondtioner is part of. category = SolverCategory::sequential }; /** * @brief Construct the overlapping Schwarz method. * @param mat The matrix to precondition. * @param subDomains Array of sets of rowindices belonging to an overlapping * subdomain * @param relaxationFactor relaxation factor * @param onTheFly_ If true the decomposition of the exact local solvers is * computed on the fly for each subdomain and * iteration step. If false all decompositions are computed in pre and * only forward and backward substitution takes place * in the iteration steps. * @warning Each rowindex should be part of at least one subdomain! */ SeqOverlappingSchwarz(const matrix_type& mat, const subdomain_vector& subDomains, field_type relaxationFactor=1, bool onTheFly_=true); /** * Construct the overlapping Schwarz method * @param mat The matrix to precondition. * @param rowToDomain The mapping of the rows onto the domains. * @param relaxationFactor relaxation factor * @param onTheFly_ If true the decomposition of the exact local solvers is * computed on the fly for each subdomain and * iteration step. If false all decompositions are computed in pre and * only forward and backward substitution takes place * in the iteration steps. */ SeqOverlappingSchwarz(const matrix_type& mat, const rowtodomain_vector& rowToDomain, field_type relaxationFactor=1, bool onTheFly_=true); /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, X& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the precondtioner \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const X& d); /*! \brief Postprocess the preconditioner. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } template void apply(X& v, const X& d); private: const M& mat; slu_vector solvers; subdomain_vector subDomains; field_type relax; typename M::size_type maxlength; bool onTheFly; }; template OverlappingSchwarzInitializer::OverlappingSchwarzInitializer(InitializerList& il, const IndexSet& idx, const subdomain_vector& domains_) : initializers(&il), indices(&idx), indexMaps(il.size()), domains(domains_) {} template void OverlappingSchwarzInitializer::addRowNnz(const Iter& row) { typedef typename IndexSet::value_type::const_iterator iterator; for(iterator domain=(*indices)[row.index()].begin(); domain != (*indices)[row.index()].end(); ++domain) { (*initializers)[*domain].addRowNnz(row, domains[*domain]); indexMaps[*domain].insert(row.index()); } } template void OverlappingSchwarzInitializer::allocate() { std::for_each(initializers->begin(), initializers->end(), std::mem_fun_ref(&AtomInitializer::allocateMatrixStorage)); std::for_each(initializers->begin(), initializers->end(), std::mem_fun_ref(&AtomInitializer::allocateMarker)); } template void OverlappingSchwarzInitializer::countEntries(const Iter& row, const CIter& col) const { typedef typename IndexSet::value_type::const_iterator iterator; for(iterator domain=(*indices)[row.index()].begin(); domain != (*indices)[row.index()].end(); ++domain) { typename std::map::const_iterator v = indexMaps[*domain].find(col.index()); if(v!= indexMaps[*domain].end()) { (*initializers)[*domain].countEntries(indexMaps[*domain].find(col.index())->second); } } } template void OverlappingSchwarzInitializer::calcColstart() const { std::for_each(initializers->begin(), initializers->end(), std::mem_fun_ref(&AtomInitializer::calcColstart)); } template void OverlappingSchwarzInitializer::copyValue(const Iter& row, const CIter& col) const { typedef typename IndexSet::value_type::const_iterator iterator; for(iterator domain=(*indices)[row.index()].begin(); domain!= (*indices)[row.index()].end(); ++domain) { typename std::map::const_iterator v = indexMaps[*domain].find(col.index()); if(v!= indexMaps[*domain].end()) { assert(indexMaps[*domain].end()!=indexMaps[*domain].find(row.index())); (*initializers)[*domain].copyValue(col, indexMaps[*domain].find(row.index())->second, v->second); } } } template void OverlappingSchwarzInitializer::createMatrix() const { std::vector().swap(indexMaps); std::for_each(initializers->begin(), initializers->end(), std::mem_fun_ref(&AtomInitializer::createMatrix)); } template OverlappingSchwarzInitializer::IndexMap::IndexMap() : row(0) {} template void OverlappingSchwarzInitializer::IndexMap::insert(size_type grow) { assert(map_.find(grow)==map_.end()); map_.insert(std::make_pair(grow, row++)); } template typename OverlappingSchwarzInitializer::IndexMap::const_iterator OverlappingSchwarzInitializer::IndexMap::find(size_type grow) const { return map_.find(grow); } template typename OverlappingSchwarzInitializer::IndexMap::iterator OverlappingSchwarzInitializer::IndexMap::find(size_type grow) { return map_.find(grow); } template typename OverlappingSchwarzInitializer::IndexMap::const_iterator OverlappingSchwarzInitializer::IndexMap::end() const { return map_.end(); } template typename OverlappingSchwarzInitializer::IndexMap::iterator OverlappingSchwarzInitializer::IndexMap::end() { return map_.end(); } template typename OverlappingSchwarzInitializer::IndexMap::const_iterator OverlappingSchwarzInitializer::IndexMap::begin() const { return map_.begin(); } template typename OverlappingSchwarzInitializer::IndexMap::iterator OverlappingSchwarzInitializer::IndexMap::begin() { return map_.begin(); } template SeqOverlappingSchwarz::SeqOverlappingSchwarz(const matrix_type& mat_, const rowtodomain_vector& rowToDomain, field_type relaxationFactor, bool fly) : mat(mat_), relax(relaxationFactor), onTheFly(fly) { typedef typename rowtodomain_vector::const_iterator RowDomainIterator; typedef typename subdomain_list::const_iterator DomainIterator; #ifdef DUNE_ISTL_WITH_CHECKING assert(rowToDomain.size()==mat.N()); assert(rowToDomain.size()==mat.M()); for(RowDomainIterator iter=rowToDomain.begin(); iter != rowToDomain.end(); ++iter) assert(iter->size()>0); #endif // calculate the number of domains size_type domains=0; for(RowDomainIterator iter=rowToDomain.begin(); iter != rowToDomain.end(); ++iter) for(DomainIterator d=iter->begin(); d != iter->end(); ++d) domains=std::max(domains, *d); ++domains; solvers.resize(domains); subDomains.resize(domains); // initialize subdomains to row mapping from row to subdomain mapping size_type row=0; for(RowDomainIterator iter=rowToDomain.begin(); iter != rowToDomain.end(); ++iter, ++row) for(DomainIterator d=iter->begin(); d != iter->end(); ++d) subDomains[*d].insert(row); #ifdef DUNE_ISTL_WITH_CHECKING size_type i=0; typedef typename subdomain_vector::const_iterator iterator; for(iterator iter=subDomains.begin(); iter != subDomains.end(); ++iter) { typedef typename subdomain_type::const_iterator entry_iterator; Dune::dvverb<<"domain "<begin(); entry != iter->end(); ++entry) { Dune::dvverb<<" "<<*entry; } Dune::dvverb< ::assembleLocalProblems(rowToDomain, mat, solvers, subDomains, onTheFly); } template SeqOverlappingSchwarz::SeqOverlappingSchwarz(const matrix_type& mat_, const subdomain_vector& sd, field_type relaxationFactor, bool fly) : mat(mat_), solvers(sd.size()), subDomains(sd), relax(relaxationFactor), onTheFly(fly) { typedef typename subdomain_vector::const_iterator DomainIterator; #ifdef DUNE_ISTL_WITH_CHECKING size_type i=0; for(DomainIterator d=sd.begin(); d != sd.end(); ++d,++i) { //std::cout<size()<size()>0); typedef typename DomainIterator::value_type::const_iterator entry_iterator; Dune::dvverb<<"domain "<begin(); entry != d->end(); ++entry) { Dune::dvverb<<" "<<*entry; } Dune::dvverb<begin(); row != domain->end(); ++row) rowToDomain[*row].push_back(domainId); } maxlength = SeqOverlappingSchwarzAssembler ::assembleLocalProblems(rowToDomain, mat, solvers, subDomains, onTheFly); } /** template helper struct to determine the size of a domain for the SeqOverlappingSchwarz solver only implemented for BCRSMatrix */ template struct SeqOverlappingSchwarzDomainSize {}; template struct SeqOverlappingSchwarzDomainSize,A > > { template static int size(const Domain & d) { assert(n==m); return m*d.size(); } }; template template std::size_t SeqOverlappingSchwarzAssemblerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false>:: assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& subDomains, bool onTheFly) { DUNE_UNUSED_PARAMETER(onTheFly); DUNE_UNUSED_PARAMETER(rowToDomain); DUNE_UNUSED_PARAMETER(mat); DUNE_UNUSED_PARAMETER(solvers); typedef typename SubDomains::const_iterator DomainIterator; std::size_t maxlength = 0; assert(onTheFly); for(DomainIterator domain=subDomains.begin(); domain!=subDomains.end(); ++domain) maxlength=std::max(maxlength, domain->size()); maxlength*=n; return maxlength; } #if HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK template class S, typename T, typename A, int m, int n> template std::size_t SeqOverlappingSchwarzAssemblerHelper,A> >,true>::assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& subDomains, bool onTheFly) { typedef typename S,A> >::MatrixInitializer MatrixInitializer; typedef typename std::vector::iterator InitializerIterator; typedef typename SubDomains::const_iterator DomainIterator; typedef typename Solvers::iterator SolverIterator; std::size_t maxlength = 0; if(onTheFly) { for(DomainIterator domain=subDomains.begin(); domain!=subDomains.end(); ++domain) maxlength=std::max(maxlength, domain->size()); maxlength*=mat[0].begin()->N(); }else{ // initialize the initializers DomainIterator domain=subDomains.begin(); // Create the initializers list. std::vector initializers(subDomains.size()); SolverIterator solver=solvers.begin(); for(InitializerIterator initializer=initializers.begin(); initializer!=initializers.end(); ++initializer, ++solver, ++domain) { solver->getInternalMatrix().N_=SeqOverlappingSchwarzDomainSize::size(*domain); solver->getInternalMatrix().M_=SeqOverlappingSchwarzDomainSize::size(*domain); //solver->setVerbosity(true); *initializer=MatrixInitializer(solver->getInternalMatrix()); } // Set up the supermatrices according to the subdomains typedef OverlappingSchwarzInitializer, RowToDomain, SubDomains> Initializer; Initializer initializer(initializers, rowToDomain, subDomains); copyToColCompMatrix(initializer, mat); // Calculate the LU decompositions std::for_each(solvers.begin(), solvers.end(), std::mem_fun_ref(&S,A> >::decompose)); for (SolverIterator solverIt = solvers.begin(); solverIt != solvers.end(); ++solverIt) { assert(solverIt->getInternalMatrix().N() == solverIt->getInternalMatrix().M()); maxlength = std::max(maxlength, solverIt->getInternalMatrix().N()); } } return maxlength; } #endif // HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK template template std::size_t SeqOverlappingSchwarzAssemblerILUBase::assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat, Solvers& solvers, const SubDomains& subDomains, bool onTheFly) { DUNE_UNUSED_PARAMETER(rowToDomain); typedef typename SubDomains::const_iterator DomainIterator; typedef typename Solvers::iterator SolverIterator; std::size_t maxlength = 0; if(onTheFly) { for(DomainIterator domain=subDomains.begin(); domain!=subDomains.end(); ++domain) maxlength=std::max(maxlength, domain->size()); }else{ // initialize the solvers of the local prolems. SolverIterator solver=solvers.begin(); for(DomainIterator domain=subDomains.begin(); domain!=subDomains.end(); ++domain, ++solver) { solver->setSubMatrix(mat, *domain); maxlength=std::max(maxlength, domain->size()); } } return maxlength; } template void SeqOverlappingSchwarz::apply(X& x, const X& b) { SeqOverlappingSchwarzApplier::apply(*this, x, b); } template template void SeqOverlappingSchwarz::apply(X& x, const X& b) { typedef slu_vector solver_vector; typedef typename IteratorDirectionSelector::solver_iterator iterator; typedef typename IteratorDirectionSelector::domain_iterator domain_iterator; OverlappingAssigner assigner(maxlength, mat, b, x); domain_iterator domain=IteratorDirectionSelector::begin(subDomains); iterator solver = IteratorDirectionSelector::begin(solvers); X v(x); // temporary for the update v=0; typedef typename AdderSelector::Adder Adder; Adder adder(v, x, assigner, relax); for(; domain != IteratorDirectionSelector::end(subDomains); ++domain) { //Copy rhs to C-array for SuperLU std::for_each(domain->begin(), domain->end(), assigner); assigner.resetIndexForNextDomain(); if(onTheFly) { // Create the subdomain solver slu sdsolver; sdsolver.setSubMatrix(mat, *domain); // Apply sdsolver.apply(assigner.lhs(), assigner.rhs()); }else{ solver->apply(assigner.lhs(), assigner.rhs()); ++solver; } //Add relaxed correction to from SuperLU to v std::for_each(domain->begin(), domain->end(), adder); assigner.resetIndexForNextDomain(); } adder.axpy(); assigner.deallocate(); } template OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::OverlappingAssignerHelper(std::size_t maxlength, const BCRSMatrix, Al>& mat_, const X& b_, Y& x_) : mat(&mat_), rhs_( new DynamicVector(maxlength, 42) ), lhs_( new DynamicVector(maxlength, -42) ), b(&b_), x(&x_), i(0), maxlength_(maxlength) {} template void OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::deallocate() { delete rhs_; delete lhs_; } template void OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::resetIndexForNextDomain() { i=0; } template DynamicVector & OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::lhs() { return *lhs_; } template DynamicVector & OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::rhs() { return *rhs_; } template void OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::relaxResult(field_type relax) { lhs() *= relax; } template void OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::operator()(const size_type& domainIndex) { lhs() = 0.0; #if 0 //assign right hand side of current domainindex block for(size_type j=0; j void OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix, Al>, X, Y >,false> ::assignResult(block_type& res) { // assign the result of the local solve to the global vector for(size_type j=0; j class S, int n, int m, typename T, typename A> OverlappingAssignerHelper,A> >,true> ::OverlappingAssignerHelper(std::size_t maxlength, const BCRSMatrix,A>& mat_, const range_type& b_, range_type& x_) : mat(&mat_), b(&b_), x(&x_), i(0), maxlength_(maxlength) { rhs_ = new field_type[maxlength]; lhs_ = new field_type[maxlength]; } template class S, int n, int m, typename T, typename A> void OverlappingAssignerHelper,A> >,true>::deallocate() { delete[] rhs_; delete[] lhs_; } template class S, int n, int m, typename T, typename A> void OverlappingAssignerHelper,A> >,true>::operator()(const size_type& domainIndex) { //assign right hand side of current domainindex block // rhs is an array of doubles! // rhs[starti] = b[domainindex] for(size_type j=0; j class S, int n, int m, typename T, typename A> void OverlappingAssignerHelper,A> >,true>::relaxResult(field_type relax) { for(size_type j=i+n; i class S, int n, int m, typename T, typename A> void OverlappingAssignerHelper,A> >,true>::assignResult(block_type& res) { // assign the result of the local solve to the global vector for(size_type j=0; j class S, int n, int m, typename T, typename A> void OverlappingAssignerHelper,A> >,true>::resetIndexForNextDomain() { i=0; } template class S, int n, int m, typename T, typename A> typename OverlappingAssignerHelper,A> >,true>::field_type* OverlappingAssignerHelper,A> >,true>::lhs() { return lhs_; } template class S, int n, int m, typename T, typename A> typename OverlappingAssignerHelper,A> >,true>::field_type* OverlappingAssignerHelper,A> >,true>::rhs() { return rhs_; } #endif // HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK template OverlappingAssignerILUBase::OverlappingAssignerILUBase(std::size_t maxlength, const M& mat_, const Y& b_, X& x_) : mat(&mat_), b(&b_), x(&x_), i(0) { rhs_= new Y(maxlength); lhs_ = new X(maxlength); } template void OverlappingAssignerILUBase::deallocate() { delete rhs_; delete lhs_; } template void OverlappingAssignerILUBase::operator()(const size_type& domainIndex) { (*rhs_)[i]=(*b)[domainIndex]; // loop over all Matrix row entries and calculate defect. typedef typename matrix_type::ConstColIterator col_iterator; // calculate defect for current row index block for(col_iterator col=(*mat)[domainIndex].begin(); col!=(*mat)[domainIndex].end(); ++col) { (*col).mmv((*x)[col.index()], (*rhs_)[i]); } // Goto next local index ++i; } template void OverlappingAssignerILUBase::relaxResult(field_type relax) { (*lhs_)[i]*=relax; } template void OverlappingAssignerILUBase::assignResult(block_type& res) { res+=(*lhs_)[i++]; } template X& OverlappingAssignerILUBase::lhs() { return *lhs_; } template Y& OverlappingAssignerILUBase::rhs() { return *rhs_; } template void OverlappingAssignerILUBase::resetIndexForNextDomain() { i=0; } template AdditiveAdder,A> >::AdditiveAdder(BlockVector,A>& v_, BlockVector,A>& x_, OverlappingAssigner& assigner_, const T& relax_) : v(&v_), x(&x_), assigner(&assigner_), relax(relax_) {} template void AdditiveAdder,A> >::operator()(const size_type& domainIndex) { // add the result of the local solve to the current update assigner->assignResult((*v)[domainIndex]); } template void AdditiveAdder,A> >::axpy() { // relax the update and add it to the current guess. x->axpy(relax,*v); } template MultiplicativeAdder,A> > ::MultiplicativeAdder(BlockVector,A>& v_, BlockVector,A>& x_, OverlappingAssigner& assigner_, const T& relax_) : x(&x_), assigner(&assigner_), relax(relax_) { DUNE_UNUSED_PARAMETER(v_); } template void MultiplicativeAdder,A> >::operator()(const size_type& domainIndex) { // add the result of the local solve to the current guess assigner->relaxResult(relax); assigner->assignResult((*x)[domainIndex]); } template void MultiplicativeAdder,A> >::axpy() { // nothing to do, as the corrections already relaxed and added in operator() } /** @} */ } #endif dune-istl-2.5.1/dune/istl/owneroverlapcopy.hh000066400000000000000000000560231313314427100212750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_OWNEROVERLAPCOPY_HH #define DUNE_ISTL_OWNEROVERLAPCOPY_HH #include #include #include #include #include #include #include #include "cmath" // MPI header #if HAVE_MPI #include #endif #include #if HAVE_MPI #include #include #include #include #endif #include "solvercategory.hh" #include "istlexception.hh" #include #include template class Comm> void testRedistributed(int s); namespace Dune { /** @addtogroup ISTL_Comm @{ */ /** * @file * @brief Classes providing communication interfaces for * overlapping Schwarz methods. * @author Peter Bastian */ /** * @brief Attribute set for overlapping schwarz. */ struct OwnerOverlapCopyAttributeSet { enum AttributeSet { owner=1, overlap=2, copy=3 }; }; /** * @brief Information about the index distribution. * * This class contains information about indices local to * the process together with information about on which * processes those indices are also present together with the * attribute they have there. * * This information might be used to set up an IndexSet together with * an RemoteIndices object needed for the ISTL communication classes. */ template class IndexInfoFromGrid { public: /** @brief The type of the global index. */ typedef G GlobalIdType; /** @brief The type of the local index. */ typedef L LocalIdType; /** * @brief A triple describing a local index. * * The triple consists of the global index and the local * index and an attribute */ typedef std::tuple IndexTripel; /** * @brief A triple describing a remote index. * * The triple consists of a process number and the global index and * the attribute of the index at the remote process. */ typedef std::tuple RemoteIndexTripel; /** * @brief Add a new index triple to the set of local indices. * * @param x The index triple. */ void addLocalIndex (const IndexTripel& x) { if (std::get<2>(x)!=OwnerOverlapCopyAttributeSet::owner && std::get<2>(x)!=OwnerOverlapCopyAttributeSet::overlap && std::get<2>(x)!=OwnerOverlapCopyAttributeSet::copy) DUNE_THROW(ISTLError,"OwnerOverlapCopyCommunication: global index not in index set"); localindices.insert(x); } /** * @brief Add a new remote index triple to the set of remote indices. * * @param x The index triple to add. */ void addRemoteIndex (const RemoteIndexTripel& x) { if (std::get<2>(x)!=OwnerOverlapCopyAttributeSet::owner && std::get<2>(x)!=OwnerOverlapCopyAttributeSet::overlap && std::get<2>(x)!=OwnerOverlapCopyAttributeSet::copy) DUNE_THROW(ISTLError,"OwnerOverlapCopyCommunication: global index not in index set"); remoteindices.insert(x); } /** * @brief Get the set of indices local to the process. * @return The set of local indices. */ const std::set& localIndices () const { return localindices; } /** * @brief Get the set of remote indices. * @return the set of remote indices. */ const std::set& remoteIndices () const { return remoteindices; } /** * @brief Remove all indices from the sets. */ void clear () { localindices.clear(); remoteindices.clear(); } private: /** @brief The set of local indices. */ std::set localindices; /** @brief The set of remote indices. */ std::set remoteindices; }; #if HAVE_MPI /** * @brief A class setting up standard communication for a two-valued * attribute set with owner/overlap/copy semantics. * * set up communication from known distribution with owner/overlap/copy semantics */ template class OwnerOverlapCopyCommunication { template friend void loadMatrixMarket(M&, const std::string&, OwnerOverlapCopyCommunication&, bool); // used types typedef typename IndexInfoFromGrid::IndexTripel IndexTripel; typedef typename IndexInfoFromGrid::RemoteIndexTripel RemoteIndexTripel; typedef typename std::set::const_iterator localindex_iterator; typedef typename std::set::const_iterator remoteindex_iterator; typedef typename OwnerOverlapCopyAttributeSet::AttributeSet AttributeSet; typedef Dune::ParallelLocalIndex LI; public: typedef Dune::ParallelIndexSet PIS; typedef Dune::RemoteIndices RI; typedef Dune::RemoteIndexListModifier RILM; typedef typename RI::RemoteIndex RX; typedef Dune::BufferedCommunicator BC; typedef Dune::Interface IF; typedef EnumItem OwnerSet; typedef EnumItem CopySet; typedef Combine,EnumItem,AttributeSet> OwnerOverlapSet; typedef Dune::AllSet AllSet; protected: /** \brief gather/scatter callback for communcation */ template struct CopyGatherScatter { typedef typename CommPolicy::IndexedType V; static V gather(const T& a, std::size_t i) { return a[i]; } static void scatter(T& a, V v, std::size_t i) { a[i] = v; } }; template struct AddGatherScatter { typedef typename CommPolicy::IndexedType V; static V gather(const T& a, std::size_t i) { return a[i]; } static void scatter(T& a, V v, std::size_t i) { a[i] += v; } }; void buildOwnerOverlapToAllInterface () const { if (OwnerOverlapToAllInterfaceBuilt) OwnerOverlapToAllInterface.free(); typedef Combine,EnumItem,AttributeSet> OwnerOverlapSet; typedef Combine,AttributeSet> AllSet; OwnerOverlapSet sourceFlags; AllSet destFlags; OwnerOverlapToAllInterface.build(ri,sourceFlags,destFlags); OwnerOverlapToAllInterfaceBuilt = true; } void buildOwnerToAllInterface () const { if (OwnerToAllInterfaceBuilt) OwnerToAllInterface.free(); OwnerSet sourceFlags; AllSet destFlags; OwnerToAllInterface.build(ri,sourceFlags,destFlags); OwnerToAllInterfaceBuilt = true; } void buildOwnerCopyToAllInterface () const { if (OwnerCopyToAllInterfaceBuilt) OwnerCopyToAllInterface.free(); typedef Combine,EnumItem,AttributeSet> OwnerCopySet; typedef Combine,AttributeSet> AllSet; OwnerCopySet sourceFlags; AllSet destFlags; OwnerCopyToAllInterface.build(ri,sourceFlags,destFlags); OwnerCopyToAllInterfaceBuilt = true; } void buildOwnerCopyToOwnerCopyInterface () const { if (OwnerCopyToOwnerCopyInterfaceBuilt) OwnerCopyToOwnerCopyInterface.free(); typedef Combine,EnumItem,AttributeSet> OwnerCopySet; OwnerCopySet sourceFlags; OwnerCopySet destFlags; OwnerCopyToOwnerCopyInterface.build(ri,sourceFlags,destFlags); OwnerCopyToOwnerCopyInterfaceBuilt = true; } void buildCopyToAllInterface () const { if (CopyToAllInterfaceBuilt) CopyToAllInterface.free(); CopySet sourceFlags; AllSet destFlags; CopyToAllInterface.build(ri,sourceFlags,destFlags); CopyToAllInterfaceBuilt = true; } public: /** * @brief Set right Solver Category (default is overlapping). */ void setSolverCategory (SolverCategory set) { category = set; } /** * @brief Get Solver Category. * @return The Solver Category. */ SolverCategory::Category getSolverCategory () const { return category; } const CollectiveCommunication& communicator() const { return cc; } /** * @brief Communicate values from owner data points to all other data points. * * @brief source The data to send from. * @brief dest The data to send to. */ template void copyOwnerToAll (const T& source, T& dest) const { if (!OwnerToAllInterfaceBuilt) buildOwnerToAllInterface (); BC communicator; communicator.template build(OwnerToAllInterface); communicator.template forward >(source,dest); communicator.free(); } /** * @brief Communicate values from copy data points to all other data points. * * @brief source The data to send from. * @brief dest The data to send to. */ template void copyCopyToAll (const T& source, T& dest) const { if (!CopyToAllInterfaceBuilt) buildCopyToAllInterface (); BC communicator; communicator.template build(CopyToAllInterface); communicator.template forward >(source,dest); communicator.free(); } /** * @brief Communicate values from owner data points to all other data points and add them to those values. * * @brief source The data to send from. * @brief dest The data to add them communicated values to. */ template void addOwnerOverlapToAll (const T& source, T& dest) const { if (!OwnerOverlapToAllInterfaceBuilt) buildOwnerOverlapToAllInterface (); BC communicator; communicator.template build(OwnerOverlapToAllInterface); communicator.template forward >(source,dest); communicator.free(); } /** * @brief Communicate values from owner and copy data points to all other data points and add them to those values. * * @brief source The data to send from. * @brief dest The data to add them communicated values to. */ template void addOwnerCopyToAll (const T& source, T& dest) const { if (!OwnerCopyToAllInterfaceBuilt) buildOwnerCopyToAllInterface (); BC communicator; communicator.template build(OwnerCopyToAllInterface); communicator.template forward >(source,dest); communicator.free(); } /** * @brief Communicate values from owner and copy data points to owner and copy data points and add them to those values. * * @brief source The data to send from. * @brief dest The data to add the communicated values to. */ template void addOwnerCopyToOwnerCopy (const T& source, T& dest) const { if (!OwnerCopyToOwnerCopyInterfaceBuilt) buildOwnerCopyToOwnerCopyInterface (); BC communicator; communicator.template build(OwnerCopyToOwnerCopyInterface); communicator.template forward >(source,dest); communicator.free(); } /** * @brief Compute a global dot product of two vectors. * * @param x The first vector of the product. * @param y The second vector of the product. * @param result Reference to store the result in. */ template void dot (const T1& x, const T1& y, T2& result) const { // set up mask vector if (mask.size()!=static_cast::size_type>(x.size())) { mask.resize(x.size()); for (typename std::vector::size_type i=0; ilocal().attribute()!=OwnerOverlapCopyAttributeSet::owner) mask[i->local().local()] = 0; } result = T2(0.0); for (typename T1::size_type i=0; i typename FieldTraits::real_type norm (const T1& x) const { // set up mask vector if (mask.size()!=static_cast::size_type>(x.size())) { mask.resize(x.size()); for (typename std::vector::size_type i=0; ilocal().attribute()!=OwnerOverlapCopyAttributeSet::owner) mask[i->local().local()] = 0; } typename T1::field_type result = typename T1::field_type(0.0); for (typename T1::size_type i=0; i(sqrt(cc.sum(result))); } typedef Dune::EnumItem CopyFlags; /** @brief The type of the parallel index set. */ typedef Dune::ParallelIndexSet ParallelIndexSet; /** @brief The type of the remote indices. */ typedef Dune::RemoteIndices RemoteIndices; /** * @brief The type of the reverse lookup of indices. */ typedef Dune::GlobalLookupIndexSet GlobalLookupIndexSet; /** * @brief Get the underlying parallel index set. * @return The underlying parallel index set. */ const ParallelIndexSet& indexSet() const { return pis; } /** * @brief Get the underlying remote indices. * @return The underlying remote indices. */ const RemoteIndices& remoteIndices() const { return ri; } /** * @brief Get the underlying parallel index set. * @return The underlying parallel index set. */ ParallelIndexSet& indexSet() { return pis; } /** * @brief Get the underlying remote indices. * @return The underlying remote indices. */ RemoteIndices& remoteIndices() { return ri; } void buildGlobalLookup() { if(globalLookup_) { if(pis.seqNo()==oldseqNo) // Nothing changed! return; delete globalLookup_; } globalLookup_ = new GlobalLookupIndexSet(pis); oldseqNo = pis.seqNo(); } void buildGlobalLookup(std::size_t size) { if(globalLookup_) { if(pis.seqNo()==oldseqNo) // Nothing changed! return; delete globalLookup_; } globalLookup_ = new GlobalLookupIndexSet(pis, size); oldseqNo = pis.seqNo(); } void freeGlobalLookup() { delete globalLookup_; globalLookup_=0; } const GlobalLookupIndexSet& globalLookup() const { assert(globalLookup_ != 0); return *globalLookup_; } /** * @brief Set vector to zero at copy dofs * * @param x The vector to project. */ template void project (T1& x) const { for (typename PIS::const_iterator i=pis.begin(); i!=pis.end(); ++i) if (i->local().attribute()==OwnerOverlapCopyAttributeSet::copy) x[i->local().local()] = 0; } /** * @brief Construct the communication without any indices. * * The local index set and the remote indices have to be set up * later on. * @param comm_ The MPI Communicator to use, e. g. MPI_COMM_WORLD * @param cat_ The Solver category, default is overlapping * @param freecomm_ Whether to free the communicator comm_ in the destructor, default is false */ OwnerOverlapCopyCommunication (MPI_Comm comm_, SolverCategory::Category cat_ = SolverCategory::overlapping, bool freecomm_ = false) : comm(comm_), cc(comm_), pis(), ri(pis,pis,comm_), OwnerToAllInterfaceBuilt(false), OwnerOverlapToAllInterfaceBuilt(false), OwnerCopyToAllInterfaceBuilt(false), OwnerCopyToOwnerCopyInterfaceBuilt(false), CopyToAllInterfaceBuilt(false), globalLookup_(0), category(cat_), freecomm(freecomm_) {} /** * @brief Construct the communication without any indices using MPI_COMM_WORLD. * * The local index set and the remote indices have to be set up * later on. * @param cat_ The Solver category, default is overlapping is false */ OwnerOverlapCopyCommunication (SolverCategory::Category cat_ = SolverCategory::overlapping) : comm(MPI_COMM_WORLD), cc(MPI_COMM_WORLD), pis(), ri(pis,pis,MPI_COMM_WORLD), OwnerToAllInterfaceBuilt(false), OwnerOverlapToAllInterfaceBuilt(false), OwnerCopyToAllInterfaceBuilt(false), OwnerCopyToOwnerCopyInterfaceBuilt(false), CopyToAllInterfaceBuilt(false), globalLookup_(0), category(cat_), freecomm(false) {} /** * @brief Constructor * @param indexinfo The set of IndexTripels describing the local and remote indices. * @param comm_ The communicator to use in the communication. * @param cat_ The Solver category, default is overlapping * @param freecomm_ Whether to free the communicator comm_ in the destructor, default is false */ OwnerOverlapCopyCommunication (const IndexInfoFromGrid& indexinfo, MPI_Comm comm_, SolverCategory::Category cat_ = SolverCategory::overlapping, bool freecomm_ = false) : comm(comm_), cc(comm_), OwnerToAllInterfaceBuilt(false), OwnerOverlapToAllInterfaceBuilt(false), OwnerCopyToAllInterfaceBuilt(false), OwnerCopyToOwnerCopyInterfaceBuilt(false), CopyToAllInterfaceBuilt(false), globalLookup_(0), category(cat_), freecomm(freecomm_) { // set up an ISTL index set pis.beginResize(); for (localindex_iterator i=indexinfo.localIndices().begin(); i!=indexinfo.localIndices().end(); ++i) { if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::owner) pis.add(std::get<0>(*i),LI(std::get<1>(*i),OwnerOverlapCopyAttributeSet::owner,true)); if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::overlap) pis.add(std::get<0>(*i),LI(std::get<1>(*i),OwnerOverlapCopyAttributeSet::overlap,true)); if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::copy) pis.add(std::get<0>(*i),LI(std::get<1>(*i),OwnerOverlapCopyAttributeSet::copy,true)); // std::cout << cc.rank() << ": adding index " << std::get<0>(*i) << " " << std::get<1>(*i) << " " << std::get<2>(*i) << std::endl; } pis.endResize(); // build remote indices WITHOUT communication // std::cout << cc.rank() << ": build remote indices" << std::endl; ri.setIndexSets(pis,pis,cc); if (indexinfo.remoteIndices().size()>0) { remoteindex_iterator i=indexinfo.remoteIndices().begin(); int p = std::get<0>(*i); RILM modifier = ri.template getModifier(p); typename PIS::const_iterator pi=pis.begin(); for ( ; i!=indexinfo.remoteIndices().end(); ++i) { // handle processor change if (p!=std::get<0>(*i)) { p = std::get<0>(*i); modifier = ri.template getModifier(p); pi=pis.begin(); } // position to correct entry in parallel index set while (pi->global()!=std::get<1>(*i) && pi!=pis.end()) ++pi; if (pi==pis.end()) DUNE_THROW(ISTLError,"OwnerOverlapCopyCommunication: global index not in index set"); // insert entry // std::cout << cc.rank() << ": adding remote index " << std::get<0>(*i) << " " << std::get<1>(*i) << " " << std::get<2>(*i) << std::endl; if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::owner) modifier.insert(RX(OwnerOverlapCopyAttributeSet::owner,&(*pi))); if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::overlap) modifier.insert(RX(OwnerOverlapCopyAttributeSet::overlap,&(*pi))); if (std::get<2>(*i)==OwnerOverlapCopyAttributeSet::copy) modifier.insert(RX(OwnerOverlapCopyAttributeSet::copy,&(*pi))); } }else{ // Force remote indices to be synced! ri.template getModifier(0); } } // destructor: free memory in some objects ~OwnerOverlapCopyCommunication () { ri.free(); if (OwnerToAllInterfaceBuilt) OwnerToAllInterface.free(); if (OwnerOverlapToAllInterfaceBuilt) OwnerOverlapToAllInterface.free(); if (OwnerCopyToAllInterfaceBuilt) OwnerCopyToAllInterface.free(); if (OwnerCopyToOwnerCopyInterfaceBuilt) OwnerCopyToOwnerCopyInterface.free(); if (CopyToAllInterfaceBuilt) CopyToAllInterface.free(); if (globalLookup_) delete globalLookup_; if (freecomm==true) if(comm!=MPI_COMM_NULL) { #ifdef MPI_2 // If it is possible to query whether MPI_Finalize // was called, only free the communicator before // calling MPI_Finalize. int wasFinalized = 0; MPI_Finalized( &wasFinalized ); if(!wasFinalized) #endif MPI_Comm_free(&comm); } } private: OwnerOverlapCopyCommunication (const OwnerOverlapCopyCommunication&) {} MPI_Comm comm; CollectiveCommunication cc; PIS pis; RI ri; mutable IF OwnerToAllInterface; mutable bool OwnerToAllInterfaceBuilt; mutable IF OwnerOverlapToAllInterface; mutable bool OwnerOverlapToAllInterfaceBuilt; mutable IF OwnerCopyToAllInterface; mutable bool OwnerCopyToAllInterfaceBuilt; mutable IF OwnerCopyToOwnerCopyInterface; mutable bool OwnerCopyToOwnerCopyInterfaceBuilt; mutable IF CopyToAllInterface; mutable bool CopyToAllInterfaceBuilt; mutable std::vector mask; int oldseqNo; GlobalLookupIndexSet* globalLookup_; SolverCategory::Category category; bool freecomm; }; #endif /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/paamg/000077500000000000000000000000001313314427100164155ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/paamg/CMakeLists.txt000066400000000000000000000006771313314427100211670ustar00rootroot00000000000000add_subdirectory(test) #install headers install(FILES aggregates.hh amg.hh combinedfunctor.hh construction.hh dependency.hh fastamg.hh fastamgsmoother.hh galerkin.hh globalaggregates.hh graph.hh graphcreator.hh hierarchy.hh indicescoarsener.hh kamg.hh parameters.hh pinfo.hh properties.hh renumberer.hh smoother.hh transfer.hh twolevelmethod.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/istl/paamg) dune-istl-2.5.1/dune/istl/paamg/aggregates.hh000066400000000000000000002443071313314427100210610ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_AGGREGATES_HH #define DUNE_AMG_AGGREGATES_HH #include "parameters.hh" #include "graph.hh" #include "properties.hh" #include "combinedfunctor.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides classes for the Coloring process of AMG */ /** * @brief Base class of all aggregation criterions. */ template class AggregationCriterion : public T { public: /** * @brief The policy for calculating the dependency graph. */ typedef T DependencyPolicy; /** * @brief Constructor. * * The parameters will be initialized with default values suitable * for 2D isotropic problems. * * If that does not fit your needs either use setDefaultValuesIsotropic * setDefaultValuesAnisotropic or setup the values by hand */ AggregationCriterion() : T() {} AggregationCriterion(const Parameters& parms) : T(parms) {} /** * @brief Sets reasonable default values for an isotropic problem. * * Reasonable means that we should end up with cube aggregates of * diameter 2. * * @param dim The dimension of the problem. * @param diameter The preferred diameter for the aggregation. */ void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2) { this->setMaxDistance(diameter-1); std::size_t csize=1; for(; dim>0; dim--) { csize*=diameter; this->setMaxDistance(this->maxDistance()+diameter-1); } this->setMinAggregateSize(csize); this->setMaxAggregateSize(static_cast(csize*1.5)); } /** * @brief Sets reasonable default values for an aisotropic problem. * * Reasonable means that we should end up with cube aggregates with * sides of diameter 2 and sides in one dimension that are longer * (e.g. for 3D: 2x2x3). * * @param dim The dimension of the problem. * @param diameter The preferred diameter for the aggregation. */ void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2) { setDefaultValuesIsotropic(dim, diameter); this->setMaxDistance(this->maxDistance()+dim-1); } }; template std::ostream& operator<<(std::ostream& os, const AggregationCriterion& criterion) { os<<"{ maxdistance="< class SymmetricMatrixDependency : public Dune::Amg::Parameters { public: /** * @brief The matrix type we build the dependency of. */ typedef M Matrix; /** * @brief The norm to use for examining the matrix entries. */ typedef N Norm; /** * @brief Constant Row iterator of the matrix. */ typedef typename Matrix::row_type Row; /** * @brief Constant column iterator of the matrix. */ typedef typename Matrix::ConstColIterator ColIter; void init(const Matrix* matrix); void initRow(const Row& row, int index); void examine(const ColIter& col); template void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col); bool isIsolated(); SymmetricMatrixDependency(const Parameters& parms) : Parameters(parms) {} SymmetricMatrixDependency() : Parameters() {} protected: /** @brief The matrix we work on. */ const Matrix* matrix_; /** @brief The current max value.*/ typedef typename Matrix::field_type field_type; typedef typename FieldTraits::real_type real_type; real_type maxValue_; /** @brief The functor for calculating the norm. */ Norm norm_; /** @brief index of the currently evaluated row. */ int row_; /** @brief The norm of the current diagonal. */ real_type diagonal_; std::vector vals_; typename std::vector::iterator valIter_; }; template inline void SymmetricMatrixDependency::init(const Matrix* matrix) { matrix_ = matrix; } template inline void SymmetricMatrixDependency::initRow(const Row& row, int index) { vals_.assign(row.size(), 0.0); assert(vals_.size()==row.size()); valIter_=vals_.begin(); maxValue_ = std::min(- std::numeric_limits::max(), std::numeric_limits::min()); diagonal_=norm_(row[index]); row_ = index; } template inline void SymmetricMatrixDependency::examine(const ColIter& col) { // skip positive offdiagonals if norm preserves sign of them. real_type eij = norm_(*col); if(!N::is_sign_preserving || eij<0) // || eji<0) { *valIter_ = eij/diagonal_*eij/norm_(matrix_->operator[](col.index())[col.index()]); maxValue_ = std::max(maxValue_, *valIter_); }else *valIter_ =0; ++valIter_; } template template inline void SymmetricMatrixDependency::examine(G&, const typename G::EdgeIterator& edge, const ColIter&) { if(*valIter_ > alpha() * maxValue_) { edge.properties().setDepends(); edge.properties().setInfluences(); } ++valIter_; } template inline bool SymmetricMatrixDependency::isIsolated() { if(diagonal_==0) DUNE_THROW(Dune::ISTLError, "No diagonal entry for row "< class Dependency : public Parameters { public: /** * @brief The matrix type we build the dependency of. */ typedef M Matrix; /** * @brief The norm to use for examining the matrix entries. */ typedef N Norm; /** * @brief Constant Row iterator of the matrix. */ typedef typename Matrix::row_type Row; /** * @brief Constant column iterator of the matrix. */ typedef typename Matrix::ConstColIterator ColIter; void init(const Matrix* matrix); void initRow(const Row& row, int index); void examine(const ColIter& col); template void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col); bool isIsolated(); Dependency(const Parameters& parms) : Parameters(parms) {} Dependency() : Parameters() {} protected: /** @brief The matrix we work on. */ const Matrix* matrix_; /** @brief The current max value.*/ typedef typename Matrix::field_type field_type; typedef typename FieldTraits::real_type real_type; real_type maxValue_; /** @brief The functor for calculating the norm. */ Norm norm_; /** @brief index of the currently evaluated row. */ int row_; /** @brief The norm of the current diagonal. */ real_type diagonal_; }; /** * @brief Dependency policy for symmetric matrices. */ template class SymmetricDependency : public Parameters { public: /** * @brief The matrix type we build the dependency of. */ typedef M Matrix; /** * @brief The norm to use for examining the matrix entries. */ typedef N Norm; /** * @brief Constant Row iterator of the matrix. */ typedef typename Matrix::row_type Row; /** * @brief Constant column iterator of the matrix. */ typedef typename Matrix::ConstColIterator ColIter; void init(const Matrix* matrix); void initRow(const Row& row, int index); void examine(const ColIter& col); template void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col); bool isIsolated(); SymmetricDependency(const Parameters& parms) : Parameters(parms) {} SymmetricDependency() : Parameters() {} protected: /** @brief The matrix we work on. */ const Matrix* matrix_; /** @brief The current max value.*/ typedef typename Matrix::field_type field_type; typedef typename FieldTraits::real_type real_type; real_type maxValue_; /** @brief The functor for calculating the norm. */ Norm norm_; /** @brief index of the currently evaluated row. */ int row_; /** @brief The norm of the current diagonal. */ real_type diagonal_; }; /** * @brief Norm that uses only the [N][N] entry of the block to determine couplings. * */ template class Diagonal { public: enum { /* @brief We preserve the sign.*/ is_sign_preserving = true }; /** * @brief compute the norm of a matrix. * @param m The matrix ro compute the norm of. */ template typename FieldTraits::real_type operator()(const M& m) const { typedef typename M::field_type field_type; typedef typename FieldTraits::real_type real_type; static_assert( std::is_convertible::value, "use of diagonal norm in AMG not implemented for complex field_type"); return m[N][N]; // possible implementation for complex types: return signed_abs(m[N][N]); } private: //! return sign * abs_value; for real numbers this is just v template static T signed_abs(const T & v) { return v; } //! return sign * abs_value; for complex numbers this is csgn(v) * abs(v) template static T signed_abs(const std::complex & v) { // return sign * abs_value // in case of complex numbers this extends to using the csgn function to determine the sign return csgn(v) * std::abs(v); } //! sign function for complex numbers; for real numbers we assume imag(v) = 0 template static T csgn(const T & v) { return (T(0) < v) - (v < T(0)); } //! sign function for complex numbers template static T csgn(std::complex a) { return csgn(a.real())+(a.real() == 0.0)*csgn(a.imag()); } }; /** * @brief Norm that uses only the [0][0] entry of the block to determine couplings. * */ class FirstDiagonal : public Diagonal<0> {}; /** * @brief Functor using the row sum (infinity) norm to determine strong couplings. * * The is proposed by several people for elasticity problems. */ struct RowSum { enum { /* @brief We preserve the sign.*/ is_sign_preserving = false }; /** * @brief compute the norm of a matrix. * @param m The matrix row to compute the norm of. */ template typename FieldTraits::real_type operator()(const M& m) const { return m.infinity_norm(); } }; struct FrobeniusNorm { enum { /* @brief We preserve the sign.*/ is_sign_preserving = false }; /** * @brief compute the norm of a matrix. * @param m The matrix row to compute the norm of. */ template typename FieldTraits::real_type operator()(const M& m) const { return m.frobenius_norm(); } }; struct AlwaysOneNorm { enum { /* @brief We preserve the sign.*/ is_sign_preserving = false }; /** * @brief compute the norm of a matrix. * @param m The matrix row to compute the norm of. */ template typename FieldTraits::real_type operator()(const M& m) const { return 1; } }; /** * @brief Criterion taking advantage of symmetric matrices. * * The two template parameters are: *
*
M
The type of the matrix the amg coarsening works on, e. g. BCRSMatrix
*
Norm
The norm to use to determine the strong couplings between the nodes, e.g. FirstDiagonal or RowSum.
*
*/ template class SymmetricCriterion : public AggregationCriterion > { public: SymmetricCriterion(const Parameters& parms) : AggregationCriterion >(parms) {} SymmetricCriterion() {} }; /** * @brief Criterion suited for unsymmetric matrices. * * Nevertheless the sparsity pattern has to be symmetric. * * The two template parameters are: *
*
M
The type of the matrix the amg coarsening works on, e. g. BCRSMatrix
*
Norm
The norm to use to determine the strong couplings between the nodes, e.g. FirstDiagonal or RowSum.
*
*/ template class UnSymmetricCriterion : public AggregationCriterion > { public: UnSymmetricCriterion(const Parameters& parms) : AggregationCriterion >(parms) {} UnSymmetricCriterion() {} }; // forward declaration template class Aggregator; /** * @brief Class providing information about the mapping of * the vertices onto aggregates. * * It is assumed that the vertices are consecutively numbered * from 0 to the maximum vertex number. */ template class AggregatesMap { public: /** * @brief Identifier of not yet aggregated vertices. */ static const V UNAGGREGATED; /** * @brief Identifier of isolated vertices. */ static const V ISOLATED; /** * @brief The vertex descriptor type. */ typedef V VertexDescriptor; /** * @brief The aggregate descriptor type. */ typedef V AggregateDescriptor; /** * @brief The allocator we use for our lists and the * set. */ typedef PoolAllocator Allocator; /** * @brief The type of a single linked list of vertex * descriptors. */ typedef SLList VertexList; /** * @brief A Dummy visitor that does nothing for each visited edge. */ class DummyEdgeVisitor { public: template void operator()(const EdgeIterator& edge) const { DUNE_UNUSED_PARAMETER(edge); } }; /** * @brief Constructs without allocating memory. */ AggregatesMap(); /** * @brief Constructs with allocating memory. * @param noVertices The number of vertices we will hold information * for. */ AggregatesMap(std::size_t noVertices); /** * @brief Destructor. */ ~AggregatesMap(); /** * @brief Build the aggregates. * @param matrix The matrix describing the dependency. * @param graph The graph corresponding to the matrix. * @param criterion The aggregation criterion. * @param finestLevel Whether this the finest level. In that case rows representing * Dirichlet boundaries will be detected and ignored during aggregation. * @return A tuple of the total number of aggregates, the number of isolated aggregates, the * number of isolated aggregates, the number of aggregates consisting only of one vertex, and * the number of skipped aggregates built. */ template std::tuple buildAggregates(const M& matrix, G& graph, const C& criterion, bool finestLevel); /** * @brief Breadth first search within an aggregate * * The template parameters:
*
reset
If true the visited flags of the vertices * will be reset after * the search
*
G
The type of the graph we perform the search on.
*
F
The type of the visitor to operate on the vertices
*
* @param start The vertex where the search should start * from. This does not need to belong to the aggregate. * @param aggregate The aggregate id. * @param graph The matrix graph to perform the search on. * @param visitedMap A map to mark the already visited vertices * @param aggregateVisitor A functor that is called with * each G::ConstEdgeIterator with an edge pointing to the * aggregate. Use DummyVisitor if these are of no interest. */ template std::size_t breadthFirstSearch(const VertexDescriptor& start, const AggregateDescriptor& aggregate, const G& graph, F& aggregateVisitor, VM& visitedMap) const; /** * @brief Breadth first search within an aggregate * * The template parameters:
*
L
A container type providing push_back(Vertex), and * pop_front() in case remove is true
*
remove
If true the entries in the visited list * will be removed.
*
reset
If true the visited flag will be reset after * the search
* @param start The vertex where the search should start * from. This does not need to belong to the aggregate. * @param aggregate The aggregate id. * @param graph The matrix graph to perform the search on. * @param visited A list to store the visited vertices in. * @param aggregateVisitor A functor that is called with * each G::ConstEdgeIterator with an edge pointing to the * aggregate. Use DummyVisitor these are of no interest. * @param nonAggregateVisitor A functor that is called with * each G::ConstEdgeIterator with an edge pointing to another * aggregate. Use DummyVisitor these are of no interest. * @param visitedMap A map to mark the already visited vertices */ template std::size_t breadthFirstSearch(const VertexDescriptor& start, const AggregateDescriptor& aggregate, const G& graph, L& visited, F1& aggregateVisitor, F2& nonAggregateVisitor, VM& visitedMap) const; /** * @brief Allocate memory for holding the information. * @param noVertices The total number of vertices to be * mapped. */ void allocate(std::size_t noVertices); /** * @brief Get the number of vertices. */ std::size_t noVertices() const; /** * @brief Free the allocated memory. */ void free(); /** * @brief Get the aggregate a vertex belongs to. * @param v The vertex we want to know the aggregate of. * @return The aggregate the vertex is mapped to. */ AggregateDescriptor& operator[](const VertexDescriptor& v); /** * @brief Get the aggregate a vertex belongs to. * @param v The vertex we want to know the aggregate of. * @return The aggregate the vertex is mapped to. */ const AggregateDescriptor& operator[](const VertexDescriptor& v) const; typedef const AggregateDescriptor* const_iterator; const_iterator begin() const { return aggregates_; } const_iterator end() const { return aggregates_+noVertices(); } typedef AggregateDescriptor* iterator; iterator begin() { return aggregates_; } iterator end() { return aggregates_+noVertices(); } private: /** @brief Prevent copying. */ AggregatesMap(const AggregatesMap& map) { throw "Auch!"; } /** @brief Prevent assingment. */ AggregatesMap& operator=(const AggregatesMap& map) { throw "Auch!"; return this; } /** * @brief The aggregates the vertices belong to. */ AggregateDescriptor* aggregates_; /** * @brief The number of vertices in the map. */ std::size_t noVertices_; }; /** * @brief Build the dependency of the matrix graph. */ template void buildDependency(G& graph, const typename C::Matrix& matrix, C criterion, bool finestLevel); /** * @brief A class for temporarily storing the vertices of an * aggregate in. */ template class Aggregate { public: /*** * @brief The type of the matrix graph we work with. */ typedef G MatrixGraph; /** * @brief The vertex descriptor type. */ typedef typename MatrixGraph::VertexDescriptor Vertex; /** * @brief The allocator we use for our lists and the * set. */ typedef PoolAllocator Allocator; /** * @brief The type of a single linked list of vertex * descriptors. */ typedef S VertexSet; /** @brief Const iterator over a vertex list. */ typedef typename VertexSet::const_iterator const_iterator; /** * @brief Type of the mapping of aggregate members onto distance spheres. */ typedef std::size_t* SphereMap; /** * @brief Constructor. * @param graph The matrix graph we work on. * @param aggregates The mapping of vertices onto aggregates. * @param connectivity The set of vertices connected to the aggregate. * distance spheres. * @param front_ The vertices of the current aggregate front. */ Aggregate(MatrixGraph& graph, AggregatesMap& aggregates, VertexSet& connectivity, std::vector& front_); void invalidate() { --id_; } /** * @brief Reconstruct the aggregat from an seed node. * * Will determine all vertices of the same agggregate * and reference those. */ void reconstruct(const Vertex& vertex); /** * @brief Initialize the aggregate with one vertex. */ void seed(const Vertex& vertex); /** * @brief Add a vertex to the aggregate. */ void add(const Vertex& vertex); void add(std::vector& vertex); /** * @brief Clear the aggregate. */ void clear(); /** * @brief Get the size of the aggregate. */ typename VertexSet::size_type size(); /** * @brief Get tne number of connections to other aggregates. */ typename VertexSet::size_type connectSize(); /** * @brief Get the id identifying the aggregate. */ int id(); /** @brief get an iterator over the vertices of the aggregate. */ const_iterator begin() const; /** @brief get an iterator over the vertices of the aggregate. */ const_iterator end() const; private: /** * @brief The vertices of the aggregate. */ VertexSet vertices_; /** * @brief The number of the currently referenced * aggregate. */ int id_; /** * @brief The matrix graph the aggregates live on. */ MatrixGraph& graph_; /** * @brief The aggregate mapping we build. */ AggregatesMap& aggregates_; /** * @brief The connections to other aggregates. */ VertexSet& connected_; /** * @brief The vertices of the current aggregate front. */ std::vector& front_; }; /** * @brief Class for building the aggregates. */ template class Aggregator { public: /** * @brief The matrix graph type used. */ typedef G MatrixGraph; /** * @brief The vertex identifier */ typedef typename MatrixGraph::VertexDescriptor Vertex; /** @brief The type of the aggregate descriptor. */ typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor; /** * @brief Constructor. */ Aggregator(); /** * @brief Destructor. */ ~Aggregator(); /** * @brief Build the aggregates. * * The template parameter C Is the type of the coarsening Criterion to * use. * @param m The matrix to build the aggregates accordingly. * @param graph A (sub) graph of the matrix. * @param aggregates Aggregate map we will build. All entries should be initialized * to UNAGGREGATED! * @param c The coarsening criterion to use. * @param finestLevel Whether this the finest level. In that case rows representing * Dirichlet boundaries will be detected and ignored during aggregation. * @return A tuple of the total number of aggregates, the number of isolated aggregates, the * number of isolated aggregates, the number of aggregates consisting only of one vertex, and * the number of skipped aggregates built. */ template std::tuple build(const M& m, G& graph, AggregatesMap& aggregates, const C& c, bool finestLevel); private: /** * @brief The allocator we use for our lists and the * set. */ typedef PoolAllocator Allocator; /** * @brief The single linked list we use. */ typedef SLList VertexList; /** * @brief The set of vertices we use. */ typedef std::set,Allocator> VertexSet; /** * @brief The type of mapping of aggregate members to spheres. */ typedef std::size_t* SphereMap; /** * @brief The graph we aggregate for. */ MatrixGraph* graph_; /** * @brief The vertices of the current aggregate- */ Aggregate* aggregate_; /** * @brief The vertices of the current aggregate front. */ std::vector front_; /** * @brief The set of connected vertices. */ VertexSet connected_; /** * @brief Number of vertices mapped. */ int size_; /** * @brief Stack. */ class Stack { public: static const Vertex NullEntry; Stack(const MatrixGraph& graph, const Aggregator& aggregatesBuilder, const AggregatesMap& aggregates); ~Stack(); Vertex pop(); private: enum { N = 1300000 }; /** @brief The graph we work on. */ const MatrixGraph& graph_; /** @brief The aggregates builder. */ const Aggregator& aggregatesBuilder_; /** @brief The aggregates information. */ const AggregatesMap& aggregates_; /** @brief The current size. */ int size_; Vertex maxSize_; /** @brief The index of the top element. */ typename MatrixGraph::ConstVertexIterator begin_; typename MatrixGraph::ConstVertexIterator end_; /** @brief The values on the stack. */ Vertex* vals_; }; friend class Stack; /** * @brief Visits all neighbours of vertex belonging to a * specific aggregate. * * @param vertex The vertex whose neighbours we want to * visit. * @param aggregate The id of the aggregate. * @param visitor The visitor evaluated for each EdgeIterator * (by its method operator()(ConstEdgeIterator edge) */ template void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates, V& visitor) const; /** * @brief An Adaptor for vsitors that only * evaluates edges pointing to a specific aggregate. */ template class AggregateVisitor { public: /** * @brief The type of the adapted visitor */ typedef V Visitor; /** * @brief Constructor. * @param aggregates The aggregate numbers of the * vertices. * @param aggregate The id of the aggregate to visit. * @param visitor The visitor. */ AggregateVisitor(const AggregatesMap& aggregates, const AggregateDescriptor& aggregate, Visitor& visitor); /** * @brief Examine an edge. * * The edge will be examined by the adapted visitor if * it belongs to the right aggregate. */ void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); private: /** @brief Mapping of vertices to aggregates. */ const AggregatesMap& aggregates_; /** @brief The aggregate id we want to visit. */ AggregateDescriptor aggregate_; /** @brief The visitor to use on the aggregate. */ Visitor* visitor_; }; /** * @brief A simple counter functor. */ class Counter { public: /** @brief Constructor */ Counter(); /** @brief Access the current count. */ int value(); protected: /** @brief Increment counter */ void increment(); /** @brief Decrement counter */ void decrement(); private: int count_; }; /** * @brief Counts the number of edges to vertices belonging * to the aggregate front. */ class FrontNeighbourCounter : public Counter { public: /** * @brief Constructor. * @param front The vertices of the front. */ FrontNeighbourCounter(const MatrixGraph& front); void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); private: const MatrixGraph& graph_; }; /** * @brief Count the number of neighbours of a vertex that belong * to the aggregate front. */ int noFrontNeighbours(const Vertex& vertex) const; /** * @brief Counter of TwoWayConnections. */ class TwoWayCounter : public Counter { public: void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); }; /** * @brief Count the number of twoway connection from * a vertex to an aggregate. * * @param vertex The vertex whose connections are counted. * @param aggregate The id of the aggregate the connections * should point to. * @param aggregates The mapping of the vertices onto aggregates. * @return The number of one way connections from the vertex to * the aggregate. */ int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief Counter of OneWayConnections. */ class OneWayCounter : public Counter { public: void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); }; /** * @brief Count the number of oneway connection from * a vertex to an aggregate. * * @param vertex The vertex whose connections are counted. * @param aggregate The id of the aggregate the connections * should point to. * @param aggregates The mapping of the vertices onto aggregates. * @return The number of one way connections from the vertex to * the aggregate. */ int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief Connectivity counter * * Increments count if the neighbour is already known as * connected or is not yet aggregated. */ class ConnectivityCounter : public Counter { public: /** * @brief Constructor. * @param connected The set of connected aggregates. * @param aggregates Mapping of the vertices onto the aggregates. * @param aggregates The mapping of aggregates to vertices. */ ConnectivityCounter(const VertexSet& connected, const AggregatesMap& aggregates); void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); private: /** @brief The connected aggregates. */ const VertexSet& connected_; /** @brief The mapping of vertices to aggregates. */ const AggregatesMap& aggregates_; }; /** * @brief Get the connectivity of a vertex. * * For each unaggregated neighbour or neighbour of an aggregate * that is already known as connected the count is increased by * one. In all other cases by two. * * @param vertex The vertex whose connectivity we want. * @param aggregates The mapping of the vertices onto the aggregates. * @return The value of the connectivity. */ double connectivity(const Vertex& vertex, const AggregatesMap& aggregates) const; /** * @brief Test whether the vertex is connected to the aggregate. * @param vertex The vertex descriptor. * @param aggregate The aggregate descriptor. * @param aggregates The mapping of the vertices onto the aggregates. * @return True if there is a connection to the aggregate. */ bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief Test whether the vertex is connected to an aggregate of a list. * @param vertex The vertex descriptor. * @param aggregateList The list of aggregate descriptors. * @param aggregates The mapping of the vertices onto the aggregates. * @return True if there is a connection to the aggregate. */ bool connected(const Vertex& vertex, const SLList& aggregateList, const AggregatesMap& aggregates) const; /** * @brief Counts the edges depending on the dependency. * * If the inluence flag of the edge is set the counter is * increased and/or if the depends flag is set it is * incremented, too. */ class DependencyCounter : public Counter { public: /** * @brief Constructor. */ DependencyCounter(); void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); }; /** * @brief Adds the targets of each edge to * the list of front vertices. * * Vertices already marked as front nodes will not get added. */ class FrontMarker { public: /** * @brief Constructor. * * @param front The list to store the front vertices in. * @param graph The matrix graph we work on. */ FrontMarker(std::vector& front, MatrixGraph& graph); void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); private: /** @brief The list of front vertices. */ std::vector& front_; /** @brief The matrix graph we work on. */ MatrixGraph& graph_; }; /** * @brief Unmarks all front vertices. */ void unmarkFront(); /** * @brief counts the dependency between a vertex and unaggregated * neighbours. * * If the inluence flag of the edge is set the counter is * increased and/or if the depends flag is set it is * incremented, too. * * @param vertex The vertex whose neighbours we count. * @param aggregates The mapping of the vertices onto the aggregates. * @return The sum of the number of unaggregated * neighbours the vertex depends on and the number of unaggregated * neighbours the vertex influences. */ int unusedNeighbours(const Vertex& vertex, const AggregatesMap& aggregates) const; /** * @brief Count connections to neighbours. * * Counts the number of strong connections of a vertex to vertices * that are not yet aggregated * and the ones that belong to specific aggregate. * * @param vertex The vertex that we count the neighbours of. * @param aggregates The mapping of the vertices into aggregates. * @param aggregate The descriptor of the aggregate. * @return The pair of number of connections to unaggregate vertices * and number of connections to vertices of the specific aggregate. */ std::pair neighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief Counts the number of neighbours belonging to an aggregate. * * * If the inluence flag of the edge is set the counter is * increased and/or if the depends flag is set it is * incremented, too. * * @param vertex The vertex whose neighbours we count. * @param aggregate The aggregate id. * @param aggregates The mapping of the vertices onto the aggregates. * @return The sum of the number of * neighbours belonging to the aggregate * the vertex depends on and the number of * neighbours of the aggregate the vertex influences. */ int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief Checks wether a vertex is admisible to be added to an aggregate. * * @param vertex The vertex whose admissibility id to be checked. * @param aggregate The id of the aggregate. * @param aggregates The mapping of the vertices onto aggregates. */ bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const; /** * @brief The maximum distance of the vertex to any vertex in the * current aggregate. * * @return The maximum of all shortest paths from the vertex to any * vertex of the aggregate. */ std::size_t distance(const Vertex& vertex, const AggregatesMap& aggregates); /** * @brief Find a strongly connected cluster of a vertex. * * @param vertex The vertex whose neighbouring aggregate we search. * @param aggregates The mapping of the vertices onto aggregates. * @return A vertex of neighbouring aggregate the vertex is allowed to * be added to. */ Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap& aggregates) const; /** * @brief Find a nonisolated connected aggregate. * * @param vertex The vertex whose neighbouring aggregate we search. * @param aggregates The mapping of the vertices onto aggregates. * @param[out] list to store the vertices of neighbouring aggregates the vertex is allowed to * be added to. */ void nonisoNeighbourAggregate(const Vertex& vertex, const AggregatesMap& aggregates, SLList& neighbours) const; /** * @brief Grows the aggregate from a seed. * * @param seed The first vertex of the aggregate. * @param aggregates The mapping of he vertices onto the aggregates. * @param c The coarsen criterium. */ template void growAggregate(const Vertex& vertex, const AggregatesMap& aggregates, const C& c); template void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap& aggregates, const C& c); }; #ifndef DOXYGEN template inline void SymmetricDependency::init(const Matrix* matrix) { matrix_ = matrix; } template inline void SymmetricDependency::initRow(const Row& row, int index) { DUNE_UNUSED_PARAMETER(row); maxValue_ = std::min(- std::numeric_limits::max(), std::numeric_limits::min()); row_ = index; diagonal_ = norm_(matrix_->operator[](row_)[row_]); } template inline void SymmetricDependency::examine(const ColIter& col) { real_type eij = norm_(*col); typename Matrix::ConstColIterator opposite_entry = matrix_->operator[](col.index()).find(row_); if ( opposite_entry == matrix_->operator[](col.index()).end() ) { // Consider this a weak connection we disregard. return; } real_type eji = norm_(*opposite_entry); // skip positive offdiagonals if norm preserves sign of them. if(!N::is_sign_preserving || eij<0 || eji<0) maxValue_ = std::max(maxValue_, eij /diagonal_ * eji/ norm_(matrix_->operator[](col.index())[col.index()])); } template template inline void SymmetricDependency::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col) { real_type eij = norm_(*col); typename Matrix::ConstColIterator opposite_entry = matrix_->operator[](col.index()).find(row_); if ( opposite_entry == matrix_->operator[](col.index()).end() ) { // Consider this as a weak connection we disregard. return; } real_type eji = norm_(*opposite_entry); // skip positve offdiagonals if norm preserves sign of them. if(!N::is_sign_preserving || (eij<0 || eji<0)) if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) * eij/ diagonal_ > alpha() * maxValue_) { edge.properties().setDepends(); edge.properties().setInfluences(); typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source()); other.setInfluences(); other.setDepends(); } } template inline bool SymmetricDependency::isIsolated() { return maxValue_ < beta(); } template inline void Dependency::init(const Matrix* matrix) { matrix_ = matrix; } template inline void Dependency::initRow(const Row& row, int index) { DUNE_UNUSED_PARAMETER(row); maxValue_ = std::min(- std::numeric_limits::max(), std::numeric_limits::min()); row_ = index; diagonal_ = norm_(matrix_->operator[](row_)[row_]); } template inline void Dependency::examine(const ColIter& col) { maxValue_ = std::max(maxValue_, -norm_(*col)); } template template inline void Dependency::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col) { if(-norm_(*col) >= maxValue_ * alpha()) { edge.properties().setDepends(); typedef typename G::EdgeDescriptor ED; ED e= graph.findEdge(edge.target(), edge.source()); if(e!=std::numeric_limits::max()) { typename G::EdgeProperties& other = graph.getEdgeProperties(e); other.setInfluences(); } } } template inline bool Dependency::isIsolated() { return maxValue_ < beta() * diagonal_; } template Aggregate::Aggregate(MatrixGraph& graph, AggregatesMap& aggregates, VertexSet& connected, std::vector& front) : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates), connected_(connected), front_(front) {} template void Aggregate::reconstruct(const Vertex& vertex) { /* vertices_.push_back(vertex); typedef typename VertexList::const_iterator iterator; iterator begin = vertices_.begin(); iterator end = vertices_.end();*/ throw "Not yet implemented"; // while(begin!=end){ //for(); // } } template inline void Aggregate::seed(const Vertex& vertex) { dvverb<<"Connected cleared"<::UNAGGREGATED && !graph_.getVertexProperties(edge.target()).front()) { front_.push_back(edge.target()); graph_.getVertexProperties(edge.target()).setFront(); } dvverb <<" size="< inline void Aggregate::clear() { vertices_.clear(); connected_.clear(); id_=-1; } template inline typename Aggregate::VertexSet::size_type Aggregate::size() { return vertices_.size(); } template inline typename Aggregate::VertexSet::size_type Aggregate::connectSize() { return connected_.size(); } template inline int Aggregate::id() { return id_; } template inline typename Aggregate::const_iterator Aggregate::begin() const { return vertices_.begin(); } template inline typename Aggregate::const_iterator Aggregate::end() const { return vertices_.end(); } template const V AggregatesMap::UNAGGREGATED = std::numeric_limits::max(); template const V AggregatesMap::ISOLATED = std::numeric_limits::max()-1; template AggregatesMap::AggregatesMap() : aggregates_(0) {} template AggregatesMap::~AggregatesMap() { if(aggregates_!=0) delete[] aggregates_; } template inline AggregatesMap::AggregatesMap(std::size_t noVertices) { allocate(noVertices); } template inline std::size_t AggregatesMap::noVertices() const { return noVertices_; } template inline void AggregatesMap::allocate(std::size_t noVertices) { aggregates_ = new AggregateDescriptor[noVertices]; noVertices_ = noVertices; for(std::size_t i=0; i < noVertices; i++) aggregates_[i]=UNAGGREGATED; } template inline void AggregatesMap::free() { assert(aggregates_ != 0); delete[] aggregates_; aggregates_=0; } template inline typename AggregatesMap::AggregateDescriptor& AggregatesMap::operator[](const VertexDescriptor& v) { return aggregates_[v]; } template inline const typename AggregatesMap::AggregateDescriptor& AggregatesMap::operator[](const VertexDescriptor& v) const { return aggregates_[v]; } template template inline std::size_t AggregatesMap::breadthFirstSearch(const V& start, const AggregateDescriptor& aggregate, const G& graph, F& aggregateVisitor, VM& visitedMap) const { VertexList vlist; DummyEdgeVisitor dummy; return breadthFirstSearch(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap); } template template std::size_t AggregatesMap::breadthFirstSearch(const V& start, const AggregateDescriptor& aggregate, const G& graph, L& visited, F1& aggregateVisitor, F2& nonAggregateVisitor, VM& visitedMap) const { typedef typename L::const_iterator ListIterator; int visitedSpheres = 0; visited.push_back(start); put(visitedMap, start, true); ListIterator current = visited.begin(); ListIterator end = visited.end(); std::size_t i=0, size=visited.size(); // visit the neighbours of all vertices of the // current sphere. while(current != end) { for(; i Aggregator::Aggregator() : graph_(0), aggregate_(0), front_(), connected_(), size_(-1) {} template Aggregator::~Aggregator() { size_=-1; } template void buildDependency(G& graph, const typename C::Matrix& matrix, C criterion, bool firstlevel) { // assert(graph.isBuilt()); typedef typename C::Matrix Matrix; typedef typename G::VertexIterator VertexIterator; criterion.init(&matrix); for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex) { typedef typename Matrix::row_type Row; const Row& row = matrix[*vertex]; // Tell the criterion what row we will examine now // This might for example be used for calculating the // maximum offdiagonal value criterion.initRow(row, *vertex); // On a first path all columns are examined. After this // the calculator should know whether the vertex is isolated. typedef typename Matrix::ConstColIterator ColIterator; ColIterator end = row.end(); typename FieldTraits::real_type absoffdiag=0.; if(firstlevel) { for(ColIterator col = row.begin(); col != end; ++col) if(col.index()!=*vertex) { criterion.examine(col); absoffdiag=std::max(absoffdiag, col->frobenius_norm()); } if(absoffdiag==0) vertex.properties().setExcludedBorder(); } else for(ColIterator col = row.begin(); col != end; ++col) if(col.index()!=*vertex) criterion.examine(col); // reset the vertex properties //vertex.properties().reset(); // Check whether the vertex is isolated. if(criterion.isIsolated()) { //std::cout<<"ISOLATED: "<<*vertex< template inline Aggregator::AggregateVisitor::AggregateVisitor(const AggregatesMap& aggregates, const AggregateDescriptor& aggregate, V& visitor) : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor) {} template template inline void Aggregator::AggregateVisitor::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(aggregates_[edge.target()]==aggregate_) visitor_->operator()(edge); } template template inline void Aggregator::visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates, V& visitor) const { // Only evaluates for edge pointing to the aggregate AggregateVisitor v(aggregates, aggregate, visitor); visitNeighbours(*graph_, vertex, v); } template inline Aggregator::Counter::Counter() : count_(0) {} template inline void Aggregator::Counter::increment() { ++count_; } template inline void Aggregator::Counter::decrement() { --count_; } template inline int Aggregator::Counter::value() { return count_; } template inline void Aggregator::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(edge.properties().isTwoWay()) Counter::increment(); } template int Aggregator::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { TwoWayCounter counter; visitAggregateNeighbours(vertex, aggregate, aggregates, counter); return counter.value(); } template int Aggregator::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { OneWayCounter counter; visitAggregateNeighbours(vertex, aggregate, aggregates, counter); return counter.value(); } template inline void Aggregator::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(edge.properties().isOneWay()) Counter::increment(); } template inline Aggregator::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected, const AggregatesMap& aggregates) : Counter(), connected_(connected), aggregates_(aggregates) {} template inline void Aggregator::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap::UNAGGREGATED) // Would be a new connection Counter::increment(); else{ Counter::increment(); Counter::increment(); } } template inline double Aggregator::connectivity(const Vertex& vertex, const AggregatesMap& aggregates) const { ConnectivityCounter counter(connected_, aggregates); double noNeighbours=visitNeighbours(*graph_, vertex, counter); return (double)counter.value()/noNeighbours; } template inline Aggregator::DependencyCounter::DependencyCounter() : Counter() {} template inline void Aggregator::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(edge.properties().depends()) Counter::increment(); if(edge.properties().influences()) Counter::increment(); } template int Aggregator::unusedNeighbours(const Vertex& vertex, const AggregatesMap& aggregates) const { return aggregateNeighbours(vertex, AggregatesMap::UNAGGREGATED, aggregates); } template std::pair Aggregator::neighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { DependencyCounter unused, aggregated; typedef AggregateVisitor Counter; typedef std::tuple CounterTuple; CombinedFunctor visitors(CounterTuple(Counter(aggregates, AggregatesMap::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated))); visitNeighbours(*graph_, vertex, visitors); return std::make_pair(unused.value(), aggregated.value()); } template int Aggregator::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { DependencyCounter counter; visitAggregateNeighbours(vertex, aggregate, aggregates, counter); return counter.value(); } template std::size_t Aggregator::distance(const Vertex& vertex, const AggregatesMap& aggregates) { return 0; typename PropertyMapTypeSelector::Type visitedMap = get(VertexVisitedTag(), *graph_); VertexList vlist; typename AggregatesMap::DummyEdgeVisitor dummy; return aggregates.template breadthFirstSearch(vertex, aggregate_->id(), *graph_, vlist, dummy, dummy, visitedMap); } template inline Aggregator::FrontMarker::FrontMarker(std::vector& front, MatrixGraph& graph) : front_(front), graph_(graph) {} template inline void Aggregator::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { Vertex target = edge.target(); if(!graph_.getVertexProperties(target).front()) { front_.push_back(target); graph_.getVertexProperties(target).setFront(); } } template inline bool Aggregator::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { // Todo Dune::dvverb<<" Admissible not yet implemented!"<endEdges(vertex); for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) { // if(edge.properties().depends() && !edge.properties().influences() if(edge.properties().isStrong() && aggregates[edge.target()]==aggregate) { // Search for another link to the aggregate Iterator edge1 = edge; for(++edge1; edge1 != vend; ++edge1) { //if(edge1.properties().depends() && !edge1.properties().influences() if(edge1.properties().isStrong() && aggregates[edge.target()]==aggregate) { //Search for an edge connecting the two vertices that is //strong bool found=false; Iterator v2end = graph_->endEdges(edge.target()); for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2) { if(edge2.target()==edge1.target() && edge2.properties().isStrong()) { found =true; break; } } if(found) { return true; } } } } } // Situation 2: cluster node depends on front node and other cluster node /// Iterate over all all neighbours of front node vend = graph_->endEdges(vertex); for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge) { //if(!edge.properties().depends() && edge.properties().influences() if(edge.properties().isStrong() && aggregates[edge.target()]==aggregate) { // Search for a link from target that stays within the aggregate Iterator v1end = graph_->endEdges(edge.target()); for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1) { //if(edge1.properties().depends() && !edge1.properties().influences() if(edge1.properties().isStrong() && aggregates[edge1.target()]==aggregate) { bool found=false; // Check if front node is also connected to this one Iterator v2end = graph_->endEdges(vertex); for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2) { if(edge2.target()==edge1.target()) { if(edge2.properties().isStrong()) found=true; break; } } if(found) { return true; } } } } } return false; } template void Aggregator::unmarkFront() { typedef typename std::vector::const_iterator Iterator; for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex) graph_->getVertexProperties(*vertex).resetFront(); front_.clear(); } template inline void Aggregator::nonisoNeighbourAggregate(const Vertex& vertex, const AggregatesMap& aggregates, SLList& neighbours) const { typedef typename MatrixGraph::ConstEdgeIterator Iterator; Iterator end=graph_->beginEdges(vertex); neighbours.clear(); for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge) { if(aggregates[edge.target()]!=AggregatesMap::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated()) neighbours.push_back(aggregates[edge.target()]); } } template inline typename G::VertexDescriptor Aggregator::mergeNeighbour(const Vertex& vertex, const AggregatesMap& aggregates) const { typedef typename MatrixGraph::ConstEdgeIterator Iterator; Iterator end = graph_->endEdges(vertex); for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) { if(aggregates[edge.target()] != AggregatesMap::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()) { if( graph_->getVertexProperties(vertex).isolated() || ((edge.properties().depends() || edge.properties().influences()) && admissible(vertex, aggregates[edge.target()], aggregates))) return edge.target(); } } return AggregatesMap::UNAGGREGATED; } template Aggregator::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph) : Counter(), graph_(graph) {} template void Aggregator::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) { if(graph_.getVertexProperties(edge.target()).front()) Counter::increment(); } template int Aggregator::noFrontNeighbours(const Vertex& vertex) const { FrontNeighbourCounter counter(*graph_); visitNeighbours(*graph_, vertex, counter); return counter.value(); } template inline bool Aggregator::connected(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap& aggregates) const { typedef typename G::ConstEdgeIterator iterator; const iterator end = graph_->endEdges(vertex); for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) if(aggregates[edge.target()]==aggregate) return true; return false; } template inline bool Aggregator::connected(const Vertex& vertex, const SLList& aggregateList, const AggregatesMap& aggregates) const { typedef typename SLList::const_iterator Iter; for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i) if(connected(vertex, *i, aggregates)) return true; return false; } template template void Aggregator::growIsolatedAggregate(const Vertex& seed, const AggregatesMap& aggregates, const C& c) { SLList connectedAggregates; nonisoNeighbourAggregate(seed, aggregates,connectedAggregates); while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()) { double maxCon=-1; std::size_t maxFrontNeighbours=0; Vertex candidate=AggregatesMap::UNAGGREGATED; typedef typename std::vector::const_iterator Iterator; for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) { if(distance(*vertex, aggregates)>c.maxDistance()) continue; // distance of proposes aggregate too big if(connectedAggregates.size()>0) { // there is already a neighbour cluster // front node must be connected to same neighbour cluster if(!connected(*vertex, connectedAggregates, aggregates)) continue; } double con = connectivity(*vertex, aggregates); if(con == maxCon) { std::size_t frontNeighbours = noFrontNeighbours(*vertex); if(frontNeighbours >= maxFrontNeighbours) { maxFrontNeighbours = frontNeighbours; candidate = *vertex; } }else if(con > maxCon) { maxCon = con; maxFrontNeighbours = noFrontNeighbours(*vertex); candidate = *vertex; } } if(candidate==AggregatesMap::UNAGGREGATED) break; aggregate_->add(candidate); } } template template void Aggregator::growAggregate(const Vertex& seed, const AggregatesMap& aggregates, const C& c) { std::size_t distance_ =0; while(aggregate_->size() < c.minAggregateSize()&& distance_ candidates; candidates.reserve(30); typedef typename std::vector::const_iterator Iterator; for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) { // Only nonisolated nodes are considered if(graph_->getVertexProperties(*vertex).isolated()) continue; int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates); /* The case of two way connections. */ if( maxTwoCons == twoWayCons && twoWayCons > 0) { double con = connectivity(*vertex, aggregates); if(con == maxCon) { int neighbours = noFrontNeighbours(*vertex); if(neighbours > maxNeighbours) { maxNeighbours = neighbours; candidates.clear(); candidates.push_back(*vertex); }else{ candidates.push_back(*vertex); } }else if( con > maxCon) { maxCon = con; maxNeighbours = noFrontNeighbours(*vertex); candidates.clear(); candidates.push_back(*vertex); } }else if(twoWayCons > maxTwoCons) { maxTwoCons = twoWayCons; maxCon = connectivity(*vertex, aggregates); maxNeighbours = noFrontNeighbours(*vertex); candidates.clear(); candidates.push_back(*vertex); // two way connections precede maxOneCons = std::numeric_limits::max(); } if(twoWayCons > 0) { continue; // THis is a two-way node, skip tests for one way nodes } /* The one way case */ int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates); if(oneWayCons==0) continue; // No strong connections, skip the tests. if(!admissible(*vertex, aggregate_->id(), aggregates)) continue; if( maxOneCons == oneWayCons && oneWayCons > 0) { double con = connectivity(*vertex, aggregates); if(con == maxCon) { int neighbours = noFrontNeighbours(*vertex); if(neighbours > maxNeighbours) { maxNeighbours = neighbours; candidates.clear(); candidates.push_back(*vertex); }else{ if(neighbours==maxNeighbours) { candidates.push_back(*vertex); } } }else if( con > maxCon) { maxCon = con; maxNeighbours = noFrontNeighbours(*vertex); candidates.clear(); candidates.push_back(*vertex); } }else if(oneWayCons > maxOneCons) { maxOneCons = oneWayCons; maxCon = connectivity(*vertex, aggregates); maxNeighbours = noFrontNeighbours(*vertex); candidates.clear(); candidates.push_back(*vertex); } } if(!candidates.size()) break; // No more candidates found distance_=distance(seed, aggregates); candidates.resize(std::min(candidates.size(), c.maxAggregateSize()- aggregate_->size())); aggregate_->add(candidates); } } template template std::tuple AggregatesMap::buildAggregates(const M& matrix, G& graph, const C& criterion, bool finestLevel) { Aggregator aggregator; return aggregator.build(matrix, graph, *this, criterion, finestLevel); } template template std::tuple Aggregator::build(const M& m, G& graph, AggregatesMap& aggregates, const C& c, bool finestLevel) { // Stack for fast vertex access Stack stack_(graph, *this, aggregates); graph_ = &graph; aggregate_ = new Aggregate(graph, aggregates, connected_, front_); Timer watch; watch.reset(); buildDependency(graph, m, c, finestLevel); dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<::ISOLATED; ++skippedAggregates; continue; } if(graph.getVertexProperties(seed).isolated()) { if(c.skipIsolated()) { // isolated vertices are not aggregated but skipped on the coarser levels. aggregates[seed]=AggregatesMap::ISOLATED; ++skippedAggregates; // skip rest as no agglomeration is done. continue; }else{ aggregate_->seed(seed); growIsolatedAggregate(seed, aggregates, c); } }else{ aggregate_->seed(seed); growAggregate(seed, aggregates, c); } /* The rounding step. */ while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()) { std::vector candidates; candidates.reserve(30); typedef typename std::vector::const_iterator Iterator; for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex) { if(graph.getVertexProperties(*vertex).isolated()) continue; // No isolated nodes here if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || !admissible( *vertex, aggregate_->id(), aggregates) )) continue; std::pair neighbourPair=neighbours(*vertex, aggregate_->id(), aggregates); //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates)) // continue; if(neighbourPair.first >= neighbourPair.second) continue; if(distance(*vertex, aggregates) > c.maxDistance()) continue; // Distance too far candidates.push_back(*vertex); break; } if(!candidates.size()) break; // no more candidates found. candidates.resize(std::min(candidates.size(), c.maxAggregateSize()- aggregate_->size())); aggregate_->add(candidates); } // try to merge aggregates consisting of only one nonisolated vertex with other aggregates if(aggregate_->size()==1 && c.maxAggregateSize()>1) { if(!graph.getVertexProperties(seed).isolated()) { Vertex mergedNeighbour = mergeNeighbour(seed, aggregates); if(mergedNeighbour != AggregatesMap::UNAGGREGATED) { // assign vertex to the neighbouring cluster aggregates[seed] = aggregates[mergedNeighbour]; aggregate_->invalidate(); }else{ ++avg; minA=std::min(minA,static_cast(1)); maxA=std::max(maxA,static_cast(1)); ++oneAggregates; ++conAggregates; } }else{ ++avg; minA=std::min(minA,static_cast(1)); maxA=std::max(maxA,static_cast(1)); ++oneAggregates; ++isoAggregates; } ++avg; }else{ avg+=aggregate_->size(); minA=std::min(minA,aggregate_->size()); maxA=std::max(maxA,aggregate_->size()); if(graph.getVertexProperties(seed).isolated()) ++isoAggregates; else ++conAggregates; } } Dune::dinfo<<"connected aggregates: "<0) Dune::dinfo<<" one node aggregates: "< #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @defgroup ISTL_PAAMG Parallel Algebraic Multigrid * @ingroup ISTL_Prec * @brief A Parallel Algebraic Multigrid based on Agglomeration. */ /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief The AMG preconditioner. */ template class KAMG; template class KAmgTwoGrid; /** * @brief Parallel algebraic multigrid based on agglomeration. * * \tparam M The matrix type * \tparam X The vector type * \tparam A An allocator for X */ template > class AMG : public Preconditioner { template friend class KAMG; friend class KAmgTwoGrid; public: /** @brief The matrix operator type. */ typedef M Operator; /** * @brief The type of the parallel information. * Either OwnerOverlapCommunication or another type * describing the parallel data distribution and * providing communication methods. */ typedef PI ParallelInformation; /** @brief The operator hierarchy type. */ typedef MatrixHierarchy OperatorHierarchy; /** @brief The parallal data distribution hierarchy type. */ typedef typename OperatorHierarchy::ParallelInformationHierarchy ParallelInformationHierarchy; /** @brief The domain type. */ typedef X Domain; /** @brief The range type. */ typedef X Range; /** @brief the type of the coarse solver. */ typedef InverseOperator CoarseSolver; /** * @brief The type of the smoother. * * One of the preconditioners implementing the Preconditioner interface. * Note that the smoother has to fit the ParallelInformation.*/ typedef S Smoother; /** @brief The argument type for the construction of the smoother. */ typedef typename SmootherTraits::Arguments SmootherArgs; enum { /** @brief The solver category. */ category = S::category }; /** * @brief Construct a new amg with a specific coarse solver. * @param matrices The already set up matix hierarchy. * @param coarseSolver The set up solver to use on the coarse * grid, must match the coarse matrix in the matrix hierarchy. * @param smootherArgs The arguments needed for thesmoother to use * for pre and post smoothing. * @param parms The parameters for the AMG. */ AMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, const Parameters& parms); /** * @brief Construct an AMG with an inexact coarse solver based on the smoother. * * As coarse solver a preconditioned CG method with the smoother as preconditioner * will be used. The matrix hierarchy is built automatically. * @param fineOperator The operator on the fine level. * @param criterion The criterion describing the coarsening strategy. E. g. SymmetricCriterion * or UnsymmetricCriterion, and providing the parameters. * @param smootherArgs The arguments for constructing the smoothers. * @param pinfo The information about the parallel distribution of the data. */ template AMG(const Operator& fineOperator, const C& criterion, const SmootherArgs& smootherArgs=SmootherArgs(), const ParallelInformation& pinfo=ParallelInformation()); /** * @brief Copy constructor. */ AMG(const AMG& amg); ~AMG(); /** \copydoc Preconditioner::pre */ void pre(Domain& x, Range& b); /** \copydoc Preconditioner::apply */ void apply(Domain& v, const Range& d); /** \copydoc Preconditioner::post */ void post(Domain& x); /** * @brief Get the aggregate number of each unknown on the coarsest level. * @param cont The random access container to store the numbers in. */ template void getCoarsestAggregateNumbers(std::vector& cont); std::size_t levels(); std::size_t maxlevels(); /** * @brief Recalculate the matrix hierarchy. * * It is assumed that the coarsening for the changed fine level * matrix would yield the same aggregates. In this case it suffices * to recalculate all the Galerkin products for the matrices of the * coarser levels. */ void recalculateHierarchy() { matrices_->recalculateGalerkin(NegateSet()); } /** * @brief Check whether the coarse solver used is a direct solver. * @return True if the coarse level solver is a direct solver. */ bool usesDirectCoarseLevelSolver() const; private: /** * @brief Create matrix and smoother hierarchies. * @param criterion The coarsening criterion. * @param matrix The fine level matrix operator. * @param pinfo The fine level parallel information. */ template void createHierarchies(C& criterion, Operator& matrix, const PI& pinfo); /** * @brief A struct that holds the context of the current level. * * These are the iterators to the smoother, matrix, parallel information, * and so on needed for the computations on the current level. */ struct LevelContext { typedef Smoother SmootherType; /** * @brief The iterator over the smoothers. */ typename Hierarchy::Iterator smoother; /** * @brief The iterator over the matrices. */ typename OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix; /** * @brief The iterator over the parallel information. */ typename ParallelInformationHierarchy::Iterator pinfo; /** * @brief The iterator over the redistribution information. */ typename OperatorHierarchy::RedistributeInfoList::const_iterator redist; /** * @brief The iterator over the aggregates maps. */ typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates; /** * @brief The iterator over the left hand side. */ typename Hierarchy::Iterator lhs; /** * @brief The iterator over the updates. */ typename Hierarchy::Iterator update; /** * @brief The iterator over the right hand sided. */ typename Hierarchy::Iterator rhs; /** * @brief The level index. */ std::size_t level; }; /** * @brief Multigrid cycle on a level. * @param levelContext the iterators of the current level. */ void mgc(LevelContext& levelContext); void additiveMgc(); /** * @brief Move the iterators to the finer level * @param levelContext the iterators of the current level. * @param processedFineLevel Whether the process computed on * fine level or not. */ void moveToFineLevel(LevelContext& levelContext,bool processedFineLevel); /** * @brief Move the iterators to the coarser level. * @param levelContext the iterators of the current level */ bool moveToCoarseLevel(LevelContext& levelContext); /** * @brief Initialize iterators over levels with fine level. * @param levelContext the iterators of the current level */ void initIteratorsWithFineLevel(LevelContext& levelContext); /** @brief The matrix we solve. */ std::shared_ptr matrices_; /** @brief The arguments to construct the smoother */ SmootherArgs smootherArgs_; /** @brief The hierarchy of the smoothers. */ std::shared_ptr > smoothers_; /** @brief The solver of the coarsest level. */ std::shared_ptr solver_; /** @brief The right hand side of our problem. */ Hierarchy* rhs_; /** @brief The left approximate solution of our problem. */ Hierarchy* lhs_; /** @brief The total update for the outer solver. */ Hierarchy* update_; /** @brief The type of the chooser of the scalar product. */ typedef Dune::ScalarProductChooser ScalarProductChooser; /** @brief The type of the scalar product for the coarse solver. */ typedef typename ScalarProductChooser::ScalarProduct ScalarProduct; typedef std::shared_ptr ScalarProductPointer; /** @brief Scalar product on the coarse level. */ ScalarProductPointer scalarProduct_; /** @brief Gamma, 1 for V-cycle and 2 for W-cycle. */ std::size_t gamma_; /** @brief The number of pre and postsmoothing steps. */ std::size_t preSteps_; /** @brief The number of postsmoothing steps. */ std::size_t postSteps_; bool buildHierarchy_; bool additive; bool coarsesolverconverged; std::shared_ptr coarseSmoother_; /** @brief The verbosity level. */ std::size_t verbosity_; }; template inline AMG::AMG(const AMG& amg) : matrices_(amg.matrices_), smootherArgs_(amg.smootherArgs_), smoothers_(amg.smoothers_), solver_(amg.solver_), rhs_(), lhs_(), update_(), scalarProduct_(amg.scalarProduct_), gamma_(amg.gamma_), preSteps_(amg.preSteps_), postSteps_(amg.postSteps_), buildHierarchy_(amg.buildHierarchy_), additive(amg.additive), coarsesolverconverged(amg.coarsesolverconverged), coarseSmoother_(amg.coarseSmoother_), verbosity_(amg.verbosity_) { if(amg.rhs_) rhs_=new Hierarchy(*amg.rhs_); if(amg.lhs_) lhs_=new Hierarchy(*amg.lhs_); if(amg.update_) update_=new Hierarchy(*amg.update_); } template AMG::AMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, const Parameters& parms) : matrices_(&matrices), smootherArgs_(smootherArgs), smoothers_(new Hierarchy), solver_(&coarseSolver), rhs_(), lhs_(), update_(), scalarProduct_(0), gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()), postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false), additive(parms.getAdditive()), coarsesolverconverged(true), coarseSmoother_(), verbosity_(parms.debugLevel()) { assert(matrices_->isBuilt()); // build the necessary smoother hierarchies matrices_->coarsenSmoother(*smoothers_, smootherArgs_); } template template AMG::AMG(const Operator& matrix, const C& criterion, const SmootherArgs& smootherArgs, const PI& pinfo) : smootherArgs_(smootherArgs), smoothers_(new Hierarchy), solver_(), rhs_(), lhs_(), update_(), scalarProduct_(), gamma_(criterion.getGamma()), preSteps_(criterion.getNoPreSmoothSteps()), postSteps_(criterion.getNoPostSmoothSteps()), buildHierarchy_(true), additive(criterion.getAdditive()), coarsesolverconverged(true), coarseSmoother_(), verbosity_(criterion.debugLevel()) { static_assert(static_cast(M::category)==static_cast(S::category), "Matrix and Solver must match in terms of category!"); // TODO: reestablish compile time checks. //static_assert(static_cast(PI::category)==static_cast(S::category), // "Matrix and Solver must match in terms of category!"); createHierarchies(criterion, const_cast(matrix), pinfo); } template AMG::~AMG() { if(buildHierarchy_) { if(solver_) solver_.reset(); if(coarseSmoother_) coarseSmoother_.reset(); } if(lhs_) delete lhs_; lhs_=nullptr; if(update_) delete update_; update_=nullptr; if(rhs_) delete rhs_; rhs_=nullptr; } template struct DirectSolverSelector { typedef typename Matrix :: field_type field_type; enum SolverType { umfpack, superlu, none }; static constexpr SolverType solver = #if HAVE_SUITESPARSE_UMFPACK UMFPackMethodChooser< field_type > :: valid ? umfpack : none ; #elif HAVE_SUPERLU superlu ; #else none; #endif template struct Solver { typedef InverseOperator type; static type* create(const M& mat, bool verbose, bool reusevector ) { DUNE_THROW(NotImplemented,"DirectSolver not selected"); return nullptr; } static std::string name () { return "None"; } }; #if HAVE_SUITESPARSE_UMFPACK template struct Solver< M, umfpack > { typedef UMFPack< M > type; static type* create(const M& mat, bool verbose, bool reusevector ) { return new type(mat, verbose, reusevector ); } static std::string name () { return "UMFPack"; } }; #endif #if HAVE_SUPERLU template struct Solver< M, superlu > { typedef SuperLU< M > type; static type* create(const M& mat, bool verbose, bool reusevector ) { return new type(mat, verbose, reusevector ); } static std::string name () { return "SuperLU"; } }; #endif // define direct solver type to be used typedef Solver< Matrix, solver > SelectedSolver ; typedef typename SelectedSolver :: type DirectSolver; static constexpr bool isDirectSolver = solver != none; static std::string name() { return SelectedSolver :: name (); } static DirectSolver* create(const Matrix& mat, bool verbose, bool reusevector ) { return SelectedSolver :: create( mat, verbose, reusevector ); } }; template template void AMG::createHierarchies(C& criterion, Operator& matrix, const PI& pinfo) { Timer watch; matrices_.reset(new OperatorHierarchy(matrix, pinfo)); matrices_->template build >(criterion); // build the necessary smoother hierarchies matrices_->coarsenSmoother(*smoothers_, smootherArgs_); if(buildHierarchy_ && matrices_->levels()==matrices_->maxlevels()) { // We have the carsest level. Create the coarse Solver SmootherArgs sargs(smootherArgs_); sargs.iterations = 1; typename ConstructionTraits::Arguments cargs; cargs.setArgs(sargs); if(matrices_->redistributeInformation().back().isSetup()) { // Solve on the redistributed partitioning cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat()); cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed()); }else{ cargs.setMatrix(matrices_->matrices().coarsest()->getmat()); cargs.setComm(*matrices_->parallelInformation().coarsest()); } coarseSmoother_.reset(ConstructionTraits::construct(cargs)); scalarProduct_.reset(ScalarProductChooser::construct(cargs.getComm())); typedef DirectSolverSelector< typename M::matrix_type, X > SolverSelector; // Use superlu if we are purely sequential or with only one processor on the coarsest level. if( SolverSelector::isDirectSolver && (std::is_same::value // sequential mode || matrices_->parallelInformation().coarsest()->communicator().size()==1 //parallel mode and only one processor || (matrices_->parallelInformation().coarsest().isRedistributed() && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()>0) ) ) { // redistribute and 1 proc if(matrices_->parallelInformation().coarsest().isRedistributed()) { if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0) { // We are still participating on this level solver_.reset(SolverSelector::create(matrices_->matrices().coarsest().getRedistributed().getmat(), false, false)); } else solver_.reset(); } else { solver_.reset(SolverSelector::create(matrices_->matrices().coarsest()->getmat(), false, false)); } if(verbosity_>0 && matrices_->parallelInformation().coarsest()->communicator().rank()==0) std::cout<< "Using a direct coarse solver (" << SolverSelector::name() << ")" << std::endl; } else { if(matrices_->parallelInformation().coarsest().isRedistributed()) { if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0) // We are still participating on this level solver_.reset(new BiCGSTABSolver(const_cast(matrices_->matrices().coarsest().getRedistributed()), *scalarProduct_, *coarseSmoother_, 1E-2, 1000, 0)); else solver_.reset(); }else solver_.reset(new BiCGSTABSolver(const_cast(*matrices_->matrices().coarsest()), *scalarProduct_, *coarseSmoother_, 1E-2, 1000, 0)); } } if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0) std::cout<<"Building hierarchy of "<maxlevels()<<" levels " <<"(inclusive coarse solver) took "< void AMG::pre(Domain& x, Range& b) { // Detect Matrix rows where all offdiagonal entries are // zero and set x such that A_dd*x_d=b_d // Thus users can be more careless when setting up their linear // systems. typedef typename M::matrix_type Matrix; typedef typename Matrix::ConstRowIterator RowIter; typedef typename Matrix::ConstColIterator ColIter; typedef typename Matrix::block_type Block; Block zero; zero=typename Matrix::field_type(); const Matrix& mat=matrices_->matrices().finest()->getmat(); for(RowIter row=mat.begin(); row!=mat.end(); ++row) { bool isDirichlet = true; bool hasDiagonal = false; Block diagonal; for(ColIter col=row->begin(); col!=row->end(); ++col) { if(row.index()==col.index()) { diagonal = *col; hasDiagonal = false; }else{ if(*col!=zero) isDirichlet = false; } } if(isDirichlet && hasDiagonal) diagonal.solve(x[row.index()], b[row.index()]); } if(smoothers_->levels()>0) smoothers_->finest()->pre(x,b); else // No smoother to make x consistent! Do it by hand matrices_->parallelInformation().coarsest()->copyOwnerToAll(x,x); Range* copy = new Range(b); if(rhs_) delete rhs_; rhs_ = new Hierarchy(copy); Domain* dcopy = new Domain(x); if(lhs_) delete lhs_; lhs_ = new Hierarchy(dcopy); dcopy = new Domain(x); if(update_) delete update_; update_ = new Hierarchy(dcopy); matrices_->coarsenVector(*rhs_); matrices_->coarsenVector(*lhs_); matrices_->coarsenVector(*update_); // Preprocess all smoothers typedef typename Hierarchy::Iterator Iterator; typedef typename Hierarchy::Iterator RIterator; typedef typename Hierarchy::Iterator DIterator; Iterator coarsest = smoothers_->coarsest(); Iterator smoother = smoothers_->finest(); RIterator rhs = rhs_->finest(); DIterator lhs = lhs_->finest(); if(smoothers_->levels()>0) { assert(lhs_->levels()==rhs_->levels()); assert(smoothers_->levels()==lhs_->levels() || matrices_->levels()==matrices_->maxlevels()); assert(smoothers_->levels()+1==lhs_->levels() || matrices_->levels()maxlevels()); if(smoother!=coarsest) for(++smoother, ++lhs, ++rhs; smoother != coarsest; ++smoother, ++lhs, ++rhs) smoother->pre(*lhs,*rhs); smoother->pre(*lhs,*rhs); } // The preconditioner might change x and b. So we have to // copy the changes to the original vectors. x = *lhs_->finest(); b = *rhs_->finest(); } template std::size_t AMG::levels() { return matrices_->levels(); } template std::size_t AMG::maxlevels() { return matrices_->maxlevels(); } /** \copydoc Preconditioner::apply */ template void AMG::apply(Domain& v, const Range& d) { LevelContext levelContext; if(additive) { *(rhs_->finest())=d; additiveMgc(); v=*lhs_->finest(); }else{ // Init all iterators for the current level initIteratorsWithFineLevel(levelContext); *levelContext.lhs = v; *levelContext.rhs = d; *levelContext.update=0; levelContext.level=0; mgc(levelContext); if(postSteps_==0||matrices_->maxlevels()==1) levelContext.pinfo->copyOwnerToAll(*levelContext.update, *levelContext.update); v=*levelContext.update; } } template void AMG::initIteratorsWithFineLevel(LevelContext& levelContext) { levelContext.smoother = smoothers_->finest(); levelContext.matrix = matrices_->matrices().finest(); levelContext.pinfo = matrices_->parallelInformation().finest(); levelContext.redist = matrices_->redistributeInformation().begin(); levelContext.aggregates = matrices_->aggregatesMaps().begin(); levelContext.lhs = lhs_->finest(); levelContext.update = update_->finest(); levelContext.rhs = rhs_->finest(); } template bool AMG ::moveToCoarseLevel(LevelContext& levelContext) { bool processNextLevel=true; if(levelContext.redist->isSetup()) { levelContext.redist->redistribute(static_cast(*levelContext.rhs), levelContext.rhs.getRedistributed()); processNextLevel = levelContext.rhs.getRedistributed().size()>0; if(processNextLevel) { //restrict defect to coarse level right hand side. typename Hierarchy::Iterator fineRhs = levelContext.rhs++; ++levelContext.pinfo; Transfer ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs, static_cast(fineRhs.getRedistributed()), *levelContext.pinfo); } }else{ //restrict defect to coarse level right hand side. typename Hierarchy::Iterator fineRhs = levelContext.rhs++; ++levelContext.pinfo; Transfer ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs, static_cast(*fineRhs), *levelContext.pinfo); } if(processNextLevel) { // prepare coarse system ++levelContext.lhs; ++levelContext.update; ++levelContext.matrix; ++levelContext.level; ++levelContext.redist; if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()maxlevels()) { // next level is not the globally coarsest one ++levelContext.smoother; ++levelContext.aggregates; } // prepare the update on the next level *levelContext.update=0; } return processNextLevel; } template void AMG ::moveToFineLevel(LevelContext& levelContext, bool processNextLevel) { if(processNextLevel) { if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()maxlevels()) { // previous level is not the globally coarsest one --levelContext.smoother; --levelContext.aggregates; } --levelContext.redist; --levelContext.level; //prolongate and add the correction (update is in coarse left hand side) --levelContext.matrix; //typename Hierarchy::Iterator coarseLhs = lhs--; --levelContext.lhs; --levelContext.pinfo; } if(levelContext.redist->isSetup()) { // Need to redistribute during prolongateVector levelContext.lhs.getRedistributed()=0; Transfer ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs, levelContext.lhs.getRedistributed(), matrices_->getProlongationDampingFactor(), *levelContext.pinfo, *levelContext.redist); }else{ *levelContext.lhs=0; Transfer ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs, matrices_->getProlongationDampingFactor(), *levelContext.pinfo); } if(processNextLevel) { --levelContext.update; --levelContext.rhs; } *levelContext.update += *levelContext.lhs; } template bool AMG::usesDirectCoarseLevelSolver() const { return IsDirectSolver< CoarseSolver>::value; } template void AMG::mgc(LevelContext& levelContext){ if(levelContext.matrix == matrices_->matrices().coarsest() && levels()==maxlevels()) { // Solve directly InverseOperatorResult res; res.converged=true; // If we do not compute this flag will not get updated if(levelContext.redist->isSetup()) { levelContext.redist->redistribute(*levelContext.rhs, levelContext.rhs.getRedistributed()); if(levelContext.rhs.getRedistributed().size()>0) { // We are still participating in the computation levelContext.pinfo.getRedistributed().copyOwnerToAll(levelContext.rhs.getRedistributed(), levelContext.rhs.getRedistributed()); solver_->apply(levelContext.update.getRedistributed(), levelContext.rhs.getRedistributed(), res); } levelContext.redist->redistributeBackward(*levelContext.update, levelContext.update.getRedistributed()); levelContext.pinfo->copyOwnerToAll(*levelContext.update, *levelContext.update); }else{ levelContext.pinfo->copyOwnerToAll(*levelContext.rhs, *levelContext.rhs); solver_->apply(*levelContext.update, *levelContext.rhs, res); } if (!res.converged) coarsesolverconverged = false; }else{ // presmoothing presmooth(levelContext, preSteps_); #ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION bool processNextLevel = moveToCoarseLevel(levelContext); if(processNextLevel) { // next level for(std::size_t i=0; imatrices().finest()) { coarsesolverconverged = matrices_->parallelInformation().finest()->communicator().prod(coarsesolverconverged); if(!coarsesolverconverged) DUNE_THROW(MathError, "Coarse solver did not converge"); } // postsmoothing postsmooth(levelContext, postSteps_); } } template void AMG::additiveMgc(){ // restrict residual to all levels typename ParallelInformationHierarchy::Iterator pinfo=matrices_->parallelInformation().finest(); typename Hierarchy::Iterator rhs=rhs_->finest(); typename Hierarchy::Iterator lhs = lhs_->finest(); typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates=matrices_->aggregatesMaps().begin(); for(typename Hierarchy::Iterator fineRhs=rhs++; fineRhs != rhs_->coarsest(); fineRhs=rhs++, ++aggregates) { ++pinfo; Transfer ::restrictVector(*(*aggregates), *rhs, static_cast(*fineRhs), *pinfo); } // pinfo is invalid, set to coarsest level //pinfo = matrices_->parallelInformation().coarsest // calculate correction for all levels lhs = lhs_->finest(); typename Hierarchy::Iterator smoother = smoothers_->finest(); for(rhs=rhs_->finest(); rhs != rhs_->coarsest(); ++lhs, ++rhs, ++smoother) { // presmoothing *lhs=0; smoother->apply(*lhs, *rhs); } // Coarse level solve #ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION InverseOperatorResult res; pinfo->copyOwnerToAll(*rhs, *rhs); solver_->apply(*lhs, *rhs, res); if(!res.converged) DUNE_THROW(MathError, "Coarse solver did not converge"); #else *lhs=0; #endif // Prologate and add up corrections from all levels --pinfo; --aggregates; for(typename Hierarchy::Iterator coarseLhs = lhs--; coarseLhs != lhs_->finest(); coarseLhs = lhs--, --aggregates, --pinfo) { Transfer ::prolongateVector(*(*aggregates), *coarseLhs, *lhs, 1.0, *pinfo); } } /** \copydoc Preconditioner::post */ template void AMG::post(Domain& x) { DUNE_UNUSED_PARAMETER(x); // Postprocess all smoothers typedef typename Hierarchy::Iterator Iterator; typedef typename Hierarchy::Iterator DIterator; Iterator coarsest = smoothers_->coarsest(); Iterator smoother = smoothers_->finest(); DIterator lhs = lhs_->finest(); if(smoothers_->levels()>0) { if(smoother != coarsest || matrices_->levels()maxlevels()) smoother->post(*lhs); if(smoother!=coarsest) for(++smoother, ++lhs; smoother != coarsest; ++smoother, ++lhs) smoother->post(*lhs); smoother->post(*lhs); } //delete &(*lhs_->finest()); delete lhs_; lhs_=nullptr; //delete &(*update_->finest()); delete update_; update_=nullptr; //delete &(*rhs_->finest()); delete rhs_; rhs_=nullptr; } template template void AMG::getCoarsestAggregateNumbers(std::vector& cont) { matrices_->getCoarsestAggregatesOnFinest(cont); } } // end namespace Amg } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/combinedfunctor.hh000066400000000000000000000020561313314427100221220ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_COMBINEDFUNCTOR_HH #define DUNE_AMG_COMBINEDFUNCTOR_HH #include #include namespace Dune { namespace Amg { template struct ApplyHelper { template static void apply(TT tuple, const T& t) { std::get(tuple) (t); ApplyHelper::apply(tuple, t); } }; template<> struct ApplyHelper<0> { template static void apply(TT tuple, const T& t) { DUNE_UNUSED_PARAMETER(tuple); DUNE_UNUSED_PARAMETER(t); } }; template class CombinedFunctor : public T { public: CombinedFunctor(const T& tuple) : T(tuple) {} template void operator()(const T1& t) { ApplyHelper::value>::apply(*this, t); } }; } //namespace Amg } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/construction.hh000066400000000000000000000131171313314427100214730ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMGCONSTRUCTION_HH #define DUNE_AMGCONSTRUCTION_HH #include #include #include #include #include #include "pinfo.hh" namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Helper classes for the construction of classes without * empty constructor. */ /** * @brief Traits class for generically constructing non default * constructable types. * * Needed because BCRSMatrix and Vector do a deep copy which is * too expensive. */ template class ConstructionTraits { public: /** * @brief A type holding all the arguments needed to call the * constructor. */ typedef const void* Arguments; /** * @brief Construct an object with the specified arguments. * * In the default implementation the copy constructor is called. * @param args The arguments for the construction. */ static inline T* construct(Arguments& args) { return new T(); } /** * @brief Destroys an object. * @param t Pointer to the object to destroy. */ static inline void deconstruct(T* t) { delete t; } }; template class ConstructionTraits > { public: typedef const int Arguments; static inline BlockVector* construct(Arguments& n) { return new BlockVector(n); } static inline void deconstruct(BlockVector* t) { delete t; } }; template struct OverlappingSchwarzOperatorArgs { OverlappingSchwarzOperatorArgs(M& matrix, C& comm) : matrix_(&matrix), comm_(&comm) {} M* matrix_; C* comm_; }; template struct NonoverlappingOperatorArgs { NonoverlappingOperatorArgs(M& matrix, C& comm) : matrix_(&matrix), comm_(&comm) {} M* matrix_; C* comm_; }; #if HAVE_MPI struct OwnerOverlapCopyCommunicationArgs { OwnerOverlapCopyCommunicationArgs(MPI_Comm comm, SolverCategory::Category cat) : comm_(comm), cat_(cat) {} MPI_Comm comm_; SolverCategory::Category cat_; }; #endif struct SequentialCommunicationArgs { SequentialCommunicationArgs(CollectiveCommunication comm, int cat) : comm_(comm) { DUNE_UNUSED_PARAMETER(cat); } CollectiveCommunication comm_; }; } // end Amg namspace // forward declaration template class OverlappingSchwarzOperator; template class NonoverlappingSchwarzOperator; namespace Amg { template class ConstructionTraits > { public: typedef OverlappingSchwarzOperatorArgs Arguments; static inline OverlappingSchwarzOperator* construct(const Arguments& args) { return new OverlappingSchwarzOperator(*args.matrix_, *args.comm_); } static inline void deconstruct(OverlappingSchwarzOperator* t) { delete t; } }; template class ConstructionTraits > { public: typedef NonoverlappingOperatorArgs Arguments; static inline NonoverlappingSchwarzOperator* construct(const Arguments& args) { return new NonoverlappingSchwarzOperator(*args.matrix_, *args.comm_); } static inline void deconstruct(NonoverlappingSchwarzOperator* t) { delete t; } }; template struct MatrixAdapterArgs { MatrixAdapterArgs(M& matrix, const SequentialInformation&) : matrix_(&matrix) {} M* matrix_; }; template class ConstructionTraits > { public: typedef const MatrixAdapterArgs Arguments; static inline MatrixAdapter* construct(Arguments& args) { return new MatrixAdapter(*args.matrix_); } static inline void deconstruct(MatrixAdapter* m) { delete m; } }; template<> class ConstructionTraits { public: typedef const SequentialCommunicationArgs Arguments; static inline SequentialInformation* construct(Arguments& args) { return new SequentialInformation(args.comm_); } static inline void deconstruct(SequentialInformation* si) { delete si; } }; #if HAVE_MPI template class ConstructionTraits > { public: typedef const OwnerOverlapCopyCommunicationArgs Arguments; static inline OwnerOverlapCopyCommunication* construct(Arguments& args) { return new OwnerOverlapCopyCommunication(args.comm_, args.cat_); } static inline void deconstruct(OwnerOverlapCopyCommunication* com) { delete com; } }; #endif /** @} */ } // namespace Amg } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/dependency.hh000066400000000000000000000257171313314427100210700ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_DEPENDENCY_HH #define DUNE_AMG_DEPENDENCY_HH #include #include #include "graph.hh" #include "properties.hh" #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides classes for initializing the link attributes of a matrix graph. */ /** * @brief Class representing the properties of an ede in the matrix graph. * * During the coarsening process the matrix graph needs to hold different * properties of its edges. * This class ontains methods for getting and setting these edge attributes. */ class EdgeProperties { friend std::ostream& operator<<(std::ostream& os, const EdgeProperties& props); public: /** @brief Flags of the link.*/ enum {INFLUENCE, DEPEND, SIZE}; private: std::bitset flags_; public: /** @brief Constructor. */ EdgeProperties(); /** @brief Access the bits directly */ std::bitset::reference operator[](std::size_t v); /** @brief Access the bits directly */ bool operator[](std::size_t v) const; /** * @brief Checks wether the vertex the edge points to depends on * the vertex the edge starts. * @return True if it depends on the starting point. */ bool depends() const; /** * @brief Marks the edge as one of which the end point depends on * the starting point. */ void setDepends(); /** * @brief Resets the depends flag. */ void resetDepends(); /** * @brief Checks wether the start vertex is influenced by the end vertex. * @return True if it is influenced. */ bool influences() const; /** * @brief Marks the edge as one of which the start vertex by the end vertex. */ void setInfluences(); /** * @brief Resets the influence flag. */ void resetInfluences(); /** * @brief Checks wether the edge is one way. * I.e. either the influence or the depends flag but is set. */ bool isOneWay() const; /** * @brief Checks wether the edge is two way. * I.e. both the influence flag and the depends flag are that. */ bool isTwoWay() const; /** * @brief Checks wether the edge is strong. * I.e. the influence or depends flag is set. */ bool isStrong() const; /** * @brief Reset all flags. */ void reset(); /** * @brief Prints the attributes of the edge for debugging. */ void printFlags() const; }; /** * @brief Class representing a node in the matrix graph. * * Contains methods for getting and setting node attributes. */ class VertexProperties { friend std::ostream& operator<<(std::ostream& os, const VertexProperties& props); public: enum { ISOLATED, VISITED, FRONT, BORDER, SIZE }; private: /** @brief The attribute flags. */ std::bitset flags_; public: /** @brief Constructor. */ VertexProperties(); /** @brief Access the bits directly */ std::bitset::reference operator[](std::size_t v); /** @brief Access the bits directly */ bool operator[](std::size_t v) const; /** * @brief Marks that node as being isolated. * * A node is isolated if it ha not got any strong connections to other nodes * in the matrix graph. */ void setIsolated(); /** * @brief Checks wether the node is isolated. */ bool isolated() const; /** * @brief Resets the isolated flag. */ void resetIsolated(); /** * @brief Mark the node as already visited. */ void setVisited(); /** * @brief Checks wether the node is marked as visited. */ bool visited() const; /** * @brief Resets the visited flag. */ void resetVisited(); /** * @brief Marks the node as belonging to the current clusters front. */ void setFront(); /** * @brief Checks wether the node is marked as a front node. */ bool front() const; /** * @brief Resets the front node flag. */ void resetFront(); /** * @brief Marks the vertex as excluded from the aggregation. */ void setExcludedBorder(); /** * @brief Tests whether the vertex is excluded from the aggregation. * @return True if the vertex is excluded from the aggregation process. */ bool excludedBorder() const; /** * @brief Marks the vertex as included in the aggregation. */ void resetExcludedBorder(); /** * @brief Reset all flags. */ void reset(); }; template class PropertyGraphVertexPropertyMap : public RAPropertyMapHelper::reference, PropertyGraphVertexPropertyMap > { public: typedef ReadWritePropertyMapTag Category; enum { /** @brief the index to access in the bitset. */ index = i }; /** * @brief The type of the graph with internal properties. */ typedef G Graph; /** * @brief The type of the bitset. */ typedef std::bitset BitSet; /** * @brief The reference type. */ typedef typename BitSet::reference Reference; /** * @brief The value type. */ typedef bool ValueType; /** * @brief The vertex descriptor. */ typedef typename G::VertexDescriptor Vertex; /** * @brief Constructor. * @param g The graph whose properties we access. */ PropertyGraphVertexPropertyMap(G& g) : graph_(&g) {} /** * @brief Default constructor. */ PropertyGraphVertexPropertyMap() : graph_(0) {} /** * @brief Get the properties associated to a vertex. * @param vertex The vertex whose Properties we want. */ Reference operator[](const Vertex& vertex) const { return graph_->getVertexProperties(vertex)[index]; } private: Graph* graph_; }; } // end namespace Amg template struct PropertyMapTypeSelector > { typedef Amg::PropertyGraphVertexPropertyMap, Amg::VertexProperties::VISITED> Type; }; template typename PropertyMapTypeSelector >::Type get(const Amg::VertexVisitedTag& tag, Amg::PropertiesGraph& graph) { DUNE_UNUSED_PARAMETER(tag); return Amg::PropertyGraphVertexPropertyMap, Amg::VertexProperties::VISITED>(graph); } namespace Amg { inline std::ostream& operator<<(std::ostream& os, const EdgeProperties& props) { return os << props.flags_; } inline EdgeProperties::EdgeProperties() : flags_() {} inline std::bitset::reference EdgeProperties::operator[](std::size_t v) { return flags_[v]; } inline bool EdgeProperties::operator[](std::size_t i) const { return flags_[i]; } inline void EdgeProperties::reset() { flags_.reset(); } inline void EdgeProperties::setInfluences() { // Set the INFLUENCE bit //flags_ |= (1<((1<((1<((1<::reference VertexProperties::operator[](std::size_t v) { return flags_[v]; } inline bool VertexProperties::operator[](std::size_t v) const { return flags_[v]; } inline void VertexProperties::setIsolated() { flags_.set(ISOLATED); } inline bool VertexProperties::isolated() const { return flags_.test(ISOLATED); } inline void VertexProperties::resetIsolated() { flags_.reset(ISOLATED); } inline void VertexProperties::setVisited() { flags_.set(VISITED); } inline bool VertexProperties::visited() const { return flags_.test(VISITED); } inline void VertexProperties::resetVisited() { flags_.reset(VISITED); } inline void VertexProperties::setFront() { flags_.set(FRONT); } inline bool VertexProperties::front() const { return flags_.test(FRONT); } inline void VertexProperties::resetFront() { flags_.reset(FRONT); } inline void VertexProperties::setExcludedBorder() { flags_.set(BORDER); } inline bool VertexProperties::excludedBorder() const { return flags_.test(BORDER); } inline void VertexProperties::resetExcludedBorder() { flags_.reset(BORDER); } inline void VertexProperties::reset() { flags_.reset(); } /** @} */ } } #endif dune-istl-2.5.1/dune/istl/paamg/fastamg.hh000066400000000000000000000713561313314427100203740ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_FASTAMG_HH #define DUNE_ISTL_FASTAMG_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fastamgsmoother.hh" /** @file * @author Markus Blatt * @brief A fast AMG method, that currently only allows only Gauss-Seidel * smoothing and is currently purely sequential. It * combines one Gauss-Seidel presmoothing sweep with * the defect calculation to reduce memory transfers. */ namespace Dune { namespace Amg { /** * @defgroup ISTL_FSAMG Fast (sequential) Algebraic Multigrid * @ingroup ISTL_Prec * @brief An Algebraic Multigrid based on Agglomeration that saves memory bandwidth. */ /** * @addtogroup ISTL_FSAMG * * @{ */ /** * @brief A fast (sequential) algebraic multigrid based on agglomeration that saves memory bandwidth. * * It combines one Gauss-Seidel smoothing sweep with * the defect calculation to reduce memory transfers. * \tparam M The matrix type * \tparam X The vector type * \tparam PI Currently ignored. * \tparam A An allocator for X */ template > class FastAMG : public Preconditioner { public: /** @brief The matrix operator type. */ typedef M Operator; /** * @brief The type of the parallel information. * Either OwnerOverlapCommunication or another type * describing the parallel data distribution and * providing communication methods. */ typedef PI ParallelInformation; /** @brief The operator hierarchy type. */ typedef MatrixHierarchy OperatorHierarchy; /** @brief The parallal data distribution hierarchy type. */ typedef typename OperatorHierarchy::ParallelInformationHierarchy ParallelInformationHierarchy; /** @brief The domain type. */ typedef X Domain; /** @brief The range type. */ typedef X Range; /** @brief the type of the coarse solver. */ typedef InverseOperator CoarseSolver; enum { /** @brief The solver category. */ category = SolverCategory::sequential }; /** * @brief Construct a new amg with a specific coarse solver. * @param matrices The already set up matix hierarchy. * @param coarseSolver The set up solver to use on the coarse * grid, must match the coarse matrix in the matrix hierarchy. * @param parms The parameters for the AMG. */ FastAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const Parameters& parms, bool symmetric=true); /** * @brief Construct an AMG with an inexact coarse solver based on the smoother. * * As coarse solver a preconditioned CG method with the smoother as preconditioner * will be used. The matrix hierarchy is built automatically. * @param fineOperator The operator on the fine level. * @param criterion The criterion describing the coarsening strategy. E. g. SymmetricCriterion * or UnsymmetricCriterion, and providing the parameters. * @param parms The parameters for the AMG. * @param pinfo The information about the parallel distribution of the data. */ template FastAMG(const Operator& fineOperator, const C& criterion, const Parameters& parms=Parameters(), bool symmetric=true, const ParallelInformation& pinfo=ParallelInformation()); /** * @brief Copy constructor. */ FastAMG(const FastAMG& amg); ~FastAMG(); /** \copydoc Preconditioner::pre */ void pre(Domain& x, Range& b); /** \copydoc Preconditioner::apply */ void apply(Domain& v, const Range& d); /** \copydoc Preconditioner::post */ void post(Domain& x); /** * @brief Get the aggregate number of each unknown on the coarsest level. * @param cont The random access container to store the numbers in. */ template void getCoarsestAggregateNumbers(std::vector& cont); std::size_t levels(); std::size_t maxlevels(); /** * @brief Recalculate the matrix hierarchy. * * It is assumed that the coarsening for the changed fine level * matrix would yield the same aggregates. In this case it suffices * to recalculate all the Galerkin products for the matrices of the * coarser levels. */ void recalculateHierarchy() { matrices_->recalculateGalerkin(NegateSet()); } /** * @brief Check whether the coarse solver used is a direct solver. * @return True if the coarse level solver is a direct solver. */ bool usesDirectCoarseLevelSolver() const; private: /** * @brief Create matrix and smoother hierarchies. * @param criterion The coarsening criterion. * @param matrix The fine level matrix operator. * @param pinfo The fine level parallel information. */ template void createHierarchies(C& criterion, Operator& matrix, const PI& pinfo); /** * @brief A struct that holds the context of the current level. * * These are the iterators to the smoother, matrix, parallel information, * and so on needed for the computations on the current level. */ struct LevelContext { /** * @brief The iterator over the matrices. */ typename OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix; /** * @brief The iterator over the parallel information. */ typename ParallelInformationHierarchy::Iterator pinfo; /** * @brief The iterator over the redistribution information. */ typename OperatorHierarchy::RedistributeInfoList::const_iterator redist; /** * @brief The iterator over the aggregates maps. */ typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates; /** * @brief The iterator over the left hand side. */ typename Hierarchy::Iterator lhs; /** * @brief The iterator over the residuals. */ typename Hierarchy::Iterator residual; /** * @brief The iterator over the right hand sided. */ typename Hierarchy::Iterator rhs; /** * @brief The level index. */ std::size_t level; }; /** @brief Multigrid cycle on a level. */ void mgc(LevelContext& levelContext, Domain& x, const Range& b); /** * @brief Apply pre smoothing on the current level. * @param levelContext The context with the iterators for the level. * @param x The left hand side at the current level. * @param b The rightt hand side at the current level. */ void presmooth(LevelContext& levelContext, Domain& x, const Range& b); /** * @brief Apply post smoothing on the current level. * @param levelContext The context with the iterators for the level. * @param x The left hand side at the current level. * @param b The rightt hand side at the current level. */ void postsmooth(LevelContext& levelContext, Domain& x, const Range& b); /** * @brief Move the iterators to the finer level * @param levelContext The context with the iterators for the level. * @param processedFineLevel whether the process did compute on the finer level * @param fineX The vector to add the coarse level correction to. */ void moveToFineLevel(LevelContext& levelContext, bool processedFineLevel, Domain& fineX); /** * @brief Move the iterators to the coarser level. * @param levelContext The context with the iterators for the level. */ bool moveToCoarseLevel(LevelContext& levelContext); /** * @brief Initialize iterators over levels with fine level. * @param levelContext The context with the iterators for the level. */ void initIteratorsWithFineLevel(LevelContext& levelContext); /** @brief The matrix we solve. */ std::shared_ptr matrices_; /** @brief The solver of the coarsest level. */ std::shared_ptr solver_; /** @brief The right hand side of our problem. */ Hierarchy* rhs_; /** @brief The left approximate solution of our problem. */ Hierarchy* lhs_; /** @brief The current residual. */ Hierarchy* residual_; /** @brief The type of the chooser of the scalar product. */ typedef ScalarProductChooser ScalarProductChooserType; /** @brief The type of the scalar product for the coarse solver. */ typedef typename ScalarProductChooserType::ScalarProduct ScalarProduct; typedef std::shared_ptr ScalarProductPointer; /** @brief Scalar product on the coarse level. */ ScalarProductPointer scalarProduct_; /** @brief Gamma, 1 for V-cycle and 2 for W-cycle. */ std::size_t gamma_; /** @brief The number of pre and postsmoothing steps. */ std::size_t preSteps_; /** @brief The number of postsmoothing steps. */ std::size_t postSteps_; std::size_t level; bool buildHierarchy_; bool symmetric; bool coarsesolverconverged; typedef SeqSSOR Smoother; typedef std::shared_ptr SmootherPointer; SmootherPointer coarseSmoother_; /** @brief The verbosity level. */ std::size_t verbosity_; }; template FastAMG::FastAMG(const FastAMG& amg) : matrices_(amg.matrices_), solver_(amg.solver_), rhs_(), lhs_(), residual_(), scalarProduct_(amg.scalarProduct_), gamma_(amg.gamma_), preSteps_(amg.preSteps_), postSteps_(amg.postSteps_), symmetric(amg.symmetric), coarsesolverconverged(amg.coarsesolverconverged), coarseSmoother_(amg.coarseSmoother_), verbosity_(amg.verbosity_) { if(amg.rhs_) rhs_=new Hierarchy(*amg.rhs_); if(amg.lhs_) lhs_=new Hierarchy(*amg.lhs_); if(amg.residual_) residual_=new Hierarchy(*amg.residual_); } template FastAMG::FastAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const Parameters& parms, bool symmetric_) : matrices_(&matrices), solver_(&coarseSolver), rhs_(), lhs_(), residual_(), scalarProduct_(), gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()), postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false), symmetric(symmetric_), coarsesolverconverged(true), coarseSmoother_(), verbosity_(parms.debugLevel()) { if(preSteps_>1||postSteps_>1) { std::cerr<<"WARNING only one step of smoothing is supported!"<isBuilt()); static_assert(std::is_same::value, "Currently only sequential runs are supported"); } template template FastAMG::FastAMG(const Operator& matrix, const C& criterion, const Parameters& parms, bool symmetric_, const PI& pinfo) : solver_(), rhs_(), lhs_(), residual_(), scalarProduct_(), gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()), postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(true), symmetric(symmetric_), coarsesolverconverged(true), coarseSmoother_(), verbosity_(criterion.debugLevel()) { if(preSteps_>1||postSteps_>1) { std::cerr<<"WARNING only one step of smoothing is supported!"<::value, "Currently only sequential runs are supported"); // TODO: reestablish compile time checks. //static_assert(static_cast(PI::category)==static_cast(S::category), // "Matrix and Solver must match in terms of category!"); createHierarchies(criterion, const_cast(matrix), pinfo); } template FastAMG::~FastAMG() { if(buildHierarchy_) { if(solver_) solver_.reset(); if(coarseSmoother_) coarseSmoother_.reset(); } if(lhs_) delete lhs_; lhs_=nullptr; if(residual_) delete residual_; residual_=nullptr; if(rhs_) delete rhs_; rhs_=nullptr; } template template void FastAMG::createHierarchies(C& criterion, Operator& matrix, const PI& pinfo) { Timer watch; matrices_.reset(new OperatorHierarchy(matrix, pinfo)); matrices_->template build >(criterion); if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0) std::cout<<"Building Hierarchy of "<maxlevels()<<" levels took "<levels()==matrices_->maxlevels()) { // We have the carsest level. Create the coarse Solver typedef typename SmootherTraits::Arguments SmootherArgs; SmootherArgs sargs; sargs.iterations = 1; typename ConstructionTraits::Arguments cargs; cargs.setArgs(sargs); if(matrices_->redistributeInformation().back().isSetup()) { // Solve on the redistributed partitioning cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat()); cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed()); }else{ cargs.setMatrix(matrices_->matrices().coarsest()->getmat()); cargs.setComm(*matrices_->parallelInformation().coarsest()); } coarseSmoother_.reset(ConstructionTraits::construct(cargs)); scalarProduct_.reset(ScalarProductChooserType::construct(cargs.getComm())); #if HAVE_SUPERLU|| HAVE_SUITESPARSE_UMFPACK #if HAVE_SUITESPARSE_UMFPACK #define DIRECTSOLVER UMFPack #else #define DIRECTSOLVER SuperLU #endif // Use superlu if we are purely sequential or with only one processor on the coarsest level. if(std::is_same::value // sequential mode || matrices_->parallelInformation().coarsest()->communicator().size()==1 //parallel mode and only one processor || (matrices_->parallelInformation().coarsest().isRedistributed() && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()>0)) { // redistribute and 1 proc if(verbosity_>0 && matrices_->parallelInformation().coarsest()->communicator().rank()==0) std::cout<<"Using superlu"<parallelInformation().coarsest().isRedistributed()) { if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0) // We are still participating on this level solver_.reset(new DIRECTSOLVER(matrices_->matrices().coarsest().getRedistributed().getmat(), false, false)); else solver_.reset(); }else solver_.reset(new DIRECTSOLVER(matrices_->matrices().coarsest()->getmat(), false, false)); }else #undef DIRECTSOLVER #endif // HAVE_SUPERLU|| HAVE_SUITESPARSE_UMFPACK { if(matrices_->parallelInformation().coarsest().isRedistributed()) { if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0) // We are still participating on this level solver_.reset(new BiCGSTABSolver(const_cast(matrices_->matrices().coarsest().getRedistributed()), *scalarProduct_, *coarseSmoother_, 1E-2, 1000, 0)); else solver_.reset(); }else solver_.reset(new BiCGSTABSolver(const_cast(*matrices_->matrices().coarsest()), *scalarProduct_, *coarseSmoother_, 1E-2, 1000, 0)); } } if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0) std::cout<<"Building Hierarchy of "<maxlevels()<<" levels took "< void FastAMG::pre(Domain& x, Range& b) { Timer watch, watch1; // Detect Matrix rows where all offdiagonal entries are // zero and set x such that A_dd*x_d=b_d // Thus users can be more careless when setting up their linear // systems. typedef typename M::matrix_type Matrix; typedef typename Matrix::ConstRowIterator RowIter; typedef typename Matrix::ConstColIterator ColIter; typedef typename Matrix::block_type Block; Block zero; zero=typename Matrix::field_type(); const Matrix& mat=matrices_->matrices().finest()->getmat(); for(RowIter row=mat.begin(); row!=mat.end(); ++row) { bool isDirichlet = true; bool hasDiagonal = false; ColIter diag; for(ColIter col=row->begin(); col!=row->end(); ++col) { if(row.index()==col.index()) { diag = col; hasDiagonal = (*col != zero); }else{ if(*col!=zero) isDirichlet = false; } } if(isDirichlet && hasDiagonal) diag->solve(x[row.index()], b[row.index()]); } if (verbosity_>0) std::cout<<" Preprocessing Dirichlet took "<parallelInformation().coarsest()->copyOwnerToAll(x,x); Range* copy = new Range(b); if(rhs_) delete rhs_; rhs_ = new Hierarchy(copy); Domain* dcopy = new Domain(x); if(lhs_) delete lhs_; lhs_ = new Hierarchy(dcopy); dcopy = new Domain(x); residual_ = new Hierarchy(dcopy); matrices_->coarsenVector(*rhs_); matrices_->coarsenVector(*lhs_); matrices_->coarsenVector(*residual_); // The preconditioner might change x and b. So we have to // copy the changes to the original vectors. x = *lhs_->finest(); b = *rhs_->finest(); } template std::size_t FastAMG::levels() { return matrices_->levels(); } template std::size_t FastAMG::maxlevels() { return matrices_->maxlevels(); } /** \copydoc Preconditioner::apply */ template void FastAMG::apply(Domain& v, const Range& d) { LevelContext levelContext; // Init all iterators for the current level initIteratorsWithFineLevel(levelContext); assert(v.two_norm()==0); level=0; if(matrices_->maxlevels()==1){ // The coarse solver might modify the d! Range b(d); mgc(levelContext, v, b); }else mgc(levelContext, v, d); if(postSteps_==0||matrices_->maxlevels()==1) levelContext.pinfo->copyOwnerToAll(v, v); } template void FastAMG::initIteratorsWithFineLevel(LevelContext& levelContext) { levelContext.matrix = matrices_->matrices().finest(); levelContext.pinfo = matrices_->parallelInformation().finest(); levelContext.redist = matrices_->redistributeInformation().begin(); levelContext.aggregates = matrices_->aggregatesMaps().begin(); levelContext.lhs = lhs_->finest(); levelContext.residual = residual_->finest(); levelContext.rhs = rhs_->finest(); levelContext.level=0; } template bool FastAMG ::moveToCoarseLevel(LevelContext& levelContext) { bool processNextLevel=true; if(levelContext.redist->isSetup()) { throw "bla"; levelContext.redist->redistribute(static_cast(*levelContext.residual), levelContext.residual.getRedistributed()); processNextLevel = levelContext.residual.getRedistributed().size()>0; if(processNextLevel) { //restrict defect to coarse level right hand side. ++levelContext.pinfo; Transfer ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs, static_cast(levelContext.residual.getRedistributed()), *levelContext.pinfo); } }else{ //restrict defect to coarse level right hand side. ++levelContext.rhs; ++levelContext.pinfo; Transfer ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs, static_cast(*levelContext.residual), *levelContext.pinfo); } if(processNextLevel) { // prepare coarse system ++levelContext.residual; ++levelContext.lhs; ++levelContext.matrix; ++levelContext.level; ++levelContext.redist; if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()maxlevels()) { // next level is not the globally coarsest one ++levelContext.aggregates; } // prepare the lhs on the next level *levelContext.lhs=0; *levelContext.residual=0; } return processNextLevel; } template void FastAMG ::moveToFineLevel(LevelContext& levelContext, bool processNextLevel, Domain& x) { if(processNextLevel) { if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()maxlevels()) { // previous level is not the globally coarsest one --levelContext.aggregates; } --levelContext.redist; --levelContext.level; //prolongate and add the correction (update is in coarse left hand side) --levelContext.matrix; --levelContext.residual; } typename Hierarchy::Iterator coarseLhs = levelContext.lhs--; if(levelContext.redist->isSetup()) { // Need to redistribute during prolongate Transfer ::prolongateVector(*(*levelContext.aggregates), *coarseLhs, x, levelContext.lhs.getRedistributed(), matrices_->getProlongationDampingFactor(), *levelContext.pinfo, *levelContext.redist); }else{ Transfer ::prolongateVector(*(*levelContext.aggregates), *coarseLhs, x, matrices_->getProlongationDampingFactor(), *levelContext.pinfo); // printvector(std::cout, *lhs, "prolongated coarse grid correction", "lhs", 10, 10, 10); } if(processNextLevel) { --levelContext.rhs; } } template void FastAMG ::presmooth(LevelContext& levelContext, Domain& x, const Range& b) { GaussSeidelPresmoothDefect::apply(levelContext.matrix->getmat(), x, *levelContext.residual, b); } template void FastAMG ::postsmooth(LevelContext& levelContext, Domain& x, const Range& b) { GaussSeidelPostsmoothDefect ::apply(levelContext.matrix->getmat(), x, *levelContext.residual, b); } template bool FastAMG::usesDirectCoarseLevelSolver() const { return IsDirectSolver< CoarseSolver>::value; } template void FastAMG::mgc(LevelContext& levelContext, Domain& v, const Range& b){ if(levelContext.matrix == matrices_->matrices().coarsest() && levels()==maxlevels()) { // Solve directly InverseOperatorResult res; res.converged=true; // If we do not compute this flag will not get updated if(levelContext.redist->isSetup()) { levelContext.redist->redistribute(b, levelContext.rhs.getRedistributed()); if(levelContext.rhs.getRedistributed().size()>0) { // We are still participating in the computation levelContext.pinfo.getRedistributed().copyOwnerToAll(levelContext.rhs.getRedistributed(), levelContext.rhs.getRedistributed()); solver_->apply(levelContext.lhs.getRedistributed(), levelContext.rhs.getRedistributed(), res); } levelContext.redist->redistributeBackward(v, levelContext.lhs.getRedistributed()); levelContext.pinfo->copyOwnerToAll(v, v); }else{ levelContext.pinfo->copyOwnerToAll(b, b); solver_->apply(v, const_cast(b), res); } // printvector(std::cout, *lhs, "coarse level update", "u", 10, 10, 10); // printvector(std::cout, *rhs, "coarse level rhs", "rhs", 10, 10, 10); if (!res.converged) coarsesolverconverged = false; }else{ // presmoothing presmooth(levelContext, v, b); // printvector(std::cout, *lhs, "update", "u", 10, 10, 10); // printvector(std::cout, *residual, "post presmooth residual", "r", 10); #ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION bool processNextLevel = moveToCoarseLevel(levelContext); if(processNextLevel) { // next level for(std::size_t i=0; imatrices().finest()) { coarsesolverconverged = matrices_->parallelInformation().finest()->communicator().prod(coarsesolverconverged); if(!coarsesolverconverged) DUNE_THROW(MathError, "Coarse solver did not converge"); } // printvector(std::cout, *lhs, "update corrected", "u", 10, 10, 10); // postsmoothing postsmooth(levelContext, v, b); // printvector(std::cout, *lhs, "update postsmoothed", "u", 10, 10, 10); } } /** \copydoc Preconditioner::post */ template void FastAMG::post(Domain& x) { DUNE_UNUSED_PARAMETER(x); delete lhs_; lhs_=nullptr; delete rhs_; rhs_=nullptr; delete residual_; residual_=nullptr; } template template void FastAMG::getCoarsestAggregateNumbers(std::vector& cont) { matrices_->getCoarsestAggregatesOnFinest(cont); } } // end namespace Amg } // end namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/fastamgsmoother.hh000066400000000000000000000061101313314427100221370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_FASTAMGSMOOTHER_HH #define DUNE_ISTL_FASTAMGSMOOTHER_HH #include namespace Dune { namespace Amg { template struct GaussSeidelPresmoothDefect { template static void apply(const M& A, X& x, Y& d, const Y& b) { typedef typename M::ConstRowIterator RowIterator; typedef typename M::ConstColIterator ColIterator; typename Y::iterator dIter=d.begin(); typename Y::const_iterator bIter=b.begin(); typename X::iterator xIter=x.begin(); for(RowIterator row=A.begin(), end=A.end(); row != end; ++row, ++dIter, ++xIter, ++bIter) { ColIterator col=(*row).begin(); *dIter = *bIter; for (; col.index()solve(*xIter,*dIter); *dIter=0; //as r=v // Update residual for the symmetric case for(col=(*row).begin(); col.index()mmv(*xIter, d[col.index()]); //d_j-=A_ij x_i } } }; template struct GaussSeidelPostsmoothDefect { template static void apply(const M& A, X& x, Y& d, const Y& b) { typedef typename M::ConstRowIterator RowIterator; typedef typename M::ConstColIterator ColIterator; typedef typename Y::block_type YBlock; typename Y::iterator dIter=d.beforeEnd(); typename X::iterator xIter=x.beforeEnd(); typename Y::const_iterator bIter=b.beforeEnd(); for(RowIterator row=A.beforeEnd(), end=A.beforeBegin(); row != end; --row, --dIter, --xIter, --bIter) { ColIterator endCol=(*row).beforeBegin(); ColIterator col=(*row).beforeEnd(); *dIter = *bIter; for (; col.index()>row.index(); --col) (*col).mmv(x[col.index()],*dIter); // rhs -= sum_{i>j} a_ij * xnew_j assert(row.index()==col.index()); ColIterator diag=col; YBlock v=*dIter; // upper diagonal matrix for (--col; col!=endCol; --col) (*col).mmv(x[col.index()],v); // v -= sum_{jsolve(*xIter,v); *dIter-=v; // Update residual for the symmetric case // Skip residual computation as it is not needed. //for(col=(*row).begin();col.index() #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides a class for building the galerkin product * based on a aggregation scheme. */ template struct OverlapVertex { /** * @brief The aggregate descriptor. */ typedef T Aggregate; /** * @brief The vertex descriptor. */ typedef T Vertex; /** * @brief The aggregate the vertex belongs to. */ Aggregate* aggregate; /** * @brief The vertex descriptor. */ Vertex vertex; }; /** * @brief Functor for building the sparsity pattern of the matrix * using examineConnectivity. */ template class SparsityBuilder { public: /** * @brief Constructor. * @param matrix The matrix whose sparsity pattern we * should set up. */ SparsityBuilder(M& matrix); void insert(const typename M::size_type& index); void operator++(); std::size_t minRowSize(); std::size_t maxRowSize(); std::size_t sumRowSize(); std::size_t index() { return row_.index(); } private: /** @brief Create iterator for the current row. */ typename M::CreateIterator row_; /** @brief The minim row size. */ std::size_t minRowSize_; /** @brief The maximum row size. */ std::size_t maxRowSize_; std::size_t sumRowSize_; #ifdef DUNE_ISTL_WITH_CHECKING bool diagonalInserted; #endif }; class BaseGalerkinProduct { public: /** * @brief Calculate the galerkin product. * @param fine The fine matrix. * @param aggregates The aggregate mapping. * @param coarse The coarse Matrix. * @param pinfo Parallel information about the fine level. * @param copy The attribute set identifying the copy nodes of the graph. */ template void calculate(const M& fine, const AggregatesMap& aggregates, M& coarse, const I& pinfo, const O& copy); }; template class GalerkinProduct : public BaseGalerkinProduct { public: typedef T ParallelInformation; /** * @brief Calculates the coarse matrix via a Galerkin product. * @param fineGraph The graph of the fine matrix. * @param visitedMap Map for marking vertices as visited. * @param pinfo Parallel information about the fine level. * @param aggregates The mapping of the fine level unknowns onto aggregates. * @param size The number of columns and rows of the coarse matrix. * @param copy The attribute set identifying the copy nodes of the graph. */ template typename G::MutableMatrix* build(G& fineGraph, V& visitedMap, const ParallelInformation& pinfo, AggregatesMap& aggregates, const typename G::Matrix::size_type& size, const Set& copy); private: /** * @brief Builds the data structure needed for rebuilding the aggregates int the overlap. * @param graph The graph of the matrix. * @param pinfo The parallel information. * @param aggregates The mapping onto the aggregates. */ template const OverlapVertex* buildOverlapVertices(const G& graph, const I& pinfo, AggregatesMap& aggregates, const Set& overlap, std::size_t& overlapCount); template struct OVLess { bool operator()(const OverlapVertex& o1, const OverlapVertex& o2) { return *o1.aggregate < *o2.aggregate; } }; }; template<> class GalerkinProduct : public BaseGalerkinProduct { public: /** * @brief Calculates the coarse matrix via a Galerkin product. * @param fineGraph The graph of the fine matrix. * @param visitedMap Map for marking vertices as visited. * @param pinfo Parallel information about the fine level. * @param aggregates The mapping of the fine level unknowns onto aggregates. * @param size The number of columns and rows of the coarse matrix. * @param copy The attribute set identifying the copy nodes of the graph. */ template typename G::MutableMatrix* build(G& fineGraph, V& visitedMap, const SequentialInformation& pinfo, const AggregatesMap& aggregates, const typename G::Matrix::size_type& size, const Set& copy); }; struct BaseConnectivityConstructor { template static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap, const AggregatesMap& aggregates, const OverlapVertex*& seed, const OverlapVertex* overlapEnd); /** * @brief Construct the connectivity of an aggregate in the overlap. */ template static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap, const AggregatesMap& aggregates, const typename G::VertexDescriptor& seed); /** * @brief Visitor for identifying connected aggregates during a breadthFirstSearch. */ template class ConnectedBuilder { public: /** * @brief The type of the graph. */ typedef G Graph; /** * @brief The constant edge iterator. */ typedef typename Graph::ConstEdgeIterator ConstEdgeIterator; /** * @brief The type of the connected set. */ typedef S Set; /** * @brief The type of the map for marking vertices as visited. */ typedef V VisitedMap; /** * @brief The vertex descriptor of the graph. */ typedef typename Graph::VertexDescriptor Vertex; /** * @brief Constructor * @param aggregates The mapping of the vertices onto the aggregates. * @param graph The graph to work on. * @param visitedMap The map for marking vertices as visited * @param connected The set to added the connected aggregates to. */ ConnectedBuilder(const AggregatesMap& aggregates, Graph& graph, VisitedMap& visitedMap, Set& connected); /** * @brief Process an edge pointing to another aggregate. * @param edge The iterator positioned at the edge. */ void operator()(const ConstEdgeIterator& edge); private: /** * @brief The mapping of the vertices onto the aggregates. */ const AggregatesMap& aggregates_; Graph& graph_; /** * @brief The map for marking vertices as visited. */ VisitedMap& visitedMap_; /** * @brief The set to add the connected aggregates to. */ Set& connected_; }; }; template struct ConnectivityConstructor : public BaseConnectivityConstructor { typedef typename G::VertexDescriptor Vertex; template static void examine(G& graph, V& visitedMap, const T& pinfo, const AggregatesMap& aggregates, const O& overlap, const OverlapVertex* overlapVertices, const OverlapVertex* overlapEnd, R& row); }; template struct ConnectivityConstructor : public BaseConnectivityConstructor { typedef typename G::VertexDescriptor Vertex; template static void examine(G& graph, V& visitedMap, const SequentialInformation& pinfo, const AggregatesMap& aggregates, R& row); }; template struct DirichletBoundarySetter { template static void set(M& coarse, const T& pinfo, const O& copy); }; template<> struct DirichletBoundarySetter { template static void set(M& coarse, const SequentialInformation& pinfo, const O& copy); }; template void BaseConnectivityConstructor::constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap, const AggregatesMap& aggregates, const typename G::VertexDescriptor& seed) { assert(row.index()==aggregates[seed]); row.insert(aggregates[seed]); ConnectedBuilder conBuilder(aggregates, graph, visitedMap, row); typedef typename G::VertexDescriptor Vertex; typedef std::allocator Allocator; typedef SLList VertexList; typedef typename AggregatesMap::DummyEdgeVisitor DummyVisitor; VertexList vlist; DummyVisitor dummy; aggregates.template breadthFirstSearch(seed,aggregates[seed], graph, vlist, dummy, conBuilder, visitedMap); } template void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap, const AggregatesMap& aggregates, const OverlapVertex*& seed, const OverlapVertex* overlapEnd) { ConnectedBuilder conBuilder(aggregates, graph, visitedMap, row); const typename G::VertexDescriptor aggregate=*seed->aggregate; if (row.index()==*seed->aggregate) { while(seed != overlapEnd && aggregate == *seed->aggregate) { row.insert(*seed->aggregate); // Walk over all neighbours and add them to the connected array. visitNeighbours(graph, seed->vertex, conBuilder); // Mark vertex as visited put(visitedMap, seed->vertex, true); ++seed; } } } template BaseConnectivityConstructor::ConnectedBuilder::ConnectedBuilder(const AggregatesMap& aggregates, Graph& graph, VisitedMap& visitedMap, Set& connected) : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected) {} template void BaseConnectivityConstructor::ConnectedBuilder::operator()(const ConstEdgeIterator& edge) { typedef typename G::VertexDescriptor Vertex; const Vertex& vertex = aggregates_[edge.target()]; assert(vertex!= AggregatesMap::UNAGGREGATED); if(vertex!= AggregatesMap::ISOLATED) connected_.insert(vertex); } template template const OverlapVertex* GalerkinProduct::buildOverlapVertices(const G& graph, const I& pinfo, AggregatesMap& aggregates, const Set& overlap, std::size_t& overlapCount) { // count the overlap vertices. typedef typename G::ConstVertexIterator ConstIterator; typedef typename I::GlobalLookupIndexSet GlobalLookup; typedef typename GlobalLookup::IndexPair IndexPair; const ConstIterator end = graph.end(); overlapCount = 0; const GlobalLookup& lookup=pinfo.globalLookup(); for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) { const IndexPair* pair = lookup.pair(*vertex); if(pair!=0 && overlap.contains(pair->local().attribute())) ++overlapCount; } // Allocate space typedef typename G::VertexDescriptor Vertex; OverlapVertex* overlapVertices = new OverlapVertex[overlapCount=0 ? 1 : overlapCount]; if(overlapCount==0) return overlapVertices; // Initialize them overlapCount=0; for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex) { const IndexPair* pair = lookup.pair(*vertex); if(pair!=0 && overlap.contains(pair->local().attribute())) { overlapVertices[overlapCount].aggregate = &aggregates[pair->local()]; overlapVertices[overlapCount].vertex = pair->local(); ++overlapCount; } } dverb << overlapCount<<" overlap vertices"<()); // due to the sorting the isolated aggregates (to be skipped) are at the end. return overlapVertices; } template template void ConnectivityConstructor::examine(G& graph, V& visitedMap, const T& pinfo, const AggregatesMap& aggregates, const O& overlap, const OverlapVertex* overlapVertices, const OverlapVertex* overlapEnd, R& row) { typedef typename T::GlobalLookupIndexSet GlobalLookup; const GlobalLookup& lookup = pinfo.globalLookup(); typedef typename G::VertexIterator VertexIterator; VertexIterator vend=graph.end(); #ifdef DUNE_ISTL_WITH_CHECKING std::set examined; #endif // The aggregates owned by the process have lower local indices // then those not owned. We process them in the first pass. // They represent the rows 0, 1, ..., n of the coarse matrix for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) if(!get(visitedMap, *vertex)) { // In the first pass we only process owner nodes typedef typename GlobalLookup::IndexPair IndexPair; const IndexPair* pair = lookup.pair(*vertex); if(pair==0 || !overlap.contains(pair->local().attribute())) { #ifdef DUNE_ISTL_WITH_CHECKING assert(examined.find(aggregates[*vertex])==examined.end()); examined.insert(aggregates[*vertex]); #endif constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex); // only needed for ALU // (ghosts with same global id as owners on the same process) if (pinfo.getSolverCategory() == static_cast(SolverCategory::nonoverlapping)) { if(overlapVertices != overlapEnd) { if(*overlapVertices->aggregate!=AggregatesMap::ISOLATED) { constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd); } else{ ++overlapVertices; } } } ++row; } } dvverb<<"constructed "<aggregate!=AggregatesMap::ISOLATED) { #ifdef DUNE_ISTL_WITH_CHECKING typedef typename GlobalLookup::IndexPair IndexPair; const IndexPair* pair = lookup.pair(overlapVertices->vertex); assert(pair!=0 && overlap.contains(pair->local().attribute())); assert(examined.find(aggregates[overlapVertices->vertex])==examined.end()); examined.insert(aggregates[overlapVertices->vertex]); #endif constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd); ++row; }else{ ++overlapVertices; } } template template void ConnectivityConstructor::examine(G& graph, V& visitedMap, const SequentialInformation& pinfo, const AggregatesMap& aggregates, R& row) { DUNE_UNUSED_PARAMETER(pinfo); typedef typename G::VertexIterator VertexIterator; VertexIterator vend=graph.end(); for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) { if(!get(visitedMap, *vertex)) { constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex); ++row; } } } template SparsityBuilder::SparsityBuilder(M& matrix) : row_(matrix.createbegin()), minRowSize_(std::numeric_limits::max()), maxRowSize_(0), sumRowSize_(0) { #ifdef DUNE_ISTL_WITH_CHECKING diagonalInserted = false; #endif } template std::size_t SparsityBuilder::maxRowSize() { return maxRowSize_; } template std::size_t SparsityBuilder::minRowSize() { return minRowSize_; } template std::size_t SparsityBuilder::sumRowSize() { return sumRowSize_; } template void SparsityBuilder::operator++() { sumRowSize_ += row_.size(); minRowSize_=std::min(minRowSize_, row_.size()); maxRowSize_=std::max(maxRowSize_, row_.size()); ++row_; #ifdef DUNE_ISTL_WITH_CHECKING assert(diagonalInserted); diagonalInserted = false; #endif } template void SparsityBuilder::insert(const typename M::size_type& index) { row_.insert(index); #ifdef DUNE_ISTL_WITH_CHECKING diagonalInserted = diagonalInserted || row_.index()==index; #endif } template template typename G::MutableMatrix* GalerkinProduct::build(G& fineGraph, V& visitedMap, const ParallelInformation& pinfo, AggregatesMap& aggregates, const typename G::Matrix::size_type& size, const Set& overlap) { typedef OverlapVertex OverlapVertex; std::size_t count; const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph, pinfo, aggregates, overlap, count); typedef typename G::MutableMatrix M; M* coarseMatrix = new M(size, size, M::row_wise); // Reset the visited flags of all vertices. // As the isolated nodes will be skipped we simply mark them as visited typedef typename G::VertexIterator Vertex; Vertex vend = fineGraph.end(); for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex) { assert(aggregates[*vertex] != AggregatesMap::UNAGGREGATED); put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap::ISOLATED); } typedef typename G::MutableMatrix M; SparsityBuilder sparsityBuilder(*coarseMatrix); ConnectivityConstructor::examine(fineGraph, visitedMap, pinfo, aggregates, overlap, overlapVertices, overlapVertices+count, sparsityBuilder); dinfo<N()<<"x"<M()<<" row: min="< #include namespace Dune { namespace Amg { template struct GlobalAggregatesMap { public: typedef TI ParallelIndexSet; typedef typename ParallelIndexSet::GlobalIndex GlobalIndex; typedef typename ParallelIndexSet::GlobalIndex IndexedType; typedef typename ParallelIndexSet::LocalIndex LocalIndex; typedef T Vertex; GlobalAggregatesMap(AggregatesMap& aggregates, const GlobalLookupIndexSet& indexset) : aggregates_(aggregates), indexset_(indexset) {} inline const GlobalIndex& operator[](std::size_t index) const { const Vertex& aggregate = aggregates_[index]; if(aggregate >= AggregatesMap::ISOLATED) { assert(aggregate != AggregatesMap::UNAGGREGATED); return isolatedMarker; }else{ const Dune::IndexPair* pair = indexset_.pair(aggregate); assert(pair!=0); return pair->global(); } } inline GlobalIndex& get(std::size_t index) { const Vertex& aggregate = aggregates_[index]; assert(aggregate < AggregatesMap::ISOLATED); const Dune::IndexPair* pair = indexset_.pair(aggregate); assert(pair!=0); return const_cast(pair->global()); } class Proxy { public: Proxy(const GlobalLookupIndexSet& indexset, Vertex& aggregate) : indexset_(&indexset), aggregate_(&aggregate) {} Proxy& operator=(const GlobalIndex& global) { if(global==isolatedMarker) *aggregate_ = AggregatesMap::ISOLATED; else{ //assert(global < AggregatesMap::ISOLATED); *aggregate_ = indexset_->operator[](global).local(); } return *this; } private: const GlobalLookupIndexSet* indexset_; Vertex* aggregate_; }; inline Proxy operator[](std::size_t index) { return Proxy(indexset_, aggregates_[index]); } inline void put(const GlobalIndex& global, size_t i) { aggregates_[i]=indexset_[global].local(); } private: AggregatesMap& aggregates_; const GlobalLookupIndexSet& indexset_; static const GlobalIndex isolatedMarker; }; template const typename TI::GlobalIndex GlobalAggregatesMap::isolatedMarker = std::numeric_limits::max(); template struct AggregatesGatherScatter { typedef TI ParallelIndexSet; typedef typename ParallelIndexSet::GlobalIndex GlobalIndex; static const GlobalIndex& gather(const GlobalAggregatesMap& ga, size_t i) { return ga[i]; } static void scatter(GlobalAggregatesMap& ga, GlobalIndex global, size_t i) { ga[i]=global; } }; template struct AggregatesPublisher {}; #if HAVE_MPI #endif } // namespace Amg #if HAVE_MPI // forward declaration template class OwnerOverlapCopyCommunication; #endif namespace Amg { #if HAVE_MPI /** * @brief Utility class for publishing the aggregate number * of the DOFs in the overlap to other processors and convert * them to local indices. * @tparam T The type of the vertices * @tparam O The set of overlap flags. * @tparam T1 The type of the global indices. * @tparam T2 The type of the local indices. */ template struct AggregatesPublisher > { typedef T Vertex; typedef O OverlapFlags; typedef OwnerOverlapCopyCommunication ParallelInformation; typedef typename ParallelInformation::GlobalLookupIndexSet GlobalLookupIndexSet; typedef typename ParallelInformation::ParallelIndexSet IndexSet; static void publish(AggregatesMap& aggregates, ParallelInformation& pinfo, const GlobalLookupIndexSet& globalLookup) { typedef Dune::Amg::GlobalAggregatesMap GlobalMap; GlobalMap gmap(aggregates, globalLookup); pinfo.copyOwnerToAll(gmap,gmap); // communication only needed for ALU // (ghosts with same global id as owners on the same process) if (pinfo.getSolverCategory() == static_cast(SolverCategory::nonoverlapping)) pinfo.copyCopyToAll(gmap,gmap); typedef typename ParallelInformation::RemoteIndices::const_iterator Lists; Lists lists = pinfo.remoteIndices().find(pinfo.communicator().rank()); if(lists!=pinfo.remoteIndices().end()) { // For periodic boundary conditions we must renumber // the aggregates of vertices in the overlap whose owners are // on the same process Vertex maxAggregate =0; typedef typename AggregatesMap::const_iterator Iter; for(Iter i=aggregates.begin(), end=aggregates.end(); i!=end; ++i) maxAggregate = std::max(maxAggregate, *i); // Compute new mapping of aggregates in the overlap that we also own std::map newMapping; // insert all elements into map typedef typename ParallelInformation::RemoteIndices::RemoteIndexList ::const_iterator RIter; for(RIter ri=lists->second.first->begin(), rend = lists->second.first->end(); ri!=rend; ++ri) if(O::contains(ri->localIndexPair().local().attribute())) newMapping.insert(std::make_pair(aggregates[ri->localIndexPair().local()], maxAggregate)); // renumber typedef typename std::map::iterator MIter; for(MIter mi=newMapping.begin(), mend=newMapping.end(); mi != mend; ++mi) mi->second=++maxAggregate; for(RIter ri=lists->second.first->begin(), rend = lists->second.first->end(); ri!=rend; ++ri) if(O::contains(ri->localIndexPair().local().attribute())) aggregates[ri->localIndexPair().local()] = newMapping[aggregates[ri->localIndexPair().local()]]; } } }; #endif template struct AggregatesPublisher { typedef T Vertex; typedef SequentialInformation ParallelInformation; typedef typename ParallelInformation::GlobalLookupIndexSet GlobalLookupIndexSet; static void publish(AggregatesMap& aggregates, ParallelInformation& pinfo, const GlobalLookupIndexSet& globalLookup) { DUNE_UNUSED_PARAMETER(aggregates); DUNE_UNUSED_PARAMETER(pinfo); DUNE_UNUSED_PARAMETER(globalLookup); } }; } // end Amg namespace #if HAVE_MPI template struct CommPolicy > { typedef Amg::AggregatesMap Type; typedef typename Amg::GlobalAggregatesMap::IndexedType IndexedType; typedef SizeOne IndexedTypeFlag; static int getSize(const Type&, int) { return 1; } }; #endif } // end Dune namespace /* @} */ #endif dune-istl-2.5.1/dune/istl/paamg/graph.hh000066400000000000000000002224301313314427100200420ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_GRAPH_HH #define DUNE_AMG_GRAPH_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides classes for building the matrix graph. * * During the coarsening process in AMG the matrix graph together * with the dependencies, what connections in the graph are considered * strong or weak, what vertices are isolated, etc., have to build. * This information will be contained in the MatrixGraph class. */ /** * @brief The (undirected) graph of a matrix. * * The graph of a sparse matrix essentially describes the sparsity * pattern (nonzero entries) of a matrix. * It is assumed that the underlying sparsity pattern is symmetric, * i.e if entry a_ij is present in the storage scheme of the matrix * (i.e. nonzero) so is a_ji. * * The matrix entries can be accessed as weights of the vertices and * edges. */ template class MatrixGraph { public: /** * @brief The type of the matrix we are a graph for. */ typedef M Matrix; /** * @brief The mutable type of the matrix we are a graph for. */ typedef typename std::remove_const::type MutableMatrix; /** * @brief The type of the weights */ typedef typename M::block_type Weight; /** * @brief The vertex descriptor. * * Each descriptor describes exactly one vertex. */ typedef typename M::size_type VertexDescriptor; /** * @brief The edge descriptor. * * Each edge is identifies by exactly one descriptor. */ typedef std::ptrdiff_t EdgeDescriptor; enum { /* * @brief Whether Matrix is mutable. */ mutableMatrix = std::is_same::type>::value }; /** * @brief Iterator over all edges starting from a vertex. */ template class EdgeIteratorT { public: /** * @brief The mutable type of the container type. */ typedef typename std::remove_const::type MutableContainer; /** * @brief The constant type of the container type. */ typedef const typename std::remove_const::type ConstContainer; friend class EdgeIteratorT; friend class EdgeIteratorT; enum { /** @brief whether C is mutable. */ isMutable = std::is_same::value }; /** * @brief The column iterator of the matrix we use. */ typedef typename std::conditional::type ColIterator; /** * @brief The matrix block type we use as weights. */ typedef typename std::conditional::type Weight; /** * @brief Constructor. * @param source The source vertex of the edges. * @param block The matrix column block the iterator is initialized to, * @param end The end iterator of the matrix row. * @param edge The edge descriptor of the current edge. */ EdgeIteratorT(const VertexDescriptor& source, const ColIterator& block, const ColIterator& end, const EdgeDescriptor& edge); /** * @brief Constructor for the end iterator. * * Variables not needed by operator== or operator!= will not be initialized. * @param block The matrix column block the iterator is initialized to. */ EdgeIteratorT(const ColIterator& block); /** * @brief Copy Constructor. * @param other The iterator to copy. */ template EdgeIteratorT(const EdgeIteratorT& other); typedef typename std::conditional::type>::value && C::mutableMatrix, typename M::block_type, const typename M::block_type>::type WeightType; /** * @brief Access the edge weight */ WeightType& weight() const; /** @brief preincrement operator. */ EdgeIteratorT& operator++(); /** @brief Inequality operator. */ bool operator!=(const EdgeIteratorT::type>& other) const; /** @brief Inequality operator. */ bool operator!=(const EdgeIteratorT::type>& other) const; /** @brief Equality operator. */ bool operator==(const EdgeIteratorT::type>& other) const; /** @brief Equality operator. */ bool operator==(const EdgeIteratorT::type>& other) const; /** @brief The index of the target vertex of the current edge. */ VertexDescriptor target() const; /** @brief The index of the source vertex of the current edge. */ VertexDescriptor source() const; /** @brief Get the edge descriptor. */ const EdgeDescriptor& operator*() const; /** @brief Get the edge descriptor. */ const EdgeDescriptor* operator->() const; private: /** @brief Start vertex of the edges. */ VertexDescriptor source_; /** @brief The column iterator describing the current edge. */ ColIterator block_; /*** * @brief The column iterator positioned at the end of the row * of vertex source_ */ ColIterator blockEnd_; /** @brief The edge descriptor. */ EdgeDescriptor edge_; }; /** * @brief The vertex iterator type of the graph. */ template class VertexIteratorT { public: /** * @brief The mutable type of the container type. */ typedef typename std::remove_const::type MutableContainer; /** * @brief The constant type of the container type. */ typedef const typename std::remove_const::type ConstContainer; friend class VertexIteratorT; friend class VertexIteratorT; enum { /** @brief whether C is mutable. */ isMutable = std::is_same::value }; /** * @brief Constructor. * @param graph The graph we are a vertex iterator for. * @param current The current vertex to position on. */ explicit VertexIteratorT(C* graph, const VertexDescriptor& current); /** * @brief Constructor for the end iterator. * * only operator== or operator!= may be called safely on an * iterator constructed this way. * @param current The current vertex to position on. */ explicit VertexIteratorT(const VertexDescriptor& current); VertexIteratorT(const VertexIteratorT& other); /** * @brief Move to the next vertex. * @return This iterator positioned at the next vertex. */ VertexIteratorT& operator++(); /** @brief Inequality operator. */ bool operator!=(const VertexIteratorT& other) const; /** @brief Equality operator. */ bool operator==(const VertexIteratorT& other) const; /** @brief Inequality operator. */ bool operator!=(const VertexIteratorT& other) const; /** @brief Equality operator. */ bool operator==(const VertexIteratorT& other) const; typedef typename std::conditional::type>::value && C::mutableMatrix, typename M::block_type, const typename M::block_type>::type WeightType; /** @brief Access the weight of the vertex. */ WeightType& weight() const; /** * @brief Get the descriptor of the current vertex. * @return The index of the currently referenced vertex. */ const VertexDescriptor& operator*() const; /** * @brief Get an iterator over all edges starting at the * current vertex. * @return Iterator position on the first edge to another vertex. */ EdgeIteratorT begin() const; /** * @brief Get an iterator over all edges starting at the * current vertex. * @return Iterator position on the first edge to another vertex. */ EdgeIteratorT end() const; private: C* graph_; VertexDescriptor current_; }; /** * @brief The constant edge iterator type. */ typedef EdgeIteratorT > ConstEdgeIterator; /** * @brief The mutable edge iterator type. */ typedef EdgeIteratorT > EdgeIterator; /** * @brief The constant vertex iterator type. */ typedef VertexIteratorT > ConstVertexIterator; /** * @brief The mutable vertex iterator type. */ typedef VertexIteratorT > VertexIterator; /** * @brief Constructor. * @param matrix The matrix we are a graph for. */ MatrixGraph(Matrix& matrix); /** * @brief Destructor. */ ~MatrixGraph(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ VertexIterator begin(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ VertexIterator end(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ ConstVertexIterator begin() const; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ ConstVertexIterator end() const; /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned at the first edge starting * from vertex source. */ EdgeIterator beginEdges(const VertexDescriptor& source); /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned behind the last edge starting * from vertex source. */ EdgeIterator endEdges(const VertexDescriptor& source); /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned at the first edge starting * from vertex source. */ ConstEdgeIterator beginEdges(const VertexDescriptor& source) const; /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned behind the last edge starting * from vertex source. */ ConstEdgeIterator endEdges(const VertexDescriptor& source) const; /** * @brief Get the underlying matrix. * @return The matrix of the graph. */ Matrix& matrix(); /** * @brief Get the underlying matrix. * @return The matrix of the graph. */ const Matrix& matrix() const; /** * @brief Get the number of vertices in the graph. */ std::size_t noVertices() const; /** * @brief Get the maximal vertex descriptor. * * @return The minimum value v such that for * all vertices w in the graph w<v holds. */ VertexDescriptor maxVertex() const; /** * @brief Get the number of edges in the graph. */ std::size_t noEdges() const; /** * @brief Find the descriptor of an edge. * @param source The source vertex of the edge we search for. * @param target The target vertex of the edge we search for. * @return The edge we found or numeric_limits::max() if it does not exist. */ EdgeDescriptor findEdge(const VertexDescriptor& source, const VertexDescriptor& target) const; private: /** @brief The matrix we are the graph for. */ Matrix& matrix_; /** @brief The edge descriptor of the first edge of each row. */ EdgeDescriptor* start_; /** Prevent copying. */ MatrixGraph(const MatrixGraph&); }; /** * @brief A subgraph of a graph. * * This is a (cached) view of a graph where certain * vertices and edges pointing to and leading from them * are skipped. * * The vertex descriptors are not changed. */ template class SubGraph { public: /** * @brief The type of the graph we are a sub graph for. */ typedef G Graph; /** * @brief Random access container providing information about * which vertices are excluded. */ typedef T Excluded; /** * @brief The vertex descriptor. */ typedef typename Graph::VertexDescriptor VertexDescriptor; typedef VertexDescriptor* EdgeDescriptor; /** * @brief An index map for mapping the edges to indices. * * This should be used for attaching properties to a SubGraph * using VertexPropertiesGraph od PropertiesGraph. */ class EdgeIndexMap { public: typedef ReadablePropertyMapTag Category; EdgeIndexMap(const EdgeDescriptor& firstEdge) : firstEdge_(firstEdge) {} /** @brief Protect copy construction. */ EdgeIndexMap(const EdgeIndexMap& emap) : firstEdge_(emap.firstEdge_) {} std::size_t operator[](const EdgeDescriptor& edge) const { return edge-firstEdge_; } private: /** @brief The first edge of the graph. */ EdgeDescriptor firstEdge_; /** @brief Protect default construction. */ EdgeIndexMap() {} }; /** * @brief Get an edge index map for the graph. * @return An edge index map for the graph. */ EdgeIndexMap getEdgeIndexMap(); /** * @brief The edge iterator of the graph. */ class EdgeIterator : public RandomAccessIteratorFacade { public: /** * @brief Constructor. * @param source The source vertex of the edge. * @param edge Pointer to the edge the iterator should point to. */ explicit EdgeIterator(const VertexDescriptor& source, const EdgeDescriptor& edge); /** * @brief Constructor for the end iterator. * * Only operator== or operator!= can be called safely on an iterator constructed * this way! * @param edge Pointer to the end of the graph's edge array. */ explicit EdgeIterator(const EdgeDescriptor& edge); /** @brief Equality operator. */ bool equals(const EdgeIterator& other) const; /** @brief Preincrement operator. */ EdgeIterator& increment(); /** @brief Preincrement operator. */ EdgeIterator& decrement(); EdgeIterator& advance(std::ptrdiff_t n); /** @brief The descriptor of the current edge. */ const EdgeDescriptor& dereference() const; /** @brief The index of the target vertex of the current edge. */ const VertexDescriptor& target() const; /** @brief The index of the source vertex of the current edge. */ const VertexDescriptor& source() const; std::ptrdiff_t distanceTo(const EdgeIterator& other) const; private: /** @brief The source vertex of the edge. */ VertexDescriptor source_; /** * @brief The offset of the current edge to the first * one starting at the vertex source_. */ EdgeDescriptor edge_; }; /** * @brief The vertex iterator of the graph. */ class VertexIterator : public ForwardIteratorFacade { public: /** * @brief Constructor. * @param graph The graph over whose vertices to iterate. * @param current The position of the iterator. * @param end The last vertex of the graph. */ explicit VertexIterator(const SubGraph* graph, const VertexDescriptor& current, const VertexDescriptor& end); /** * @brief Constructor for end iterator. * * Use with care! All operations except operator== or operator!= will fail! * @param current The position of the iterator. */ explicit VertexIterator(const VertexDescriptor& current); /** @brief Preincrement operator. */ VertexIterator& increment(); /** @brief Equality iterator. */ bool equals(const VertexIterator& other) const; /** * @brief Get the descriptor of the current vertex. * @return The index of the currently referenced vertex. */ const VertexDescriptor& dereference() const; /** * @brief Get an iterator over all edges starting at the * current vertex. * @return Iterator position on the first edge to another vertex. */ EdgeIterator begin() const; /** * @brief Get an iterator over all edges starting at the * current vertex. * @return Iterator position on the first edge to another vertex. */ EdgeIterator end() const; private: /** @brief The graph we are a vertex iterator for. */ const SubGraph* graph_; /** @brief The current position. */ VertexDescriptor current_; /** @brief The number of vertices of the graph. */ VertexDescriptor end_; }; /** * @brief The constant edge iterator type. */ typedef EdgeIterator ConstEdgeIterator; /** * @brief The constant vertex iterator type. */ typedef VertexIterator ConstVertexIterator; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ ConstVertexIterator begin() const; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ ConstVertexIterator end() const; /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned at the first edge starting * from vertex source. */ ConstEdgeIterator beginEdges(const VertexDescriptor& source) const; /** * @brief Get an iterator over the edges starting at a vertex. * @param source The vertex where the edges should start. * @return An edge iterator positioned behind the last edge starting * from vertex source. */ ConstEdgeIterator endEdges(const VertexDescriptor& source) const; /** * @brief Get the number of vertices in the graph. */ std::size_t noVertices() const; /** * @brief Get the maximal vertex descriptor. * * @return The minimum value v such that for * all vertices w in the graph w<v holds. */ VertexDescriptor maxVertex() const; /** * @brief Get the number of edges in the graph. */ std::size_t noEdges() const; /** * @brief Find the descriptor of an edge. * @param source The source vertex of the edge we search for. * @param target The target vertex of the edge we search for. * @return The edge we found or numeric_limits::max() if it does not exist. */ EdgeDescriptor findEdge(const VertexDescriptor& source, const VertexDescriptor& target) const; /** * @brief Constructor. * * @param graph The graph we are a sub graph for. * @param excluded If excluded[i] is true then vertex i will not appear * in the sub graph. */ SubGraph(const Graph& graph, const T& excluded); /** * @brief Destructor. */ ~SubGraph(); private: /** @brief flags indication which vertices are excluded. */ const T& excluded_; /** @brief The number of vertices in this sub graph. */ std::size_t noVertices_; /** @brief Vertex behind the last valid vertex of this sub graph. */ VertexDescriptor endVertex_; /** @brief The number of edges in this sub graph.*/ int noEdges_; /** * @brief The maximum vertex descriptor of the graph * we are a subgraph for. */ VertexDescriptor maxVertex_; /** @brief The edges of this sub graph. */ VertexDescriptor* edges_; /** @brief The start of the out edges of each vertex. */ std::ptrdiff_t* start_; /** @brief The edge behind the last out edge of each vertex. */ std::ptrdiff_t* end_; /** prevent copying */ SubGraph(const SubGraph&) {} }; /** * @brief Attaches properties to the vertices of a graph. */ template class VertexPropertiesGraph { public: /** * @brief The graph we attach properties to. */ typedef G Graph; /** * @brief The vertex descriptor. */ typedef typename Graph::VertexDescriptor VertexDescriptor; /** * @brief The edge descritor. */ typedef typename Graph::EdgeDescriptor EdgeDescriptor; /** * @brief The type of the properties of the vertices. */ typedef VP VertexProperties; /** * @brief The type of the map for converting the VertexDescriptor * to std::size_t * * Has to provide the following method: * std::size_t operator[](const VertexDescriptor& vertex) * * The following condition has to be met: * Let v1 and v2 be two vertex descriptors with v1 < v2 and map be the * index map. Then map[v1] class VertexIteratorT : public std::conditional::type, C>::value, typename Graph::VertexIterator, typename Graph::ConstVertexIterator>::type { friend class VertexIteratorT::type>; friend class VertexIteratorT::type>; public: /** * @brief The father class. */ typedef typename std::conditional::type, C>::value, typename Graph::VertexIterator, typename Graph::ConstVertexIterator>::type Father; /** * @brief The class of the edge iterator. */ typedef typename std::conditional::type, C>::value, typename Graph::EdgeIterator, typename Graph::ConstEdgeIterator>::type EdgeIterator; /** * @brief Constructor. * @param iter The iterator of the underlying graph. * @param graph The property graph over whose vertices we iterate. */ explicit VertexIteratorT(const Father& iter, C* graph); /** * @brief Constructor for the end iterator. * * Only operator!= or operator== can be calles safely on an iterator * constructed this way. * @param iter The iterator of the underlying graph. */ explicit VertexIteratorT(const Father& iter); /** * @brief Copy Constructor. * @param other The iterator to copy. */ template VertexIteratorT(const VertexIteratorT& other); /** * @brief Get the properties of the current Vertex. */ typename std::conditional::type>::value, VertexProperties&, const VertexProperties&>::type properties() const; /** * @brief Get an iterator over the edges starting from the current vertex. * @return An iterator over the edges starting from the current vertex * positioned at the first edge. */ EdgeIterator begin() const; /** * @brief Get an iterator over the edges starting from the current vertex. * @return An iterator over the edges starting from the current vertex * positioned after the last edge. */ EdgeIterator end() const; private: /** * @brief The graph over whose vertices we iterate. */ C* graph_; }; /** * @brief The type of the mutable Vertex iterator. */ typedef VertexIteratorT > VertexIterator; /** * @brief The type of the constant Vertex iterator. */ typedef VertexIteratorT > ConstVertexIterator; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ VertexIterator begin(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ VertexIterator end(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ ConstVertexIterator begin() const; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ ConstVertexIterator end() const; /** * @brief Get the properties associated with a vertex. * @param vertex The descriptor identifying the vertex. * @return The properties of the vertex. */ VertexProperties& getVertexProperties(const VertexDescriptor& vertex); /** * @brief Get the properties associated with a vertex. * @param vertex The descriptor identifying the vertex. * @return The properties of the vertex. */ const VertexProperties& getVertexProperties(const VertexDescriptor& vertex) const; /** * @brief Get the graph the properties are attached to. * @return The underlying graph. */ const Graph& graph() const; /** * @brief Get the number of vertices in the graph. */ std::size_t noVertices() const; /** * @brief Get the number of edges in the graph. */ std::size_t noEdges() const; /** * @brief Get the maximal vertex descriptor. * * @return The minimum value v such that for * all vertices w in the graph w<v holds. */ VertexDescriptor maxVertex() const; /** * @brief Constructor. * @param graph The graph we attach properties to. * @param vmap The vertex map. */ VertexPropertiesGraph(Graph& graph, const VertexMap vmap=VertexMap()); private: VertexPropertiesGraph(const VertexPropertiesGraph&) {} /** @brief The graph the properties are attached to. */ Graph& graph_; /** @brief The vertex map. */ VertexMap vmap_; /** @brief The vertex properties. */ std::vector vertexProperties_; }; /** * @brief Attaches properties to the edges and vertices of a graph. */ template class PropertiesGraph { public: /** * @brief The graph we attach properties to. */ typedef G Graph; /** * @brief The vertex descriptor. */ typedef typename Graph::VertexDescriptor VertexDescriptor; /** * @brief The edge descritor. */ typedef typename Graph::EdgeDescriptor EdgeDescriptor; /** * @brief The type of the properties of the vertices. */ typedef VP VertexProperties; /** * @brief The type of the map for converting the VertexDescriptor * to std::size_t * * Has to provide the following method: * std::size_t operator[](const VertexDescriptor& vertex) * * The following condition has to be met: * Let v1 and v2 be two vertex descriptors with v1 < v2 and map be the * index map. Then map[v1] class EdgeIteratorT : public std::conditional::type, C>::value, typename Graph::EdgeIterator, typename Graph::ConstEdgeIterator>::type { friend class EdgeIteratorT::type>; friend class EdgeIteratorT::type>; public: /** * @brief The father class. */ typedef typename std::conditional::type, C>::value, typename Graph::EdgeIterator, typename Graph::ConstEdgeIterator>::type Father; /** * @brief Constructor. * @param iter The iterator of the underlying graph. * @param graph The graph over whose edges we iterate on. */ explicit EdgeIteratorT(const Father& iter, C* graph); /** * @brief Constructor for the end iterator. * * Only operator== or operator!= should be called on * an iterator constructed this way. * @param iter The iterator of the underlying graph. */ explicit EdgeIteratorT(const Father& iter); /** * @brief Copy constructor. * @param other the iterator to copy. */ template EdgeIteratorT(const EdgeIteratorT& other); /** * @brief Get the properties of the current edge. */ typename std::conditional::type>::value, EdgeProperties&, const EdgeProperties&>::type properties() const; private: /** * @brief The graph over whose edges we iterate. */ C* graph_; }; /** * @brief The type of the mutable edge iterator. */ typedef EdgeIteratorT > EdgeIterator; /** * @brief The type of the constant edge iterator. */ typedef EdgeIteratorT > ConstEdgeIterator; /** * @brief Get the mutable edge iterator over edges starting at a vertex. * @return An edge iterator over edges starting at a vertex * positioned at the first edge. */ EdgeIterator beginEdges(const VertexDescriptor& source); /** * @brief Get the mutable edge iterator over edges starting at a vertex. * @return An edge iterator over edges starting at a vertex * positioned after the last edge. */ EdgeIterator endEdges(const VertexDescriptor& source); /** * @brief Get the mutable edge iterator over edges starting at a vertex. * @return An edge iterator over edges starting at a vertex * positioned at the first edge. */ ConstEdgeIterator beginEdges(const VertexDescriptor& source) const; /** * @brief Get the mutable edge iterator over edges starting at a vertex. * @return An edge iterator over edges starting at a vertex * positioned after the last edge. */ ConstEdgeIterator endEdges(const VertexDescriptor& source) const; template class VertexIteratorT : public std::conditional::type, C>::value, typename Graph::VertexIterator, typename Graph::ConstVertexIterator>::type { friend class VertexIteratorT::type>; friend class VertexIteratorT::type>; public: /** * @brief The father class. */ typedef typename std::conditional::type, C>::value, typename Graph::VertexIterator, typename Graph::ConstVertexIterator>::type Father; /** * @brief Constructor. * @param iter The iterator of the underlying graph. * @param graph The property graph over whose vertices we iterate. */ explicit VertexIteratorT(const Father& iter, C* graph); /** * @brief Constructor for the end iterator. * * Only operator!= or operator== can be called safely on an iterator * constructed this way. * @param iter The iterator of the underlying graph. */ explicit VertexIteratorT(const Father& iter); /** * @brief Copy Constructor. * @param other The iterator to copy. */ template VertexIteratorT(const VertexIteratorT& other); /** * @brief Get the properties of the current Vertex. */ typename std::conditional::type>::value, VertexProperties&, const VertexProperties&>::type properties() const; /** * @brief Get an iterator over the edges starting from the current vertex. * @return An iterator over the edges starting from the current vertex * positioned at the first edge. */ EdgeIteratorT begin() const; /** * @brief Get an iterator over the edges starting from the current vertex. * @return An iterator over the edges starting from the current vertex * positioned after the last edge. */ EdgeIteratorT end() const; private: /** * @brief The graph over whose vertices we iterate. */ C* graph_; }; /** * @brief The type of the mutable Vertex iterator. */ typedef VertexIteratorT > VertexIterator; /** * @brief The type of the constant Vertex iterator. */ typedef VertexIteratorT > ConstVertexIterator; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ VertexIterator begin(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ VertexIterator end(); /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned at the first vertex. */ ConstVertexIterator begin() const; /** * @brief Get an iterator over the vertices. * @return A vertex Iterator positioned behind the last vertex. */ ConstVertexIterator end() const; /** * @brief Get the properties associated with a vertex. * @param vertex The descriptor identifying the vertex. * @return The properties of the vertex. */ VertexProperties& getVertexProperties(const VertexDescriptor& vertex); /** * @brief Get the properties associated with a vertex. * @param vertex The descriptor identifying the vertex. * @return The properties of the vertex. */ const VertexProperties& getVertexProperties(const VertexDescriptor& vertex) const; /** * @brief Find the descriptor of an edge. * @param source The source vertex of the edge we search for. * @param target The target vertex of the edge we search for. * @return The edge we found or numeric_limits::max() if it does not exist. */ EdgeDescriptor findEdge(const VertexDescriptor& source, const VertexDescriptor& target) { return graph_.findEdge(source,target); } /** * @brief Get the properties associated with a edge. * @param edge The descriptor identifying the edge. * @return The properties of the edge. */ EdgeProperties& getEdgeProperties(const EdgeDescriptor& edge); /** * @brief Get the properties associated with a edge. * @param edge The descriptor identifying the edge. * @return The properties of the edge. */ const EdgeProperties& getEdgeProperties(const EdgeDescriptor& edge) const; /** * @brief Get the properties associated with a edge. * @param source The descriptor identifying the source vertex of the edge. * @param target The descriptor identifying the target vertex of the edge. * @return The properties of the edge. */ EdgeProperties& getEdgeProperties(const VertexDescriptor& source, const VertexDescriptor& target); /** * @brief Get the properties associated with a edge. * @param source The descriptor identifying the source vertex of the edge. * @param target The descriptor identifying the target vertex of the edge. * @return The properties of the edge. */ const EdgeProperties& getEdgeProperties(const VertexDescriptor& source, const VertexDescriptor& target) const; /** * @brief Get the graph the properties are attached to. * @return The underlying graph. */ const Graph& graph() const; /** * @brief Get the number of vertices in the graph. */ std::size_t noVertices() const; /** * @brief Get the number of edges in the graph. */ std::size_t noEdges() const; /** * @brief Get the maximal vertex descriptor. * * @return The minimum value v such that for * all vertices w in the graph w<v holds. */ VertexDescriptor maxVertex() const; /** * @brief Constructor. * @param graph The graph we attach properties to. * @param vmap The map of the vertices onto indices. * @param emap The map of the edges onto indices. */ PropertiesGraph(Graph& graph, const VertexMap& vmap=VertexMap(), const EdgeMap& emap=EdgeMap()); private: PropertiesGraph(const PropertiesGraph&) {} /** @brief The graph the properties are attached to. */ Graph& graph_; /** @brief The vertex properties. */ /** @brief The mapping of the vertices to indices. */ VertexMap vmap_; std::vector vertexProperties_; /** @brief The mapping of the edges to indices. */ EdgeMap emap_; /** @brief The edge properties. */ std::vector edgeProperties_; }; /** * @brief Wrapper to access the internal edge properties of a graph * via operator[]() */ template class GraphVertexPropertiesSelector { public: /** * @brief The type of the graph with internal properties. */ typedef G Graph; /** * @brief The type of the vertex properties. */ typedef typename G::VertexProperties VertexProperties; /** * @brief The vertex descriptor. */ typedef typename G::VertexDescriptor Vertex; /** * @brief Constructor. * @param g The graph whose properties we access. */ GraphVertexPropertiesSelector(G& g) : graph_(g) {} /** * @brief Default constructor. */ GraphVertexPropertiesSelector() : graph_(0) {} /** * @brief Get the properties associated to a vertex. * @param vertex The vertex whose Properties we want. */ VertexProperties& operator[](const Vertex& vertex) const { return graph_->getVertexProperties(vertex); } private: Graph* graph_; }; /** * @brief Wrapper to access the internal vertex properties of a graph * via operator[]() */ template class GraphEdgePropertiesSelector { public: /** * @brief The type of the graph with internal properties. */ typedef G Graph; /** * @brief The type of the vertex properties. */ typedef typename G::EdgeProperties EdgeProperties; /** * @brief The edge descriptor. */ typedef typename G::EdgeDescriptor Edge; /** * @brief Constructor. * @param g The graph whose properties we access. */ GraphEdgePropertiesSelector(G& g) : graph_(g) {} /** * @brief Default constructor. */ GraphEdgePropertiesSelector() : graph_(0) {} /** * @brief Get the properties associated to a vertex. * @param edge The edge whose Properties we want. */ EdgeProperties& operator[](const Edge& edge) const { return graph_->getEdgeProperties(edge); } private: Graph* graph_; }; /** * @brief Visit all neighbour vertices of a vertex in a graph. * * @param graph The graph whose vertices to visit. * @param vertex The vertex whose neighbours we want to * visit. * @param visitor The visitor evaluated for each EdgeIterator * (by its method operator()(const ConstEdgeIterator& edge) * @return The number of neighbours of the vertex. */ template int visitNeighbours(const G& graph, const typename G::VertexDescriptor& vertex, V& visitor); #ifndef DOXYGEN template MatrixGraph::MatrixGraph(M& matrix) : matrix_(matrix) { if(matrix_.N()!=matrix_.M()) DUNE_THROW(ISTLError, "Matrix has to have as many columns as rows!"); start_ = new EdgeDescriptor[matrix_.N()+1]; typedef typename M::ConstIterator Iterator; start_[matrix_.begin().index()] = 0; for(Iterator row=matrix_.begin(); row != matrix_.end(); ++row) start_[row.index()+1] = start_[row.index()] + row->size(); } template MatrixGraph::~MatrixGraph() { delete[] start_; } template inline std::size_t MatrixGraph::noEdges() const { return start_[matrix_.N()]; } template inline std::size_t MatrixGraph::noVertices() const { return matrix_.N(); } template inline typename MatrixGraph::VertexDescriptor MatrixGraph::maxVertex() const { return matrix_.N()-1; } template typename MatrixGraph::EdgeDescriptor MatrixGraph::findEdge(const VertexDescriptor& source, const VertexDescriptor& target) const { typename M::ConstColIterator found =matrix_[source].find(target); if(found == matrix_[source].end()) return std::numeric_limits::max(); std::size_t offset = found.offset(); if(target>source) offset--; assert(offset inline M& MatrixGraph::matrix() { return matrix_; } template inline const M& MatrixGraph::matrix() const { return matrix_; } template template MatrixGraph::EdgeIteratorT::EdgeIteratorT(const VertexDescriptor& source, const ColIterator& block, const ColIterator& end, const EdgeDescriptor& edge) : source_(source), block_(block), blockEnd_(end), edge_(edge) { if(block_!=blockEnd_ && block_.index() == source_) { // This is the edge from the diagonal to the diagonal. Skip it. ++block_; } } template template MatrixGraph::EdgeIteratorT::EdgeIteratorT(const ColIterator& block) : block_(block) {} template template template MatrixGraph::EdgeIteratorT::EdgeIteratorT(const EdgeIteratorT& other) : source_(other.source_), block_(other.block_), blockEnd_(other.blockEnd_), edge_(other.edge_) {} template template inline typename MatrixGraph::template EdgeIteratorT::WeightType& MatrixGraph::EdgeIteratorT::weight() const { return *block_; } template template inline typename MatrixGraph::template EdgeIteratorT& MatrixGraph::EdgeIteratorT::operator++() { ++block_; ++edge_; if(block_!=blockEnd_ && block_.index() == source_) { // This is the edge from the diagonal to the diagonal. Skip it. ++block_; } return *this; } template template inline bool MatrixGraph::EdgeIteratorT::operator!=(const typename MatrixGraph::template EdgeIteratorT::type>& other) const { return block_!=other.block_; } template template inline bool MatrixGraph::EdgeIteratorT::operator!=(const typename MatrixGraph::template EdgeIteratorT::type>& other) const { return block_!=other.block_; } template template inline bool MatrixGraph::EdgeIteratorT::operator==(const typename MatrixGraph::template EdgeIteratorT::type>& other) const { return block_==other.block_; } template template inline bool MatrixGraph::EdgeIteratorT::operator==(const typename MatrixGraph::template EdgeIteratorT::type>& other) const { return block_==other.block_; } template template inline typename MatrixGraph::VertexDescriptor MatrixGraph::EdgeIteratorT::target() const { return block_.index(); } template template inline typename MatrixGraph::VertexDescriptor MatrixGraph::EdgeIteratorT::source() const { return source_; } template template inline const typename MatrixGraph::EdgeDescriptor& MatrixGraph::EdgeIteratorT::operator*() const { return edge_; } template template inline const typename MatrixGraph::EdgeDescriptor* MatrixGraph::EdgeIteratorT::operator->() const { return &edge_; } template template MatrixGraph::VertexIteratorT::VertexIteratorT(C* graph, const VertexDescriptor& current) : graph_(graph), current_(current) {} template template MatrixGraph::VertexIteratorT::VertexIteratorT(const VertexDescriptor& current) : current_(current) {} template template MatrixGraph::VertexIteratorT::VertexIteratorT(const VertexIteratorT& other) : graph_(other.graph_), current_(other.current_) {} template template inline bool MatrixGraph::VertexIteratorT::operator!=(const VertexIteratorT& other) const { return current_ != other.current_; } template template inline bool MatrixGraph::VertexIteratorT::operator!=(const VertexIteratorT& other) const { return current_ != other.current_; } template template inline bool MatrixGraph::VertexIteratorT::operator==(const VertexIteratorT& other) const { return current_ == other.current_; } template template inline bool MatrixGraph::VertexIteratorT::operator==(const VertexIteratorT& other) const { return current_ == other.current_; } template template inline typename MatrixGraph::template VertexIteratorT& MatrixGraph::VertexIteratorT::operator++() { ++current_; return *this; } template template inline typename MatrixGraph::template VertexIteratorT::WeightType& MatrixGraph::VertexIteratorT::weight() const { return graph_->matrix()[current_][current_]; } template template inline const typename MatrixGraph::VertexDescriptor& MatrixGraph::VertexIteratorT::operator*() const { return current_; } template template inline typename MatrixGraph::template EdgeIteratorT MatrixGraph::VertexIteratorT::begin() const { return graph_->beginEdges(current_); } template template inline typename MatrixGraph::template EdgeIteratorT MatrixGraph::VertexIteratorT::end() const { return graph_->endEdges(current_); } template inline typename MatrixGraph::template VertexIteratorT > MatrixGraph::begin() { return VertexIterator(this,0); } template inline typename MatrixGraph::template VertexIteratorT > MatrixGraph::end() { return VertexIterator(matrix_.N()); } template inline typename MatrixGraph::template VertexIteratorT > MatrixGraph::begin() const { return ConstVertexIterator(this, 0); } template inline typename MatrixGraph::template VertexIteratorT > MatrixGraph::end() const { return ConstVertexIterator(matrix_.N()); } template inline typename MatrixGraph::template EdgeIteratorT > MatrixGraph::beginEdges(const VertexDescriptor& source) { return EdgeIterator(source, matrix_.operator[](source).begin(), matrix_.operator[](source).end(), start_[source]); } template inline typename MatrixGraph::template EdgeIteratorT > MatrixGraph::endEdges(const VertexDescriptor& source) { return EdgeIterator(matrix_.operator[](source).end()); } template inline typename MatrixGraph::template EdgeIteratorT > MatrixGraph::beginEdges(const VertexDescriptor& source) const { return ConstEdgeIterator(source, matrix_.operator[](source).begin(), matrix_.operator[](source).end(), start_[source]); } template inline typename MatrixGraph::template EdgeIteratorT > MatrixGraph::endEdges(const VertexDescriptor& source) const { return ConstEdgeIterator(matrix_.operator[](source).end()); } template SubGraph::EdgeIterator::EdgeIterator(const VertexDescriptor& source, const EdgeDescriptor& edge) : source_(source), edge_(edge) {} template SubGraph::EdgeIterator::EdgeIterator(const EdgeDescriptor& edge) : edge_(edge) {} template typename SubGraph::EdgeIndexMap SubGraph::getEdgeIndexMap() { return EdgeIndexMap(edges_); } template inline bool SubGraph::EdgeIterator::equals(const EdgeIterator & other) const { return other.edge_==edge_; } template inline typename SubGraph::EdgeIterator& SubGraph::EdgeIterator::increment() { ++edge_; return *this; } template inline typename SubGraph::EdgeIterator& SubGraph::EdgeIterator::decrement() { --edge_; return *this; } template inline typename SubGraph::EdgeIterator& SubGraph::EdgeIterator::advance(std::ptrdiff_t n) { edge_+=n; return *this; } template inline const typename G::VertexDescriptor& SubGraph::EdgeIterator::source() const { return source_; } template inline const typename G::VertexDescriptor& SubGraph::EdgeIterator::target() const { return *edge_; } template inline const typename SubGraph::EdgeDescriptor& SubGraph::EdgeIterator::dereference() const { return edge_; } template inline std::ptrdiff_t SubGraph::EdgeIterator::distanceTo(const EdgeIterator & other) const { return other.edge_-edge_; } template SubGraph::VertexIterator::VertexIterator(const SubGraph* graph, const VertexDescriptor& current, const VertexDescriptor& end) : graph_(graph), current_(current), end_(end) { // Skip excluded vertices typedef typename T::const_iterator Iterator; for(Iterator vertex = graph_->excluded_.begin(); current_ != end_ && *vertex; ++vertex) ++current_; assert(current_ == end_ || !graph_->excluded_[current_]); } template SubGraph::VertexIterator::VertexIterator(const VertexDescriptor& current) : current_(current) {} template inline typename SubGraph::VertexIterator& SubGraph::VertexIterator::increment() { ++current_; //Skip excluded vertices while(current_ != end_ && graph_->excluded_[current_]) ++current_; assert(current_ == end_ || !graph_->excluded_[current_]); return *this; } template inline bool SubGraph::VertexIterator::equals(const VertexIterator & other) const { return current_==other.current_; } template inline const typename G::VertexDescriptor& SubGraph::VertexIterator::dereference() const { return current_; } template inline typename SubGraph::EdgeIterator SubGraph::VertexIterator::begin() const { return graph_->beginEdges(current_); } template inline typename SubGraph::EdgeIterator SubGraph::VertexIterator::end() const { return graph_->endEdges(current_); } template inline typename SubGraph::VertexIterator SubGraph::begin() const { return VertexIterator(this, 0, endVertex_); } template inline typename SubGraph::VertexIterator SubGraph::end() const { return VertexIterator(endVertex_); } template inline typename SubGraph::EdgeIterator SubGraph::beginEdges(const VertexDescriptor& source) const { return EdgeIterator(source, edges_+start_[source]); } template inline typename SubGraph::EdgeIterator SubGraph::endEdges(const VertexDescriptor& source) const { return EdgeIterator(edges_+end_[source]); } template std::size_t SubGraph::noVertices() const { return noVertices_; } template inline typename SubGraph::VertexDescriptor SubGraph::maxVertex() const { return maxVertex_; } template inline std::size_t SubGraph::noEdges() const { return noEdges_; } template inline typename SubGraph::EdgeDescriptor SubGraph::findEdge(const VertexDescriptor& source, const VertexDescriptor& target) const { const EdgeDescriptor edge = std::lower_bound(edges_+start_[source], edges_+end_[source], target); if(edge==edges_+end_[source] || *edge!=target) return std::numeric_limits::max(); return edge; } template SubGraph::~SubGraph() { delete[] edges_; delete[] end_; delete[] start_; } template SubGraph::SubGraph(const G& graph, const T& excluded) : excluded_(excluded), noVertices_(0), endVertex_(0), maxVertex_(graph.maxVertex()) { start_ = new std::ptrdiff_t[graph.noVertices()]; end_ = new std::ptrdiff_t[graph.noVertices()]; edges_ = new VertexDescriptor[graph.noEdges()]; VertexDescriptor* edge=edges_; typedef typename Graph::ConstVertexIterator Iterator; Iterator endVertex=graph.end(); for(Iterator vertex = graph.begin(); vertex != endVertex; ++vertex) if(excluded_[*vertex]) start_[*vertex]=end_[*vertex]=-1; else{ ++noVertices_; endVertex_ = std::max(*vertex, endVertex_); start_[*vertex] = edge-edges_; typedef typename Graph::ConstEdgeIterator Iterator; Iterator endEdge = vertex.end(); for(Iterator iter=vertex.begin(); iter!= endEdge; ++iter) if(!excluded[iter.target()]) { *edge = iter.target(); ++edge; } end_[*vertex] = edge - edges_; // Sort the edges std::sort(edges_+start_[*vertex], edge); } noEdges_ = edge-edges_; ++endVertex_; } template inline std::size_t VertexPropertiesGraph::noEdges() const { return graph_.noEdges(); } template inline typename VertexPropertiesGraph::EdgeIterator VertexPropertiesGraph::beginEdges(const VertexDescriptor& source) { return graph_.beginEdges(source); } template inline typename VertexPropertiesGraph::EdgeIterator VertexPropertiesGraph::endEdges(const VertexDescriptor& source) { return graph_.endEdges(source); } template typename VertexPropertiesGraph::ConstEdgeIterator inline VertexPropertiesGraph::beginEdges(const VertexDescriptor& source) const { return graph_.beginEdges(source); } template typename VertexPropertiesGraph::ConstEdgeIterator VertexPropertiesGraph::endEdges(const VertexDescriptor& source) const { return graph_.endEdges(source); } template template VertexPropertiesGraph::VertexIteratorT ::VertexIteratorT(const Father& iter, C* graph) : Father(iter), graph_(graph) {} template template VertexPropertiesGraph::VertexIteratorT ::VertexIteratorT(const Father& iter) : Father(iter) {} template template template VertexPropertiesGraph::VertexIteratorT ::VertexIteratorT(const VertexIteratorT& other) : Father(other), graph_(other.graph_) {} template template typename std::conditional::type>::value, V&, const V&>::type inline VertexPropertiesGraph::VertexIteratorT::properties() const { return graph_->getVertexProperties(Father::operator*()); } template template typename std::conditional::type, C>::value, typename G::EdgeIterator, typename G::ConstEdgeIterator>::type inline VertexPropertiesGraph::VertexIteratorT::begin() const { return graph_->beginEdges(Father::operator*()); } template template typename std::conditional::type, C>::value, typename G::EdgeIterator, typename G::ConstEdgeIterator>::type inline VertexPropertiesGraph::VertexIteratorT::end() const { return graph_->endEdges(Father::operator*()); } template inline typename VertexPropertiesGraph::VertexIterator VertexPropertiesGraph::begin() { return VertexIterator(graph_.begin(), this); } template inline typename VertexPropertiesGraph::VertexIterator VertexPropertiesGraph::end() { return VertexIterator(graph_.end()); } template inline typename VertexPropertiesGraph::ConstVertexIterator VertexPropertiesGraph::begin() const { return ConstVertexIterator(graph_.begin(), this); } template inline typename VertexPropertiesGraph::ConstVertexIterator VertexPropertiesGraph::end() const { return ConstVertexIterator(graph_.end()); } template inline V& VertexPropertiesGraph::getVertexProperties(const VertexDescriptor& vertex) { return vertexProperties_[vmap_[vertex]]; } template inline const V& VertexPropertiesGraph::getVertexProperties(const VertexDescriptor& vertex) const { return vertexProperties_[vmap_[vertex]]; } template inline const G& VertexPropertiesGraph::graph() const { return graph_; } template inline std::size_t VertexPropertiesGraph::noVertices() const { return graph_.noVertices(); } template inline typename VertexPropertiesGraph::VertexDescriptor VertexPropertiesGraph::maxVertex() const { return graph_.maxVertex(); } template VertexPropertiesGraph::VertexPropertiesGraph(Graph& graph, const VM vmap) : graph_(graph), vmap_(vmap), vertexProperties_(vmap_[graph_.maxVertex()+1], V()) {} template template PropertiesGraph::EdgeIteratorT::EdgeIteratorT(const Father& iter, C* graph) : Father(iter), graph_(graph) {} template template PropertiesGraph::EdgeIteratorT::EdgeIteratorT(const Father& iter) : Father(iter) {} template template template PropertiesGraph::EdgeIteratorT::EdgeIteratorT(const EdgeIteratorT& other) : Father(other), graph_(other.graph_) {} template inline std::size_t PropertiesGraph::noEdges() const { return graph_.noEdges(); } template template inline typename std::conditional::type>::value,E&,const E&>::type PropertiesGraph::EdgeIteratorT::properties() const { return graph_->getEdgeProperties(Father::operator*()); } template inline typename PropertiesGraph::EdgeIterator PropertiesGraph::beginEdges(const VertexDescriptor& source) { return EdgeIterator(graph_.beginEdges(source), this); } template inline typename PropertiesGraph::EdgeIterator PropertiesGraph::endEdges(const VertexDescriptor& source) { return EdgeIterator(graph_.endEdges(source)); } template typename PropertiesGraph::ConstEdgeIterator inline PropertiesGraph::beginEdges(const VertexDescriptor& source) const { return ConstEdgeIterator(graph_.beginEdges(source), this); } template typename PropertiesGraph::ConstEdgeIterator PropertiesGraph::endEdges(const VertexDescriptor& source) const { return ConstEdgeIterator(graph_.endEdges(source)); } template template PropertiesGraph::VertexIteratorT ::VertexIteratorT(const Father& iter, C* graph) : Father(iter), graph_(graph) {} template template PropertiesGraph::VertexIteratorT ::VertexIteratorT(const Father& iter) : Father(iter) {} template template template PropertiesGraph::VertexIteratorT ::VertexIteratorT(const VertexIteratorT& other) : Father(other), graph_(other.graph_) {} template template inline typename std::conditional::type>::value, V&, const V&>::type PropertiesGraph::VertexIteratorT::properties() const { return graph_->getVertexProperties(Father::operator*()); } template template inline typename PropertiesGraph::template EdgeIteratorT PropertiesGraph::VertexIteratorT::begin() const { return graph_->beginEdges(Father::operator*()); } template template inline typename PropertiesGraph::template EdgeIteratorT PropertiesGraph::VertexIteratorT::end() const { return graph_->endEdges(Father::operator*()); } template inline typename PropertiesGraph::VertexIterator PropertiesGraph::begin() { return VertexIterator(graph_.begin(), this); } template inline typename PropertiesGraph::VertexIterator PropertiesGraph::end() { return VertexIterator(graph_.end()); } template inline typename PropertiesGraph::ConstVertexIterator PropertiesGraph::begin() const { return ConstVertexIterator(graph_.begin(), this); } template inline typename PropertiesGraph::ConstVertexIterator PropertiesGraph::end() const { return ConstVertexIterator(graph_.end()); } template inline V& PropertiesGraph::getVertexProperties(const VertexDescriptor& vertex) { return vertexProperties_[vmap_[vertex]]; } template inline const V& PropertiesGraph::getVertexProperties(const VertexDescriptor& vertex) const { return vertexProperties_[vmap_[vertex]]; } template inline E& PropertiesGraph::getEdgeProperties(const EdgeDescriptor& edge) { return edgeProperties_[emap_[edge]]; } template inline const E& PropertiesGraph::getEdgeProperties(const EdgeDescriptor& edge) const { return edgeProperties_[emap_[edge]]; } template inline E& PropertiesGraph::getEdgeProperties(const VertexDescriptor& source, const VertexDescriptor& target) { return getEdgeProperties(graph_.findEdge(source,target)); } template inline const E& PropertiesGraph::getEdgeProperties(const VertexDescriptor& source, const VertexDescriptor& target) const { return getEdgeProperties(graph_.findEdge(source,target)); } template inline const G& PropertiesGraph::graph() const { return graph_; } template inline std::size_t PropertiesGraph::noVertices() const { return graph_.noVertices(); } template inline typename PropertiesGraph::VertexDescriptor PropertiesGraph::maxVertex() const { return graph_.maxVertex(); } template PropertiesGraph::PropertiesGraph(Graph& graph, const VM& vmap, const EM& emap) : graph_(graph), vmap_(vmap), vertexProperties_(vmap_[graph_.maxVertex()+1], V()), emap_(emap), edgeProperties_(graph_.noEdges(), E()) {} template inline int visitNeighbours(const G& graph, const typename G::VertexDescriptor& vertex, V& visitor) { typedef typename G::ConstEdgeIterator iterator; const iterator end = graph.endEdges(vertex); int noNeighbours=0; for(iterator edge = graph.beginEdges(vertex); edge != end; ++edge, ++noNeighbours) visitor(edge); return noNeighbours; } #endif // DOXYGEN /** @} */ } } #endif dune-istl-2.5.1/dune/istl/paamg/graphcreator.hh000066400000000000000000000106321313314427100214210ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_GRAPHCREATOR_HH #define DUNE_AMG_GRAPHCREATOR_HH #include #include "graph.hh" #include "dependency.hh" #include "pinfo.hh" #include #include #include namespace Dune { namespace Amg { template struct PropertiesGraphCreator {}; template struct PropertiesGraphCreator { typedef typename M::matrix_type Matrix; typedef Dune::Amg::MatrixGraph MatrixGraph; typedef Dune::Amg::PropertiesGraph PropertiesGraph; typedef std::tuple GraphTuple; template static GraphTuple create(const M& matrix, T& excluded, const SequentialInformation& pinfo, const OF&) { DUNE_UNUSED_PARAMETER(excluded); DUNE_UNUSED_PARAMETER(pinfo); MatrixGraph* mg = new MatrixGraph(matrix.getmat()); PropertiesGraph* pg = new PropertiesGraph(*mg, IdentityMap(), IdentityMap()); return GraphTuple(mg,pg); } static void free(GraphTuple& graphs) { delete std::get<1>(graphs); } }; template struct PropertiesGraphCreator { typedef typename M::matrix_type Matrix; typedef Dune::Amg::MatrixGraph MatrixGraph; typedef Dune::Amg::SubGraph > SubGraph; typedef Dune::Amg::PropertiesGraph PropertiesGraph; typedef std::tuple GraphTuple; template static GraphTuple create(const M& matrix, T& excluded, PI& pinfo, const OF& of) { MatrixGraph* mg = new MatrixGraph(matrix.getmat()); typedef typename PI::ParallelIndexSet ParallelIndexSet; typedef typename ParallelIndexSet::const_iterator IndexIterator; IndexIterator iend = pinfo.indexSet().end(); for(IndexIterator index = pinfo.indexSet().begin(); index != iend; ++index) excluded[index->local()] = of.contains(index->local().attribute()); SubGraph* sg= new SubGraph(*mg, excluded); PropertiesGraph* pg = new PropertiesGraph(*sg, IdentityMap(), sg->getEdgeIndexMap()); return GraphTuple(mg,pg,sg); } static void free(GraphTuple& graphs) { delete std::get<2>(graphs); delete std::get<1>(graphs); } }; template struct PropertiesGraphCreator { typedef typename M::matrix_type Matrix; typedef Dune::Amg::MatrixGraph MatrixGraph; typedef Dune::Amg::SubGraph > SubGraph; typedef Dune::Amg::PropertiesGraph PropertiesGraph; typedef std::tuple GraphTuple; template static GraphTuple create(const M& matrix, T& excluded, PI& pinfo, const OF& of) { MatrixGraph* mg = new MatrixGraph(matrix.getmat()); typedef typename PI::ParallelIndexSet ParallelIndexSet; typedef typename ParallelIndexSet::const_iterator IndexIterator; IndexIterator iend = pinfo.indexSet().end(); for(IndexIterator index = pinfo.indexSet().begin(); index != iend; ++index) excluded[index->local()] = of.contains(index->local().attribute()); SubGraph* sg= new SubGraph(*mg, excluded); PropertiesGraph* pg = new PropertiesGraph(*sg, IdentityMap(), sg->getEdgeIndexMap()); return GraphTuple(mg,pg,sg); } static void free(GraphTuple& graphs) { delete std::get<2>(graphs); delete std::get<1>(graphs); } }; } //namespace Amg } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/hierarchy.hh000066400000000000000000001426521313314427100207260ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMGHIERARCHY_HH #define DUNE_AMGHIERARCHY_HH #include #include #include #include #include #include "aggregates.hh" #include "graph.hh" #include "galerkin.hh" #include "renumberer.hh" #include "graphcreator.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides a classes representing the hierarchies in AMG. */ enum { /** * @brief Hard limit for the number of processes allowed. * * This is needed to prevent overflows when calculating * the coarsening rate. Currently set 72,000 which is * enough for JUGENE. */ MAX_PROCESSES = 72000 }; /** * @brief A hierarchy of coantainers (e.g. matrices or vectors) * * Because sometimes a redistribution of the parallel data might be * advisable one can add redistributed version of the container at * each level. */ template > class Hierarchy { public: /** * @brief The type of the container we store. */ typedef T MemberType; template class LevelIterator; private: /** * @brief An element in the hierarchy. */ struct Element { friend class LevelIterator, T>; friend class LevelIterator, const T>; /** @brief The next coarser element in the list. */ Element* coarser_; /** @brief The next finer element in the list. */ Element* finer_; /** @brief Pointer to the element. */ MemberType* element_; /** @brief The redistributed version of the element. */ MemberType* redistributed_; }; public: // enum{ // /** // * @brief If true only the method addCoarser will be usable // * otherwise only the method addFiner will be usable. // */ // coarsen = b // }; /** * @brief The allocator to use for the list elements. */ typedef typename A::template rebind::other Allocator; typedef typename ConstructionTraits::Arguments Arguments; /** * @brief Construct a new hierarchy. * @param first The first element in the hierarchy. */ Hierarchy(MemberType& first); /** * @brief Construct a new hierarchy. * @param first Pointer to the first element in the hierarchy. * @warning Hierarchy will be responsible for the memory * management of the pointer. */ Hierarchy(MemberType* first); /** * @brief Construct a new empty hierarchy. */ Hierarchy(); /** * @brief Copy constructor. */ Hierarchy(const Hierarchy& other); /** * @brief Add an element on a coarser level. * @param args The arguments needed for the construction. */ void addCoarser(Arguments& args); void addRedistributedOnCoarsest(Arguments& args); /** * @brief Add an element on a finer level. * @param args The arguments needed for the construction. */ void addFiner(Arguments& args); /** * @brief Iterator over the levels in the hierarchy. * * operator++() moves to the next coarser level in the hierarchy. * while operator--() moves to the next finer level in the hierarchy. */ template class LevelIterator : public BidirectionalIteratorFacade,T1,T1&> { friend class LevelIterator::type, typename std::remove_const::type >; friend class LevelIterator::type, const typename std::remove_const::type >; public: /** @brief Constructor. */ LevelIterator() : element_(0) {} LevelIterator(Element* element) : element_(element) {} /** @brief Copy constructor. */ LevelIterator(const LevelIterator::type, typename std::remove_const::type>& other) : element_(other.element_) {} /** @brief Copy constructor. */ LevelIterator(const LevelIterator::type, const typename std::remove_const::type>& other) : element_(other.element_) {} /** * @brief Equality check. */ bool equals(const LevelIterator::type, typename std::remove_const::type>& other) const { return element_ == other.element_; } /** * @brief Equality check. */ bool equals(const LevelIterator::type, const typename std::remove_const::type>& other) const { return element_ == other.element_; } /** @brief Dereference the iterator. */ T1& dereference() const { return *(element_->element_); } /** @brief Move to the next coarser level */ void increment() { element_ = element_->coarser_; } /** @brief Move to the next fine level */ void decrement() { element_ = element_->finer_; } /** * @brief Check whether there was a redistribution at the current level. * @return True if there is a redistributed version of the conatainer at the current level. */ bool isRedistributed() const { return element_->redistributed_; } /** * @brief Get the redistributed container. * @return The redistributed container. */ T1& getRedistributed() const { assert(element_->redistributed_); return *element_->redistributed_; } void addRedistributed(T1* t) { element_->redistributed_ = t; } void deleteRedistributed() { element_->redistributed_ = nullptr; } private: Element* element_; }; /** @brief Type of the mutable iterator. */ typedef LevelIterator,T> Iterator; /** @brief Type of the const iterator. */ typedef LevelIterator, const T> ConstIterator; /** * @brief Get an iterator positioned at the finest level. * @return An iterator positioned at the finest level. */ Iterator finest(); /** * @brief Get an iterator positioned at the coarsest level. * @return An iterator positioned at the coarsest level. */ Iterator coarsest(); /** * @brief Get an iterator positioned at the finest level. * @return An iterator positioned at the finest level. */ ConstIterator finest() const; /** * @brief Get an iterator positioned at the coarsest level. * @return An iterator positioned at the coarsest level. */ ConstIterator coarsest() const; /** * @brief Get the number of levels in the hierarchy. * @return The number of levels. */ std::size_t levels() const; /** @brief Destructor. */ ~Hierarchy(); private: /** @brief The finest element in the hierarchy. */ Element* finest_; /** @brief The coarsest element in the hierarchy. */ Element* coarsest_; /** @brief Whether the first element was not allocated by us. */ Element* nonAllocated_; /** @brief The allocator for the list elements. */ Allocator allocator_; /** @brief The number of levels in the hierarchy. */ int levels_; }; /** * @brief The hierarchies build by the coarsening process. * * Namely a hierarchy of matrices, index sets, remote indices, * interfaces and communicators. */ template > class MatrixHierarchy { public: /** @brief The type of the matrix operator. */ typedef M MatrixOperator; /** @brief The type of the matrix. */ typedef typename MatrixOperator::matrix_type Matrix; /** @brief The type of the index set. */ typedef PI ParallelInformation; /** @brief The allocator to use. */ typedef A Allocator; /** @brief The type of the aggregates map we use. */ typedef Dune::Amg::AggregatesMap::VertexDescriptor> AggregatesMap; /** @brief The type of the parallel matrix hierarchy. */ typedef Dune::Amg::Hierarchy ParallelMatrixHierarchy; /** @brief The type of the parallel informarion hierarchy. */ typedef Dune::Amg::Hierarchy ParallelInformationHierarchy; /** @brief Allocator for pointers. */ typedef typename Allocator::template rebind::other AAllocator; /** @brief The type of the aggregates maps list. */ typedef std::list AggregatesMapList; /** @brief The type of the redistribute information. */ typedef RedistributeInformation RedistributeInfoType; /** @brief Allocator for RedistributeInfoType. */ typedef typename Allocator::template rebind::other RILAllocator; /** @brief The type of the list of redistribute information. */ typedef std::list RedistributeInfoList; /** * @brief Constructor * @param fineMatrix The matrix to coarsen. * @param pinfo The information about the parallel data decomposition at the first level. */ MatrixHierarchy(const MatrixOperator& fineMatrix, const ParallelInformation& pinfo=ParallelInformation()); ~MatrixHierarchy(); /** * @brief Build the matrix hierarchy using aggregation. * * @brief criterion The criterion describing the aggregation process. */ template void build(const T& criterion); /** * @brief Recalculate the galerkin products. * * If the data of the fine matrix changes but not its sparsity pattern * this will recalculate all coarser levels without starting the expensive * aggregation process all over again. */ template void recalculateGalerkin(const F& copyFlags); /** * @brief Coarsen the vector hierarchy according to the matrix hierarchy. * @param hierarchy The vector hierarchy to coarsen. */ template void coarsenVector(Hierarchy >& hierarchy) const; /** * @brief Coarsen the smoother hierarchy according to the matrix hierarchy. * @param smoothers The smoother hierarchy to coarsen. * @param args The arguments for the construction of the coarse level smoothers. */ template void coarsenSmoother(Hierarchy& smoothers, const typename SmootherTraits::Arguments& args) const; /** * @brief Get the number of levels in the hierarchy. * @return The number of levels. */ std::size_t levels() const; /** * @brief Get the max number of levels in the hierarchy of processors. * @return The maximum number of levels. */ std::size_t maxlevels() const; bool hasCoarsest() const; /** * @brief Whether the hierarchy was built. * @return true if the MatrixHierarchy::build method was called. */ bool isBuilt() const; /** * @brief Get the matrix hierarchy. * @return The matrix hierarchy. */ const ParallelMatrixHierarchy& matrices() const; /** * @brief Get the hierarchy of the parallel data distribution information. * @return The hierarchy of the parallel data distribution information. */ const ParallelInformationHierarchy& parallelInformation() const; /** * @brief Get the hierarchy of the mappings of the nodes onto aggregates. * @return The hierarchy of the mappings of the nodes onto aggregates. */ const AggregatesMapList& aggregatesMaps() const; /** * @brief Get the hierarchy of the information about redistributions, * @return The hierarchy of the information about redistributions of the * data to fewer processes. */ const RedistributeInfoList& redistributeInformation() const; typename MatrixOperator::field_type getProlongationDampingFactor() const { return prolongDamp_; } /** * @brief Get the mapping of fine level unknowns to coarse level * aggregates. * * For each fine level unknown i the correcponding data[i] is the * aggregate it belongs to on the coarsest level. * * @param[out] data The mapping of fine level unknowns to coarse level * aggregates. */ void getCoarsestAggregatesOnFinest(std::vector& data) const; private: typedef typename ConstructionTraits::Arguments MatrixArgs; typedef typename ConstructionTraits::Arguments CommunicationArgs; /** @brief The list of aggregates maps. */ AggregatesMapList aggregatesMaps_; /** @brief The list of redistributes. */ RedistributeInfoList redistributes_; /** @brief The hierarchy of parallel matrices. */ ParallelMatrixHierarchy matrices_; /** @brief The hierarchy of the parallel information. */ ParallelInformationHierarchy parallelInformation_; /** @brief Whether the hierarchy was built. */ bool built_; /** @brief The maximum number of level across all processors.*/ int maxlevels_; typename MatrixOperator::field_type prolongDamp_; /** * @brief functor to print matrix statistics. */ template struct MatrixStats { /** * @brief Print matrix statistics. */ static void stats(const Matrix& matrix) { DUNE_UNUSED_PARAMETER(matrix); } }; template struct MatrixStats { struct calc { typedef typename Matrix::size_type size_type; typedef typename Matrix::row_type matrix_row; calc() { min=std::numeric_limits::max(); max=0; sum=0; } void operator()(const matrix_row& row) { min=std::min(min, row.size()); max=std::max(max, row.size()); sum += row.size(); } size_type min; size_type max; size_type sum; }; /** * @brief Print matrix statistics. */ static void stats(const Matrix& matrix) { calc c= for_each(matrix.begin(), matrix.end(), calc()); dinfo<<"Matrix row: min="< bool repartitionAndDistributeMatrix(const M& origMatrix, M& newMatrix, C& origComm, C*& newComm, RedistributeInformation& ri, int nparts, C1& criterion) { Timer time; #ifdef AMG_REPART_ON_COMM_GRAPH // Done not repartition the matrix graph, but a graph of the communication scheme. bool existentOnRedist=Dune::commGraphRepartition(origMatrix, origComm, nparts, newComm, ri.getInterface(), criterion.debugLevel()>1); #else typedef Dune::Amg::MatrixGraph MatrixGraph; typedef Dune::Amg::PropertiesGraph PropertiesGraph; MatrixGraph graph(origMatrix); PropertiesGraph pgraph(graph); buildDependency(pgraph, origMatrix, criterion, false); #ifdef DEBUG_REPART if(origComm.communicator().rank()==0) std::cout<<"Original matrix"<1); #endif // if else AMG_REPART if(origComm.communicator().rank()==0 && criterion.debugLevel()>1) std::cout<<"Repartitioning took "<indexSet(), origComm.communicator()); #endif redistributeMatrix(const_cast(origMatrix), newMatrix, origComm, *newComm, ri); #ifdef DEBUG_REPART if(origComm.communicator().rank()==0) std::cout<<"Original matrix"<communicator().size()>0) printGlobalSparseMatrix(newMatrix, *newComm, std::cout); origComm.communicator().barrier(); #endif if(origComm.communicator().rank()==0 && criterion.debugLevel()>1) std::cout<<"Redistributing matrix took "< bool repartitionAndDistributeMatrix(M& origMatrix, M& newMatrix, SequentialInformation& origComm, SequentialInformation& newComm, RedistributeInformation& ri) { return true; } template MatrixHierarchy::MatrixHierarchy(const MatrixOperator& fineOperator, const ParallelInformation& pinfo) : matrices_(const_cast(fineOperator)), parallelInformation_(const_cast(pinfo)) { static_assert((static_cast(MatrixOperator::category) == static_cast(SolverCategory::sequential) || static_cast(MatrixOperator::category) == static_cast(SolverCategory::overlapping) || static_cast(MatrixOperator::category) == static_cast(SolverCategory::nonoverlapping)), "MatrixOperator must be of category sequential or overlapping or nonoverlapping"); if (static_cast(MatrixOperator::category) != static_cast(pinfo.getSolverCategory())) DUNE_THROW(ISTLError, "MatrixOperator and ParallelInformation must belong to the same category!"); } template template void MatrixHierarchy::build(const T& criterion) { prolongDamp_ = criterion.getProlongationDampingFactor(); typedef O OverlapFlags; typedef typename ParallelMatrixHierarchy::Iterator MatIterator; typedef typename ParallelInformationHierarchy::Iterator PInfoIterator; static const int noints=(Dune::Amg::MAX_PROCESSES/4096>0) ? (Dune::Amg::MAX_PROCESSES/4096) : 1; typedef bigunsignedint BIGINT; GalerkinProduct productBuilder; MatIterator mlevel = matrices_.finest(); MatrixStats::stats(mlevel->getmat()); PInfoIterator infoLevel = parallelInformation_.finest(); BIGINT finenonzeros=countNonZeros(mlevel->getmat()); finenonzeros = infoLevel->communicator().sum(finenonzeros); BIGINT allnonzeros = finenonzeros; int level = 0; int rank = 0; BIGINT unknowns = mlevel->getmat().N(); unknowns = infoLevel->communicator().sum(unknowns); double dunknowns=unknowns.todouble(); infoLevel->buildGlobalLookup(mlevel->getmat().N()); redistributes_.push_back(RedistributeInfoType()); for(; level < criterion.maxLevel(); ++level, ++mlevel) { assert(matrices_.levels()==redistributes_.size()); rank = infoLevel->communicator().rank(); if(rank==0 && criterion.debugLevel()>1) std::cout<<"Level "<communicator().size() <<" unknowns per proc (procs="<communicator().size()<<")"<communicator().size())) && infoLevel->communicator().size()>1 && dunknowns/infoLevel->communicator().size() <= criterion.coarsenTarget()) { // accumulate to fewer processors Matrix* redistMat= new Matrix(); ParallelInformation* redistComm=0; std::size_t nodomains = (std::size_t)std::ceil(dunknowns/(criterion.minAggregateSize() *criterion.coarsenTarget())); if( nodomains<=criterion.minAggregateSize()/2 || dunknowns <= criterion.coarsenTarget() ) nodomains=1; bool existentOnNextLevel = repartitionAndDistributeMatrix(mlevel->getmat(), *redistMat, *infoLevel, redistComm, redistributes_.back(), nodomains, criterion); BIGINT unknownsRedist = redistMat->N(); unknownsRedist = infoLevel->communicator().sum(unknownsRedist); dunknowns= unknownsRedist.todouble(); if(redistComm->communicator().rank()==0 && criterion.debugLevel()>1) std::cout<<"Level "<communicator().size() <<" unknowns per proc (procs="<communicator().size()<<")"<::construct(args)); assert(mlevel.isRedistributed()); infoLevel.addRedistributed(redistComm); infoLevel->freeGlobalLookup(); if(!existentOnNextLevel) // We do not hold any data on the redistributed partitioning break; // Work on the redistributed Matrix from now on matrix = &(mlevel.getRedistributed()); info = &(infoLevel.getRedistributed()); info->buildGlobalLookup(matrix->getmat().N()); } rank = info->communicator().rank(); if(dunknowns <= criterion.coarsenTarget()) // No further coarsening needed break; typedef PropertiesGraphCreator GraphCreator; typedef typename GraphCreator::PropertiesGraph PropertiesGraph; typedef typename GraphCreator::GraphTuple GraphTuple; typedef typename PropertiesGraph::VertexDescriptor Vertex; std::vector excluded(matrix->getmat().N(), false); GraphTuple graphs = GraphCreator::create(*matrix, excluded, *info, OverlapFlags()); AggregatesMap* aggregatesMap=new AggregatesMap(std::get<1>(graphs)->maxVertex()+1); aggregatesMaps_.push_back(aggregatesMap); Timer watch; watch.reset(); int noAggregates, isoAggregates, oneAggregates, skippedAggregates; std::tie(noAggregates, isoAggregates, oneAggregates, skippedAggregates) = aggregatesMap->buildAggregates(matrix->getmat(), *(std::get<1>(graphs)), criterion, level==0); if(rank==0 && criterion.debugLevel()>2) std::cout<<" Have built "<communicator().rank(); int n = UNKNOWNS/procs; // number of unknowns per process int bigger = UNKNOWNS%procs; // number of process with n+1 unknows // Compute owner region if(rank0) overlapStart = start - 1; else overlapStart = start; if(endnoVertices()); for(int j=0; j< UNKNOWNS; ++j) for(int i=0; i < UNKNOWNS; ++i) { if(i>=overlapStart && i1 && info->communicator().rank()==0) std::cout<<"aggregating finished."<communicator().sum(gnoAggregates); double dgnoAggregates = gnoAggregates.todouble(); #ifdef TEST_AGGLO BIGINT gnoAggregates=((UNKNOWNS)/2)*((UNKNOWNS)/2); #endif if(criterion.debugLevel()>2 && rank==0) std::cout << "Building "<0) std::cerr << "Stopped coarsening because of rate breakdown "<free(); delete aggregatesMap; aggregatesMaps_.pop_back(); if(criterion.accumulate() && mlevel.isRedistributed() && info->communicator().size()>1) { // coarse level matrix was already redistributed, but to more than 1 process // Therefore need to delete the redistribution. Further down it will // then be redistributed to 1 process delete &(mlevel.getRedistributed().getmat()); mlevel.deleteRedistributed(); delete &(infoLevel.getRedistributed()); infoLevel.deleteRedistributed(); redistributes_.back().resetSetup(); } break; } unknowns = noAggregates; dunknowns = dgnoAggregates; CommunicationArgs commargs(info->communicator(),info->getSolverCategory()); parallelInformation_.addCoarser(commargs); ++infoLevel; // parallel information on coarse level typename PropertyMapTypeSelector::Type visitedMap = get(VertexVisitedTag(), *(std::get<1>(graphs))); watch.reset(); int aggregates = IndicesCoarsener ::coarsen(*info, *(std::get<1>(graphs)), visitedMap, *aggregatesMap, *infoLevel, noAggregates); GraphCreator::free(graphs); if(criterion.debugLevel()>2) { if(rank==0) std::cout<<"Coarsening of index sets took "<buildGlobalLookup(aggregates); AggregatesPublisher::publish(*aggregatesMap, *info, infoLevel->globalLookup()); if(criterion.debugLevel()>2) { if(rank==0) std::cout<<"Communicating global aggregate numbers took "<& visited=excluded; typedef std::vector::iterator Iterator; typedef IteratorPropertyMap VisitedMap2; Iterator end = visited.end(); for(Iterator iter= visited.begin(); iter != end; ++iter) *iter=false; VisitedMap2 visitedMap2(visited.begin(), Dune::IdentityMap()); typename MatrixOperator::matrix_type* coarseMatrix; coarseMatrix = productBuilder.build(*(std::get<0>(graphs)), visitedMap2, *info, *aggregatesMap, aggregates, OverlapFlags()); dverb<<"Building of sparsity pattern took "<freeGlobalLookup(); delete std::get<0>(graphs); productBuilder.calculate(matrix->getmat(), *aggregatesMap, *coarseMatrix, *infoLevel, OverlapFlags()); if(criterion.debugLevel()>2) { if(rank==0) std::cout<<"Calculation entries of Galerkin product took "<communicator().sum(nonzeros); MatrixArgs args(*coarseMatrix, *infoLevel); matrices_.addCoarser(args); redistributes_.push_back(RedistributeInfoType()); } // end level loop infoLevel->freeGlobalLookup(); built_=true; AggregatesMap* aggregatesMap=new AggregatesMap(0); aggregatesMaps_.push_back(aggregatesMap); if(criterion.debugLevel()>0) { if(level==criterion.maxLevel()) { BIGINT unknownsLevel = mlevel->getmat().N(); unknownsLevel = infoLevel->communicator().sum(unknownsLevel); double dunknownsLevel = unknownsLevel.todouble(); if(rank==0 && criterion.debugLevel()>1) { std::cout<<"Level "<communicator().size() <<" unknowns per proc (procs="<communicator().size()<<")"<communicator().size()>1) { #if HAVE_MPI && !HAVE_PARMETIS if(criterion.accumulate()==successiveAccu && infoLevel->communicator().rank()==0) std::cerr<<"Successive accumulation of data on coarse levels only works with ParMETIS installed." <<" Fell back to accumulation to one domain on coarsest level"<getmat(), *redistMat, *infoLevel, redistComm, redistributes_.back(), nodomains,criterion); MatrixArgs args(*redistMat, *redistComm); BIGINT unknownsRedist = redistMat->N(); unknownsRedist = infoLevel->communicator().sum(unknownsRedist); if(redistComm->communicator().rank()==0 && criterion.debugLevel()>1) { double dunknownsRedist = unknownsRedist.todouble(); std::cout<<"Level "<communicator().size() <<" unknowns per proc (procs="<communicator().size()<<")"<::construct(args)); infoLevel.addRedistributed(redistComm); infoLevel->freeGlobalLookup(); } int levels = matrices_.levels(); maxlevels_ = parallelInformation_.finest()->communicator().max(levels); assert(matrices_.levels()==redistributes_.size()); if(hasCoarsest() && rank==0 && criterion.debugLevel()>1) std::cout<<"operator complexity: "< const typename MatrixHierarchy::ParallelMatrixHierarchy& MatrixHierarchy::matrices() const { return matrices_; } template const typename MatrixHierarchy::ParallelInformationHierarchy& MatrixHierarchy::parallelInformation() const { return parallelInformation_; } template void MatrixHierarchy::getCoarsestAggregatesOnFinest(std::vector& data) const { int levels=aggregatesMaps().size(); int maxlevels=parallelInformation_.finest()->communicator().max(levels); std::size_t size=(*(aggregatesMaps().begin()))->noVertices(); // We need an auxiliary vector for the consecutive prolongation. std::vector tmp; std::vector *coarse, *fine; // make sure the allocated space suffices. tmp.reserve(size); data.reserve(size); // Correctly assign coarse and fine for the first prolongation such that // we end up in data in the end. if(levels%2==0) { coarse=&tmp; fine=&data; }else{ coarse=&data; fine=&tmp; } // Number the unknowns on the coarsest level consecutively for each process. if(levels==maxlevels) { const AggregatesMap& map = *(*(++aggregatesMaps().rbegin())); std::size_t m=0; for(typename AggregatesMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) if(*iter< AggregatesMap::ISOLATED) m=std::max(*iter,m); coarse->resize(m+1); std::size_t i=0; srand((unsigned)std::clock()); std::set used; for(typename std::vector::iterator iter=coarse->begin(); iter != coarse->end(); ++iter, ++i) { std::pair::iterator,bool> ibpair = used.insert(static_cast((((double)rand())/(RAND_MAX+1.0)))*coarse->size()); while(!ibpair.second) ibpair = used.insert(static_cast((((double)rand())/(RAND_MAX+1.0))*coarse->size())); *iter=*(ibpair.first); } } typename ParallelInformationHierarchy::Iterator pinfo = parallelInformation().coarsest(); --pinfo; // Now consecutively project the numbers to the finest level. for(typename AggregatesMapList::const_reverse_iterator aggregates=++aggregatesMaps().rbegin(); aggregates != aggregatesMaps().rend(); ++aggregates,--levels) { fine->resize((*aggregates)->noVertices()); fine->assign(fine->size(), 0); Transfer, ParallelInformation> ::prolongateVector(*(*aggregates), *coarse, *fine, static_cast(1), *pinfo); --pinfo; std::swap(coarse, fine); } // Assertion to check that we really projected to data on the last step. assert(coarse==&data); } template const typename MatrixHierarchy::AggregatesMapList& MatrixHierarchy::aggregatesMaps() const { return aggregatesMaps_; } template const typename MatrixHierarchy::RedistributeInfoList& MatrixHierarchy::redistributeInformation() const { return redistributes_; } template MatrixHierarchy::~MatrixHierarchy() { typedef typename AggregatesMapList::reverse_iterator AggregatesMapIterator; typedef typename ParallelMatrixHierarchy::Iterator Iterator; typedef typename ParallelInformationHierarchy::Iterator InfoIterator; AggregatesMapIterator amap = aggregatesMaps_.rbegin(); InfoIterator info = parallelInformation_.coarsest(); for(Iterator level=matrices_.coarsest(), finest=matrices_.finest(); level != finest; --level, --info, ++amap) { (*amap)->free(); delete *amap; delete &level->getmat(); if(level.isRedistributed()) delete &(level.getRedistributed().getmat()); } delete *amap; } template template void MatrixHierarchy::coarsenVector(Hierarchy >& hierarchy) const { assert(hierarchy.levels()==1); typedef typename ParallelMatrixHierarchy::ConstIterator Iterator; typedef typename RedistributeInfoList::const_iterator RIter; RIter redist = redistributes_.begin(); Iterator matrix = matrices_.finest(), coarsest = matrices_.coarsest(); int level=0; if(redist->isSetup()) hierarchy.addRedistributedOnCoarsest(matrix.getRedistributed().getmat().N()); Dune::dvverb<<"Level "<getmat().N()<<" unknowns!"<getmat().N()<<" unknowns!"<getmat().N()); if(redist->isSetup()) hierarchy.addRedistributedOnCoarsest(matrix.getRedistributed().getmat().N()); } } template template void MatrixHierarchy::coarsenSmoother(Hierarchy& smoothers, const typename SmootherTraits::Arguments& sargs) const { assert(smoothers.levels()==0); typedef typename ParallelMatrixHierarchy::ConstIterator MatrixIterator; typedef typename ParallelInformationHierarchy::ConstIterator PinfoIterator; typedef typename AggregatesMapList::const_iterator AggregatesIterator; typename ConstructionTraits::Arguments cargs; cargs.setArgs(sargs); PinfoIterator pinfo = parallelInformation_.finest(); AggregatesIterator aggregates = aggregatesMaps_.begin(); int level=0; for(MatrixIterator matrix = matrices_.finest(), coarsest = matrices_.coarsest(); matrix != coarsest; ++matrix, ++pinfo, ++aggregates, ++level) { cargs.setMatrix(matrix->getmat(), **aggregates); cargs.setComm(*pinfo); smoothers.addCoarser(cargs); } if(maxlevels()>levels()) { // This is not the globally coarsest level and therefore smoothing is needed cargs.setMatrix(matrices_.coarsest()->getmat(), **aggregates); cargs.setComm(*pinfo); smoothers.addCoarser(cargs); ++level; } } template template void MatrixHierarchy::recalculateGalerkin(const F& copyFlags) { typedef typename AggregatesMapList::iterator AggregatesMapIterator; typedef typename ParallelMatrixHierarchy::Iterator Iterator; typedef typename ParallelInformationHierarchy::Iterator InfoIterator; AggregatesMapIterator amap = aggregatesMaps_.begin(); BaseGalerkinProduct productBuilder; InfoIterator info = parallelInformation_.finest(); typename RedistributeInfoList::iterator riIter = redistributes_.begin(); Iterator level = matrices_.finest(), coarsest=matrices_.coarsest(); if(level.isRedistributed()) { info->buildGlobalLookup(level->getmat().N()); redistributeMatrixEntries(const_cast(level->getmat()), const_cast(level.getRedistributed().getmat()), *info,info.getRedistributed(), *riIter); info->freeGlobalLookup(); } for(; level!=coarsest; ++amap) { const Matrix& fine = (level.isRedistributed() ? level.getRedistributed() : *level).getmat(); ++level; ++info; ++riIter; productBuilder.calculate(fine, *(*amap), const_cast(level->getmat()), *info, copyFlags); if(level.isRedistributed()) { info->buildGlobalLookup(level->getmat().N()); redistributeMatrixEntries(const_cast(level->getmat()), const_cast(level.getRedistributed().getmat()), *info, info.getRedistributed(), *riIter); info->freeGlobalLookup(); } } } template std::size_t MatrixHierarchy::levels() const { return matrices_.levels(); } template std::size_t MatrixHierarchy::maxlevels() const { return maxlevels_; } template bool MatrixHierarchy::hasCoarsest() const { return levels()==maxlevels() && (!matrices_.coarsest().isRedistributed() ||matrices_.coarsest()->getmat().N()>0); } template bool MatrixHierarchy::isBuilt() const { return built_; } template Hierarchy::Hierarchy() : finest_(0), coarsest_(0), nonAllocated_(0), allocator_(), levels_(0) {} template Hierarchy::Hierarchy(MemberType& first) : allocator_() { finest_ = allocator_.allocate(1,0); finest_->element_ = &first; finest_->redistributed_ = nullptr; nonAllocated_ = finest_; coarsest_ = finest_; coarsest_->coarser_ = coarsest_->finer_ = nullptr; levels_ = 1; } template Hierarchy::Hierarchy(MemberType* first) : allocator_() { finest_ = allocator_.allocate(1,0); finest_->element_ = first; finest_->redistributed_ = nullptr; nonAllocated_ = nullptr; coarsest_ = finest_; coarsest_->coarser_ = coarsest_->finer_ = nullptr; levels_ = 1; } template Hierarchy::~Hierarchy() { while(coarsest_) { Element* current = coarsest_; coarsest_ = coarsest_->finer_; if(current != nonAllocated_) { if(current->redistributed_) ConstructionTraits::deconstruct(current->redistributed_); ConstructionTraits::deconstruct(current->element_); } allocator_.deallocate(current, 1); current=nullptr; //coarsest_->coarser_ = nullptr; } } template Hierarchy::Hierarchy(const Hierarchy& other) : nonAllocated_(), allocator_(other.allocator_), levels_(other.levels_) { if(!other.finest_) { finest_=coarsest_=nonAllocated_=nullptr; return; } finest_=allocator_.allocate(1,0); Element* finer_ = nullptr; Element* current_ = finest_; Element* otherCurrent_ = other.finest_; while(otherCurrent_) { T* t=new T(*(otherCurrent_->element_)); current_->element_=t; current_->finer_=finer_; if(otherCurrent_->redistributed_) current_->redistributed_ = new T(*otherCurrent_->redistributed_); else current_->redistributed_= nullptr; finer_=current_; if(otherCurrent_->coarser_) { current_->coarser_=allocator_.allocate(1,0); current_=current_->coarser_; }else current_->coarser_=nullptr; otherCurrent_=otherCurrent_->coarser_; } coarsest_=current_; } template std::size_t Hierarchy::levels() const { return levels_; } template void Hierarchy::addRedistributedOnCoarsest(Arguments& args) { coarsest_->redistributed_ = ConstructionTraits::construct(args); } template void Hierarchy::addCoarser(Arguments& args) { if(!coarsest_) { assert(!finest_); coarsest_ = allocator_.allocate(1,0); coarsest_->element_ = ConstructionTraits::construct(args); finest_ = coarsest_; coarsest_->finer_ = nullptr; }else{ coarsest_->coarser_ = allocator_.allocate(1,0); coarsest_->coarser_->finer_ = coarsest_; coarsest_ = coarsest_->coarser_; coarsest_->element_ = ConstructionTraits::construct(args); } coarsest_->redistributed_ = nullptr; coarsest_->coarser_=nullptr; ++levels_; } template void Hierarchy::addFiner(Arguments& args) { if(!finest_) { assert(!coarsest_); finest_ = allocator_.allocate(1,0); finest_->element = ConstructionTraits::construct(args); coarsest_ = finest_; coarsest_->coarser_ = coarsest_->finer_ = nullptr; }else{ finest_->finer_ = allocator_.allocate(1,0); finest_->finer_->coarser_ = finest_; finest_ = finest_->finer_; finest_->finer = nullptr; finest_->element = ConstructionTraits::construct(args); } ++levels_; } template typename Hierarchy::Iterator Hierarchy::finest() { return Iterator(finest_); } template typename Hierarchy::Iterator Hierarchy::coarsest() { return Iterator(coarsest_); } template typename Hierarchy::ConstIterator Hierarchy::finest() const { return ConstIterator(finest_); } template typename Hierarchy::ConstIterator Hierarchy::coarsest() const { return ConstIterator(coarsest_); } /** @} */ } // namespace Amg } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/indicescoarsener.hh000066400000000000000000000362421313314427100222650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_INDICESCOARSENER_HH #define DUNE_AMG_INDICESCOARSENER_HH #include #include #include #include "renumberer.hh" #if HAVE_MPI #include #endif #include "pinfo.hh" namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides a class for building the index set * and remote indices on the coarse level. */ template class IndicesCoarsener {}; #if HAVE_MPI template class ParallelIndicesCoarsener { public: /** * @brief The set of excluded attributes */ typedef E ExcludedAttributes; /** * @brief The type of the parallel information. */ typedef T ParallelInformation; typedef typename ParallelInformation::ParallelIndexSet ParallelIndexSet; /** * @brief The type of the global index. */ typedef typename ParallelIndexSet::GlobalIndex GlobalIndex; /** * @brief The type of the local index. */ typedef typename ParallelIndexSet::LocalIndex LocalIndex; /** * @brief The type of the attribute. */ typedef typename LocalIndex::Attribute Attribute; /** * @brief The type of the remote indices. */ typedef Dune::RemoteIndices RemoteIndices; /** * @brief Build the coarse index set after the aggregatio. * * @param fineInfo The parallel information at the fine level. * @param fineGraph The graph of the fine lecel, * @param visitedMap Map for marking vertices as visited. * @param aggregates The mapping of unknowns onto aggregates. * @param coarseInfo The information about the parallel data decomposition * on the coarse level. * @return The number of unknowns on the coarse level. */ template static typename Graph::VertexDescriptor coarsen(ParallelInformation& fineInfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, ParallelInformation& coarseInfo, typename Graph::VertexDescriptor noAggregates); private: template class ParallelAggregateRenumberer : public AggregateRenumberer { typedef typename G::VertexDescriptor Vertex; typedef I GlobalLookupIndexSet; typedef typename GlobalLookupIndexSet::IndexPair IndexPair; typedef typename IndexPair::GlobalIndex GlobalIndex; public: ParallelAggregateRenumberer(AggregatesMap& aggregates, const I& lookup) : AggregateRenumberer(aggregates), isPublic_(false), lookup_(lookup), globalIndex_(std::numeric_limits::max()) {} void operator()(const typename G::ConstEdgeIterator& edge) { AggregateRenumberer::operator()(edge); const IndexPair* pair= lookup_.pair(edge.target()); if(pair!=0) { globalIndex(pair->global()); attribute(pair->local().attribute()); isPublic(pair->local().isPublic()); } } Vertex operator()(const GlobalIndex& global) { DUNE_UNUSED_PARAMETER(global); Vertex current = this->number_; this->operator++(); return current; } bool isPublic() { return isPublic_; } void isPublic(bool b) { isPublic_ = isPublic_ || b; } void reset() { globalIndex_ = std::numeric_limits::max(); isPublic_=false; } void attribute(const Attribute& attribute) { attribute_=attribute; } Attribute attribute() { return attribute_; } const GlobalIndex& globalIndex() const { return globalIndex_; } void globalIndex(const GlobalIndex& global) { globalIndex_ = global; } private: bool isPublic_; Attribute attribute_; const GlobalLookupIndexSet& lookup_; GlobalIndex globalIndex_; }; template static void buildCoarseIndexSet(const ParallelInformation& pinfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, ParallelIndexSet& coarseIndices, ParallelAggregateRenumberer& renumberer); template static void buildCoarseRemoteIndices(const RemoteIndices& fineRemote, const AggregatesMap& aggregates, ParallelIndexSet& coarseIndices, RemoteIndices& coarseRemote, ParallelAggregateRenumberer& renumberer); }; /** * @brief Coarsen Indices in the parallel case. */ template class IndicesCoarsener,E> : public ParallelIndicesCoarsener,E> {}; #endif /** * @brief Coarsen Indices in the sequential case. * * Nothing to be coarsened here. Just renumber the aggregates * consecutively */ template class IndicesCoarsener { public: template static typename Graph::VertexDescriptor coarsen(const SequentialInformation & fineInfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, SequentialInformation& coarseInfo, typename Graph::VertexDescriptor noAggregates); }; #if HAVE_MPI template template inline typename Graph::VertexDescriptor ParallelIndicesCoarsener::coarsen(ParallelInformation& fineInfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, ParallelInformation& coarseInfo, typename Graph::VertexDescriptor noAggregates) { DUNE_UNUSED_PARAMETER(noAggregates); ParallelAggregateRenumberer renumberer(aggregates, fineInfo.globalLookup()); buildCoarseIndexSet(fineInfo, fineGraph, visitedMap, aggregates, coarseInfo.indexSet(), renumberer); buildCoarseRemoteIndices(fineInfo.remoteIndices(), aggregates, coarseInfo.indexSet(), coarseInfo.remoteIndices(), renumberer); return renumberer; } template template void ParallelIndicesCoarsener::buildCoarseIndexSet(const ParallelInformation& pinfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, ParallelIndexSet& coarseIndices, ParallelAggregateRenumberer& renumberer) { // fineGraph is the local subgraph corresponding to the vertices the process owns. // i.e. no overlap/copy vertices can be visited traversing the graph typedef typename Graph::ConstVertexIterator Iterator; typedef typename ParallelInformation::GlobalLookupIndexSet GlobalLookupIndexSet; Iterator end = fineGraph.end(); const GlobalLookupIndexSet& lookup = pinfo.globalLookup(); coarseIndices.beginResize(); // Setup the coarse index set and renumber the aggregate consecutively // ascending from zero according to the minimum global index belonging // to the aggregate for(Iterator index = fineGraph.begin(); index != end; ++index) { if(aggregates[*index]!=AggregatesMap::ISOLATED) // Isolated vertices will not be represented on the next level. // These should only be there if skipIsolated is activiated in // the coarsening criterion as otherwise they will be aggregated // and should have real aggregate number in the map right now. if(!get(visitedMap, *index)) { // This vertex was not visited by breadthFirstSearch yet. typedef typename GlobalLookupIndexSet::IndexPair IndexPair; const IndexPair* pair= lookup.pair(*index); renumberer.reset(); // reset attribute and global index. if(pair!=0) { // vertex is in the index set. Note that not all vertices have // to be in the index set, just the ones where communication // will happen. assert(!ExcludedAttributes::contains(pair->local().attribute())); renumberer.attribute(pair->local().attribute()); renumberer.isPublic(pair->local().isPublic()); renumberer.globalIndex(pair->global()); } // Reconstruct aggregate and mark vertices as visited aggregates.template breadthFirstSearch(*index, aggregates[*index], fineGraph, renumberer, visitedMap); typedef typename GlobalLookupIndexSet::IndexPair::GlobalIndex GlobalIndex; if(renumberer.globalIndex()!=std::numeric_limits::max()) { // vertex is in the index set. //std::cout <<" Adding global="<< renumberer.globalIndex()<<" local="<(renumberer)<(renumberer) >= coarseIndices.size()); // Reset the visited flags for(Iterator vertex=fineGraph.begin(); vertex != end; ++vertex) put(visitedMap, *vertex, false); } template template void ParallelIndicesCoarsener::buildCoarseRemoteIndices(const RemoteIndices& fineRemote, const AggregatesMap& aggregates, ParallelIndexSet& coarseIndices, RemoteIndices& coarseRemote, ParallelAggregateRenumberer& renumberer) { std::vector attributes(static_cast(renumberer)); GlobalLookupIndexSet coarseLookup(coarseIndices, static_cast(renumberer)); typedef typename RemoteIndices::const_iterator Iterator; Iterator end = fineRemote.end(); for(Iterator neighbour = fineRemote.begin(); neighbour != end; ++neighbour) { int process = neighbour->first; assert(neighbour->second.first==neighbour->second.second); // Mark all as not known typedef typename std::vector::iterator CIterator; for(CIterator iter=attributes.begin(); iter!= attributes.end(); ++iter) *iter = std::numeric_limits::max(); typedef typename RemoteIndices::RemoteIndexList::const_iterator Iterator; Iterator riEnd = neighbour->second.second->end(); for(Iterator index = neighbour->second.second->begin(); index != riEnd; ++index) { if(!E::contains(index->localIndexPair().local().attribute()) && aggregates[index->localIndexPair().local()] != AggregatesMap::ISOLATED) { assert(aggregates[index->localIndexPair().local()]localIndexPair().local()]] != 3) attributes[aggregates[index->localIndexPair().local()]] = index->attribute(); } } // Build remote index list typedef RemoteIndexListModifier Modifier; typedef typename RemoteIndices::RemoteIndex RemoteIndex; typedef typename ParallelIndexSet::const_iterator IndexIterator; Modifier coarseList = coarseRemote.template getModifier(process); IndexIterator iend = coarseIndices.end(); for(IndexIterator index = coarseIndices.begin(); index != iend; ++index) if(attributes[index->local()] != std::numeric_limits::max()) { // remote index is present coarseList.insert(RemoteIndex(Attribute(attributes[index->local()]), &(*index))); } //std::cout< syncer(coarseIndices, coarseRemote); syncer.sync(renumberer); } #endif template template typename Graph::VertexDescriptor IndicesCoarsener::coarsen(const SequentialInformation& fineInfo, Graph& fineGraph, VM& visitedMap, AggregatesMap& aggregates, SequentialInformation& coarseInfo, typename Graph::VertexDescriptor noAggregates) { DUNE_UNUSED_PARAMETER(fineInfo); DUNE_UNUSED_PARAMETER(fineGraph); DUNE_UNUSED_PARAMETER(visitedMap); DUNE_UNUSED_PARAMETER(aggregates); DUNE_UNUSED_PARAMETER(coarseInfo); DUNE_UNUSED_PARAMETER(noAggregates); return noAggregates; } } //namespace Amg } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/kamg.hh000066400000000000000000000375731313314427100176740ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_KAMG_HH #define DUNE_AMG_KAMG_HH #include #include "amg.hh" namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * @{ */ /** @file * @author Markus Blatt * @brief Provides an algebraic multigrid using a Krylov cycle. * */ /** * @brief Two grid operator for AMG with Krylov cycle. * @tparam AMG The type of the underlying agglomeration AMG. */ template class KAmgTwoGrid : public Preconditioner { /** @brief The type of the domain. */ typedef typename AMG::Domain Domain; /** @brief the type of the range. */ typedef typename AMG::Range Range; public: enum { /** @brief The solver category. */ category = AMG::category }; /** * @brief Constructor. * @param amg The underlying amg. It is used as the storage for the hierarchic * data structures. * @param coarseSolver The solver used for the coarse grid correction. */ KAmgTwoGrid(AMG& amg, std::shared_ptr > coarseSolver) : amg_(amg), coarseSolver_(coarseSolver) {} /** \copydoc Preconditioner::pre(X&,Y&) */ void pre(typename AMG::Domain& x, typename AMG::Range& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /** \copydoc Preconditioner::post(X&) */ void post(typename AMG::Domain& x) { DUNE_UNUSED_PARAMETER(x); } /** \copydoc Preconditioner::apply(X&,const Y&) */ void apply(typename AMG::Domain& v, const typename AMG::Range& d) { // Copy data *levelContext_->update=0; *levelContext_->rhs = d; *levelContext_->lhs = v; presmooth(*levelContext_, amg_.preSteps_); bool processFineLevel = amg_.moveToCoarseLevel(*levelContext_); if(processFineLevel) { typename AMG::Range b=*levelContext_->rhs; typename AMG::Domain x=*levelContext_->update; InverseOperatorResult res; coarseSolver_->apply(x, b, res); *levelContext_->update=x; } amg_.moveToFineLevel(*levelContext_, processFineLevel); postsmooth(*levelContext_, amg_.postSteps_); v=*levelContext_->update; } /** * @brief Get a pointer to the coarse grid solver. * @return The coarse grid solver. */ InverseOperator* coarseSolver() { return coarseSolver_; } /** * @brief Set the level context pointer. * @param p The pointer to set it to. */ void setLevelContext(std::shared_ptr p) { levelContext_=p; } /** @brief Destructor. */ ~KAmgTwoGrid() {} private: /** @brief Underlying AMG used as storage and engine. */ AMG& amg_; /** @brief The coarse grid solver.*/ std::shared_ptr > coarseSolver_; /** @brief A shared pointer to the level context of AMG. */ std::shared_ptr levelContext_; }; /** * @brief an algebraic multigrid method using a Krylov-cycle. * * The implementation is based on the paper * [[Notay and Vassilevski, 2007]](http://onlinelibrary.wiley.com/doi/10.1002/nla.542/abstract) * * @tparam M The type of the linear operator. * @tparam X The type of the range and domain. * @tparam PI The parallel information object. Use SequentialInformation (default) * for a sequential AMG, OwnerOverlapCopyCommunication for the parallel case. * @tparam K The type of the Krylov method to use for the cycle. * @tparam A The type of the allocator to use. */ template, class A=std::allocator > class KAMG : public Preconditioner { public: /** @brief The type of the underlying AMG. */ typedef AMG Amg; /** @brief The type of the Krylov solver for the cycle. */ typedef K KrylovSolver; /** @brief The type of the hierarchy of operators. */ typedef typename Amg::OperatorHierarchy OperatorHierarchy; /** @brief The type of the coarse solver. */ typedef typename Amg::CoarseSolver CoarseSolver; /** @brief the type of the parallelinformation to use.*/ typedef typename Amg::ParallelInformation ParallelInformation; /** @brief The type of the arguments for construction of the smoothers. */ typedef typename Amg::SmootherArgs SmootherArgs; /** @brief the type of the lineatr operator. */ typedef typename Amg::Operator Operator; /** @brief the type of the domain. */ typedef typename Amg::Domain Domain; /** @brief The type of the range. */ typedef typename Amg::Range Range; /** @brief The type of the hierarchy of parallel information. */ typedef typename Amg::ParallelInformationHierarchy ParallelInformationHierarchy; /** @brief The type of the scalar product. */ typedef typename Amg::ScalarProduct ScalarProduct; enum { /** @brief The solver category. */ category = Amg::category }; /** * @brief Construct a new amg with a specific coarse solver. * @param matrices The already set up matix hierarchy. * @param coarseSolver The set up solver to use on the coarse * grid, must match the sparse matrix in the matrix hierarchy. * @param smootherArgs The arguments needed for thesmoother to use * for pre and post smoothing * @param gamma The number of subcycles. 1 for V-cycle, 2 for W-cycle. * @param preSmoothingSteps The number of smoothing steps for premoothing. * @param postSmoothingSteps The number of smoothing steps for postmoothing. * @param maxLevelKrylovSteps The maximum number of Krylov steps allowed at each level. * @param minDefectReduction The minimal defect reduction to achieve on each Krylov level. */ KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, std::size_t gamma, std::size_t preSmoothingSteps=1, std::size_t postSmoothingSteps=1, std::size_t maxLevelKrylovSteps=3, double minDefectReduction=1e-1) DUNE_DEPRECATED; /** * @brief Construct a new amg with a specific coarse solver. * @param matrices The already set up matix hierarchy. * @param coarseSolver The set up solver to use on the coarse * grid, must match the coarse matrix in the matrix hierarchy. * @param smootherArgs The arguments needed for thesmoother to use * for pre and post smoothing. * @param parms The parameters for the AMG. * @param maxLevelKrylovSteps maximum of krylov iterations on a particular level (default=3) * @param minDefectReduction minimal defect reduction during the krylov iterations on a particular level (default=1e-1) */ KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, const Parameters& parms, std::size_t maxLevelKrylovSteps=3, double minDefectReduction=1e-1); /** * @brief Construct an AMG with an inexact coarse solver based on the smoother. * * As coarse solver a preconditioned CG method with the smoother as preconditioner * will be used. The matrix hierarchy is built automatically. * @param fineOperator The operator on the fine level. * @param criterion The criterion describing the coarsening strategy. E. g. SymmetricCriterion * or UnsymmetricCriterion. * @param smootherArgs The arguments for constructing the smoothers. * @param gamma 1 for V-cycle, 2 for W-cycle * @param preSmoothingSteps The number of smoothing steps for premoothing. * @param postSmoothingSteps The number of smoothing steps for postmoothing. * @param maxLevelKrylovSteps The maximum number of Krylov steps allowed at each level. * @param minDefectReduction The defect reduction to achieve on each krylov level. * @param pinfo The information about the parallel distribution of the data. * @deprecated Use * KAMG(const Operator&, const C&, const SmootherArgs, const ParallelInformation) * instead. * All parameters can be set in the criterion! */ template KAMG(const Operator& fineOperator, const C& criterion, const SmootherArgs& smootherArgs, std::size_t gamma, std::size_t preSmoothingSteps=1, std::size_t postSmoothingSteps=1, std::size_t maxLevelKrylovSteps=3, double minDefectReduction=1e-1, const ParallelInformation& pinfo=ParallelInformation()) DUNE_DEPRECATED; /** * @brief Construct an AMG with an inexact coarse solver based on the smoother. * * As coarse solver a preconditioned CG method with the smoother as preconditioner * will be used. The matrix hierarchy is built automatically. * @param fineOperator The operator on the fine level. * @param criterion The criterion describing the coarsening strategy. E. g. SymmetricCriterion * or UnsymmetricCriterion, and providing the parameters. * @param smootherArgs The arguments for constructing the smoothers. * @param maxLevelKrylovSteps maximum of krylov iterations on a particular level (default=3) * @param minDefectReduction minimal defect reduction during the krylov iterations on a particular level (default=1e-1) * @param pinfo The information about the parallel distribution of the data. */ template KAMG(const Operator& fineOperator, const C& criterion, const SmootherArgs& smootherArgs=SmootherArgs(), std::size_t maxLevelKrylovSteps=3, double minDefectReduction=1e-1, const ParallelInformation& pinfo=ParallelInformation()); /** \copydoc Preconditioner::pre(X&,Y&) */ void pre(Domain& x, Range& b); /** \copydoc Preconditioner::post(X&) */ void post(Domain& x); /** \copydoc Preconditioner::apply(X&,const Y&) */ void apply(Domain& v, const Range& d); std::size_t maxlevels(); private: /** @brief The underlying amg. */ Amg amg; /** \brief The maximum number of Krylov steps allowed at each level. */ std::size_t maxLevelKrylovSteps; /** \brief The defect reduction to achieve on each krylov level. */ double levelDefectReduction; /** @brief pointers to the allocated scalar products. */ std::vector > scalarproducts; /** @brief pointers to the allocated krylov solvers. */ std::vector > > ksolvers; }; template KAMG::KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, std::size_t gamma, std::size_t preSmoothingSteps, std::size_t postSmoothingSteps, std::size_t ksteps, double reduction) : amg(matrices, coarseSolver, smootherArgs, gamma, preSmoothingSteps, postSmoothingSteps), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction) {} template KAMG::KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, const SmootherArgs& smootherArgs, const Parameters& params, std::size_t ksteps, double reduction) : amg(matrices, coarseSolver, smootherArgs, params), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction) {} template template KAMG::KAMG(const Operator& fineOperator, const C& criterion, const SmootherArgs& smootherArgs, std::size_t gamma, std::size_t preSmoothingSteps, std::size_t postSmoothingSteps, std::size_t ksteps, double reduction, const ParallelInformation& pinfo) : amg(fineOperator, criterion, smootherArgs, gamma, preSmoothingSteps, postSmoothingSteps, false, pinfo), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction) {} template template KAMG::KAMG(const Operator& fineOperator, const C& criterion, const SmootherArgs& smootherArgs, std::size_t ksteps, double reduction, const ParallelInformation& pinfo) : amg(fineOperator, criterion, smootherArgs, pinfo), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction) {} template void KAMG::pre(Domain& x, Range& b) { amg.pre(x,b); scalarproducts.reserve(amg.levels()); ksolvers.reserve(amg.levels()); typename OperatorHierarchy::ParallelMatrixHierarchy::Iterator matrix = amg.matrices_->matrices().coarsest(); typename ParallelInformationHierarchy::Iterator pinfo = amg.matrices_->parallelInformation().coarsest(); bool hasCoarsest=(amg.levels()==amg.maxlevels()); if(hasCoarsest) { if(matrix==amg.matrices_->matrices().finest()) return; --matrix; --pinfo; ksolvers.push_back(std::shared_ptr >(new KAmgTwoGrid(amg, amg.solver_))); }else ksolvers.push_back(std::shared_ptr >(new KAmgTwoGrid(amg, std::shared_ptr >()))); std::ostringstream s; if(matrix!=amg.matrices_->matrices().finest()) while(true) { scalarproducts.push_back(std::shared_ptr(Amg::ScalarProductChooser::construct(*pinfo))); std::shared_ptr > ks = std::shared_ptr >(new KrylovSolver(*matrix, *(scalarproducts.back()), *(ksolvers.back()), levelDefectReduction, maxLevelKrylovSteps, 0)); ksolvers.push_back(std::shared_ptr >(new KAmgTwoGrid(amg, ks))); --matrix; --pinfo; if(matrix==amg.matrices_->matrices().finest()) break; } } template void KAMG::post(Domain& x) { amg.post(x); } template void KAMG::apply(Domain& v, const Range& d) { if(ksolvers.size()==0) { Range td=d; InverseOperatorResult res; amg.solver_->apply(v,td,res); }else { typedef typename Amg::LevelContext LevelContext; std::shared_ptr levelContext(new LevelContext); amg.initIteratorsWithFineLevel(*levelContext); typedef typename std::vector > >::iterator Iter; for(Iter solver=ksolvers.begin(); solver!=ksolvers.end(); ++solver) (*solver)->setLevelContext(levelContext); ksolvers.back()->apply(v,d); } } template std::size_t KAMG::maxlevels() { return amg.maxlevels(); } /** @}*/ } // Amg } // Dune #endif dune-istl-2.5.1/dune/istl/paamg/parameters.hh000066400000000000000000000346131313314427100211100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_PARAMETERS_HH #define DUNE_AMG_PARAMETERS_HH #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Parameter classes for customizing AMG * * All parameters of the AMG can be set by using the class Parameter, which * can be provided to CoarsenCriterion via its constructor. */ /** * @brief Parameters needed to check whether a node depends on another. */ class DependencyParameters { public: /** @brief Constructor */ DependencyParameters() : alpha_(1.0/3.0), beta_(1.0E-5) {} /** * @brief Set threshold for marking nodes as isolated. * The default value is 1.0E-5. */ void setBeta(double b) { beta_ = b; } /** * @brief Get the threshold for marking nodes as isolated. * The default value is 1.0E-5. * @return beta */ double beta() const { return beta_; } /** * @brief Set the scaling value for marking connections as strong. * Default value is 1/3 */ void setAlpha(double a) { alpha_ = a; } /** * @brief Get the scaling value for marking connections as strong. * Default value is 1/3 */ double alpha() const { return alpha_; } private: double alpha_, beta_; }; /** * @brief Parameters needed for the aggregation process, */ class AggregationParameters : public DependencyParameters { public: /** * @brief Constructor. * * The parameters will be initialized with default values suitable * for 2D isotropic problems. * * If that does not fit your needs either use setDefaultValuesIsotropic * setDefaultValuesAnisotropic or setup the values by hand */ AggregationParameters() : maxDistance_(2), minAggregateSize_(4), maxAggregateSize_(6), connectivity_(15), skipiso_(false) {} /** * @brief Sets reasonable default values for an isotropic problem. * * Reasonable means that we should end up with cube aggregates of * diameter 2. * * @param dim The dimension of the problem. * @param diameter The preferred diameter for the aggregation. */ void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2) { maxDistance_=diameter-1; std::size_t csize=1; for(; dim>0; dim--) { csize*=diameter; maxDistance_+=diameter-1; } minAggregateSize_=csize; maxAggregateSize_=static_cast(csize*1.5); } /** * @brief Sets reasonable default values for an aisotropic problem. * * Reasonable means that we should end up with cube aggregates with * sides of diameter 2 and sides in one dimension that are longer * (e.g. for 3D: 2x2x3). * * @param dim The dimension of the problem. * @param diameter The preferred diameter for the aggregation. */ void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2) { setDefaultValuesIsotropic(dim, diameter); maxDistance_+=dim-1; } /** * @brief Get the maximal distance allowed between to nodes in a aggregate. * * The distance between two nodes in a aggregate is the minimal number of edges * it takes to travel from one node to the other without leaving the aggregate. * @return The maximum distance allowed. */ std::size_t maxDistance() const { return maxDistance_;} /** * @brief Set the maximal distance allowed between to nodes in a aggregate. * * The distance between two nodes in a aggregate is the minimal number of edges * it takes to travel from one node to the other without leaving the aggregate. * The default value is 2. * @param distance The maximum distance allowed. */ void setMaxDistance(std::size_t distance) { maxDistance_ = distance;} /** * @brief Whether isolated aggregates will not be represented on * the coarse level. * @return True if these aggregates will be skipped. */ bool skipIsolated() const { return skipiso_; } /** * @brief Set whether isolated aggregates will not be represented on * the coarse level. * @param skip True if these aggregates will be skipped. */ void setSkipIsolated(bool skip) { skipiso_=skip; } /** * @brief Get the minimum number of nodes a aggregate has to consist of. * @return The minimum number of nodes. */ std::size_t minAggregateSize() const { return minAggregateSize_;} /** * @brief Set the minimum number of nodes a aggregate has to consist of. * * the default value is 4. * @return The minimum number of nodes. */ void setMinAggregateSize(std::size_t size){ minAggregateSize_=size;} /** * @brief Get the maximum number of nodes a aggregate is allowed to have. * @return The maximum number of nodes. */ std::size_t maxAggregateSize() const { return maxAggregateSize_;} /** * @brief Set the maximum number of nodes a aggregate is allowed to have. * * The default values is 6. * @param size The maximum number of nodes. */ void setMaxAggregateSize(std::size_t size){ maxAggregateSize_ = size;} /** * @brief Get the maximum number of connections a aggregate is allowed to have. * * This limit exists to achieve sparsity of the coarse matrix. the default value is 15. * * @return The maximum number of connections a aggregate is allowed to have. */ std::size_t maxConnectivity() const { return connectivity_;} /** * @brief Set the maximum number of connections a aggregate is allowed to have. * * This limit exists to achieve sparsity of the coarse matrix. the default value is 15. * * @param connectivity The maximum number of connections a aggregate is allowed to have. */ void setMaxConnectivity(std::size_t connectivity){ connectivity_ = connectivity;} private: std::size_t maxDistance_, minAggregateSize_, maxAggregateSize_, connectivity_; bool skipiso_; }; /** * @brief Identifiers for the different accumulation modes. */ enum AccumulationMode { /** * @brief No data accumulution. * * The coarse level data will be distributed to all processes. */ noAccu = 0, /** * @brief Accumulate data to on process at once * * Once no further coarsening is possible all data will be accumulated to one process */ atOnceAccu=1, /** * @brief Successively accumulate to fewer processes. */ successiveAccu=2 }; /** * @brief Parameters for the complete coarsening process. */ class CoarseningParameters : public AggregationParameters { public: /** * @brief Set the maximum number of levels allowed in the hierarchy. */ void setMaxLevel(int l) { maxLevel_ = l; } /** * @brief Get the maximum number of levels allowed in the hierarchy. */ int maxLevel() const { return maxLevel_; } /** * @brief Set the maximum number of unknowns allowed on the coarsest level. */ void setCoarsenTarget(int nodes) { coarsenTarget_ = nodes; } /** * @brief Get the maximum number of unknowns allowed on the coarsest level. */ int coarsenTarget() const { return coarsenTarget_; } /** * @brief Set the minimum coarsening rate to be achieved in each coarsening. * * The default value is 1.2 */ void setMinCoarsenRate(double rate) { minCoarsenRate_ = rate; } /** * @brief Get the minimum coarsening rate to be achieved. */ double minCoarsenRate() const { return minCoarsenRate_; } /** * @brief Whether the data should be accumulated on fewer processes on coarser levels. */ AccumulationMode accumulate() const { return accumulate_; } /** * @brief Set whether he data should be accumulated on fewer processes on coarser levels. */ void setAccumulate(AccumulationMode accu) { accumulate_=accu; } void setAccumulate(bool accu){ accumulate_=accu ? successiveAccu : noAccu; } /** * @brief Set the damping factor for the prolongation. * * @param d The new damping factor. */ void setProlongationDampingFactor(double d) { dampingFactor_ = d; } /** * @brief Get the damping factor for the prolongation. * * @return d The damping factor. */ double getProlongationDampingFactor() const { return dampingFactor_; } /** * @brief Constructor * @param maxLevel The maximum number of levels allowed in the matrix hierarchy (default: 100). * @param coarsenTarget If the number of nodes in the matrix is below this threshold the * coarsening will stop (default: 1000). * @param minCoarsenRate If the coarsening rate falls below this threshold the * coarsening will stop (default: 1.2) * @param prolongDamp The damping factor to apply to the prolongated update (default: 1.6) * @param accumulate Whether to accumulate the data onto fewer processors on coarser levels. */ CoarseningParameters(int maxLevel=100, int coarsenTarget=1000, double minCoarsenRate=1.2, double prolongDamp=1.6, AccumulationMode accumulate=successiveAccu) : maxLevel_(maxLevel), coarsenTarget_(coarsenTarget), minCoarsenRate_(minCoarsenRate), dampingFactor_(prolongDamp), accumulate_( accumulate) {} private: /** * @brief The maximum number of levels allowed in the hierarchy. */ int maxLevel_; /** * @brief The maximum number of unknowns allowed on the coarsest level. */ int coarsenTarget_; /** * @brief The minimum coarsening rate to be achieved. */ double minCoarsenRate_; /** * @brief The damping factor to apply to the prologated correction. */ double dampingFactor_; /** * @brief Whether the data should be agglomerated to fewer processor on * coarser levels. */ AccumulationMode accumulate_; }; /** * @brief All parameters for AMG. * * Instances of this class can be provided to CoarsenCriterion via its * constructor. */ class Parameters : public CoarseningParameters { public: /** * @brief Set the debugging level. * * @param level If 0 no debugging output will be generated. * @warning In parallel the level has to be consistent over all procceses. */ void setDebugLevel(int level) { debugLevel_ = level; } /** * @brief Get the debugging Level. * * @return 0 if no debugging output will be generated. */ int debugLevel() const { return debugLevel_; } /** * @brief Set the number of presmoothing steps to apply * @param steps The number of steps: */ void setNoPreSmoothSteps(std::size_t steps) { preSmoothSteps_=steps; } /** * @brief Get the number of presmoothing steps to apply * @return The number of steps: */ std::size_t getNoPreSmoothSteps() const { return preSmoothSteps_; } /** * @brief Set the number of postsmoothing steps to apply * @param steps The number of steps: */ void setNoPostSmoothSteps(std::size_t steps) { postSmoothSteps_=steps; } /** * @brief Get the number of postsmoothing steps to apply * @return The number of steps: */ std::size_t getNoPostSmoothSteps() const { return postSmoothSteps_; } /** * @brief Set the value of gamma; 1 for V-cycle, 2 for W-cycle */ void setGamma(std::size_t gamma) { gamma_=gamma; } /** * @brief Get the value of gamma; 1 for V-cycle, 2 for W-cycle */ std::size_t getGamma() const { return gamma_; } /** * @brief Set whether to use additive multigrid. * @param additive True if multigrid should be additive. */ void setAdditive(bool additive) { additive_=additive; } /** * @brief Get whether to use additive multigrid. * @return True if multigrid should be additive. */ bool getAdditive() const { return additive_; } /** * @brief Constructor * @param maxLevel The maximum number of levels allowed in the matrix hierarchy (default: 100). * @param coarsenTarget If the number of nodes in the matrix is below this threshold the * coarsening will stop (default: 1000). * @param minCoarsenRate If the coarsening rate falls below this threshold the * coarsening will stop (default: 1.2) * @param prolongDamp The damping factor to apply to the prolongated update (default: 1.6) * @param accumulate Whether to accumulate the data onto fewer processors on coarser levels. */ Parameters(int maxLevel=100, int coarsenTarget=1000, double minCoarsenRate=1.2, double prolongDamp=1.6, AccumulationMode accumulate=successiveAccu) : CoarseningParameters(maxLevel, coarsenTarget, minCoarsenRate, prolongDamp, accumulate) , debugLevel_(2), preSmoothSteps_(2), postSmoothSteps_(2), gamma_(1), additive_(false) {} private: int debugLevel_; std::size_t preSmoothSteps_; std::size_t postSmoothSteps_; std::size_t gamma_; bool additive_; }; } //namespace AMG } //namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/pinfo.hh000066400000000000000000000037271313314427100200620ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_PINFO_HH #define DUNE_AMG_PINFO_HH #include #include #if HAVE_MPI #include #include #include #include #include #endif #include namespace Dune { namespace Amg { class SequentialInformation { public: typedef CollectiveCommunication MPICommunicator; typedef EmptySet CopyFlags; typedef AllSet OwnerSet; enum { category = SolverCategory::sequential }; SolverCategory::Category getSolverCategory () const { return SolverCategory::sequential; } MPICommunicator communicator() const { return comm_; } int procs() const { return 1; } template T globalSum(const T& t) const { return t; } typedef int GlobalLookupIndexSet; void buildGlobalLookup(std::size_t){} void freeGlobalLookup(){} const GlobalLookupIndexSet& globalLookup() const { return gli; } template void copyOwnerToAll(V& v, V& v1) const { DUNE_UNUSED_PARAMETER(v); DUNE_UNUSED_PARAMETER(v1); } template void project(V& v) const { DUNE_UNUSED_PARAMETER(v); } template SequentialInformation(const CollectiveCommunication&) {} SequentialInformation() {} SequentialInformation(const SequentialInformation&) {} private: MPICommunicator comm_; GlobalLookupIndexSet gli; }; } // namespace Amg } //namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/properties.hh000066400000000000000000000042171313314427100211360ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_AMG_PROPERTIES_HH #define DUNE_ISTL_AMG_PROPERTIES_HH #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Provides classes for handling internal properties in a graph */ /** * @brief Tag idnetifying the visited property of a vertex. */ struct VertexVisitedTag {}; /** * @brief A property map that extracts one property out of a bundle * using operator[]() * * Using this access class properties can be stored in std::bitset. */ template class RandomAccessBundledPropertyMap : public RAPropertyMapHelper > { public: /** @brief The container that holds the properties */ typedef C Container; /** @brief The reference type of the container. */ typedef R Reference; /** @brief The key of the property map. */ typedef K Key; /** * @brief The category of the property map. */ typedef LvaluePropertyMapTag Category; enum { /** @brief The index of the property in the bundle. */ index = i }; /** * @brief Get the property for a key. * @param key The key. * @return The corresponding property. */ Reference operator[](const Key& key) const { return container_[key][index]; } /** * @brief Constructor. * @param container The container with the property bundle. */ RandomAccessBundledPropertyMap(Container& container) : container_(&container) {} /** @brief The default constructor. */ RandomAccessBundledPropertyMap() : container_(0) {} private: /** @brief The container with property bundles. */ Container* container_; }; } } #endif dune-istl-2.5.1/dune/istl/paamg/renumberer.hh000066400000000000000000000042461313314427100211120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMG_RENUMBERER_HH #define DUNE_AMG_RENUMBERER_HH #include "aggregates.hh" namespace Dune { namespace Amg { template class AggregateRenumberer { public: /** @brief The vertex type */ typedef typename G::VertexDescriptor Vertex; /** * @brief Constructor. * @param aggregates The aggregate map to renumber. */ AggregateRenumberer(AggregatesMap& aggregates); /** @brief Conversion to vertex. */ operator Vertex() const; void operator()(const typename G::ConstEdgeIterator& edge); void operator++(); protected: Vertex number_; AggregatesMap& aggregates_; }; template AggregateRenumberer::AggregateRenumberer(AggregatesMap& aggregates) : number_(0), aggregates_(aggregates) {} template AggregateRenumberer::operator Vertex() const { return number_; } template void AggregateRenumberer::operator()(const typename G::ConstEdgeIterator& edge) { aggregates_[edge.target()]=number_; } template void AggregateRenumberer::operator++() { ++number_; } template void renumberAggregates(const G& graph, I index, I endIndex, V& visitedMap, AggregatesMap& aggregates) { AggregateRenumberer renumberer(aggregates); for(I index1=index; index1 != endIndex; ++index1) if(aggregates[index1.index()]!=AggregatesMap::ISOLATED && !get(visitedMap, index1.index())) { aggregates.template breadthFirstSearch(index1.index(), aggregates[index1.index()], graph, renumberer, visitedMap); aggregates[index1.index()] = renumberer; ++renumberer; } for(; index != endIndex; ++index) put(visitedMap, index.index(), false); } } // namespace AMG } // namespace Dune #endif dune-istl-2.5.1/dune/istl/paamg/smoother.hh000066400000000000000000000636511313314427100206110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMGSMOOTHER_HH #define DUNE_AMGSMOOTHER_HH #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Classes for the generic construction and application * of the smoothers. */ /** * @brief The default class for the smoother arguments. */ template struct DefaultSmootherArgs { /** * @brief The type of the relaxation factor. */ typedef T RelaxationFactor; /** * @brief The numbe of iterations to perform. */ int iterations; /** * @brief The relaxation factor to use. */ RelaxationFactor relaxationFactor; /** * @brief Default constructor. */ DefaultSmootherArgs() : iterations(1), relaxationFactor(1.0) {} }; /** * @brief Traits class for getting the attribute class of a smoother. */ template struct SmootherTraits { typedef DefaultSmootherArgs Arguments; }; template struct SmootherTraits > { typedef DefaultSmootherArgs Arguments; }; template struct SmootherTraits > { typedef DefaultSmootherArgs Arguments; }; /** * @brief Construction Arguments for the default smoothers */ template class DefaultConstructionArgs { typedef typename T::matrix_type Matrix; typedef typename SmootherTraits::Arguments SmootherArgs; typedef Dune::Amg::AggregatesMap::VertexDescriptor> AggregatesMap; public: virtual ~DefaultConstructionArgs() {} void setMatrix(const Matrix& matrix) { matrix_=&matrix; } virtual void setMatrix(const Matrix& matrix, const AggregatesMap& amap) { DUNE_UNUSED_PARAMETER(amap); setMatrix(matrix); } const Matrix& getMatrix() const { return *matrix_; } void setArgs(const SmootherArgs& args) { args_=&args; } template void setComm(T1& comm) { DUNE_UNUSED_PARAMETER(comm); } const SequentialInformation& getComm() { return comm_; } const SmootherArgs getArgs() const { return *args_; } protected: const Matrix* matrix_; private: const SmootherArgs* args_; SequentialInformation comm_; }; template struct ConstructionArgs : public DefaultConstructionArgs {}; template class DefaultParallelConstructionArgs : public ConstructionArgs { public: virtual ~DefaultParallelConstructionArgs() {} void setComm(const C& comm) { comm_ = &comm; } const C& getComm() const { return *comm_; } private: const C* comm_; }; template class ConstructionTraits; /** * @brief Policy for the construction of the SeqSSOR smoother */ template struct ConstructionTraits > { typedef DefaultConstructionArgs > Arguments; static inline SeqSSOR* construct(Arguments& args) { return new SeqSSOR(args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor); } static inline void deconstruct(SeqSSOR* ssor) { delete ssor; } }; /** * @brief Policy for the construction of the SeqSOR smoother */ template struct ConstructionTraits > { typedef DefaultConstructionArgs > Arguments; static inline SeqSOR* construct(Arguments& args) { return new SeqSOR(args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor); } static inline void deconstruct(SeqSOR* sor) { delete sor; } }; /** * @brief Policy for the construction of the SeqJac smoother */ template struct ConstructionTraits > { typedef DefaultConstructionArgs > Arguments; static inline SeqJac* construct(Arguments& args) { return new SeqJac(args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor); } static void deconstruct(SeqJac* jac) { delete jac; } }; /** * @brief Policy for the construction of the SeqILUn smoother */ template struct ConstructionTraits > { typedef DefaultConstructionArgs > Arguments; static inline SeqILU0* construct(Arguments& args) { return new SeqILU0(args.getMatrix(), args.getArgs().relaxationFactor); } static void deconstruct(SeqILU0* ilu) { delete ilu; } }; template class ConstructionArgs > : public DefaultConstructionArgs > { public: ConstructionArgs(int n=1) : n_(n) {} void setN(int n) { n_ = n; } int getN() { return n_; } private: int n_; }; /** * @brief Policy for the construction of the SeqJac smoother */ template struct ConstructionTraits > { typedef ConstructionArgs > Arguments; static inline SeqILUn* construct(Arguments& args) { return new SeqILUn(args.getMatrix(), args.getN(), args.getArgs().relaxationFactor); } static void deconstruct(SeqILUn* ilu) { delete ilu; } }; /** * @brief Policy for the construction of the ParSSOR smoother */ template struct ConstructionTraits > { typedef DefaultParallelConstructionArgs Arguments; static inline ParSSOR* construct(Arguments& args) { return new ParSSOR(args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor, args.getComm()); } static inline void deconstruct(ParSSOR* ssor) { delete ssor; } }; template struct ConstructionTraits > { typedef DefaultParallelConstructionArgs Arguments; typedef ConstructionTraits SeqConstructionTraits; static inline BlockPreconditioner* construct(Arguments& args) { return new BlockPreconditioner(*SeqConstructionTraits::construct(args), args.getComm()); } static inline void deconstruct(BlockPreconditioner* bp) { SeqConstructionTraits::deconstruct(static_cast(&bp->preconditioner)); delete bp; } }; template struct ConstructionTraits > { typedef DefaultParallelConstructionArgs Arguments; typedef ConstructionTraits SeqConstructionTraits; static inline NonoverlappingBlockPreconditioner* construct(Arguments& args) { return new NonoverlappingBlockPreconditioner(*SeqConstructionTraits::construct(args), args.getComm()); } static inline void deconstruct(NonoverlappingBlockPreconditioner* bp) { SeqConstructionTraits::deconstruct(static_cast(&bp->preconditioner)); delete bp; } }; /** * @brief Helper class for applying the smoothers. * * The goal of this class is to get a symmetric AMG method * whenever possible. * * The specializations for SOR and SeqOverlappingSchwarz in * MultiplicativeSchwarzMode will apply * the smoother forward when pre and backward when post smoothing. */ template struct SmootherApplier { typedef T Smoother; typedef typename Smoother::range_type Range; typedef typename Smoother::domain_type Domain; /** * @brief apply pre smoothing in forward direction * * @param smoother The smoother to use. * @param d The current defect. * @param v handle to store the update in. */ static void preSmooth(Smoother& smoother, Domain& v, const Range& d) { smoother.apply(v,d); } /** * @brief apply post smoothing in forward direction * * @param smoother The smoother to use. * @param d The current defect. * @param v handle to store the update in. */ static void postSmooth(Smoother& smoother, Domain& v, const Range& d) { smoother.apply(v,d); } }; /** * @brief Apply pre smoothing on the current level. * @param levelContext the iterators of the current level. * @param steps The number of smoothing steps to apply. */ template void presmooth(LevelContext& levelContext, size_t steps) { for(std::size_t i=0; i < steps; ++i) { *levelContext.lhs=0; SmootherApplier ::preSmooth(*levelContext.smoother, *levelContext.lhs, *levelContext.rhs); // Accumulate update *levelContext.update += *levelContext.lhs; // update defect levelContext.matrix->applyscaleadd(-1, *levelContext.lhs, *levelContext.rhs); levelContext.pinfo->project(*levelContext.rhs); } } /** * @brief Apply post smoothing on the current level. * @param levelContext the iterators of the current level. * @param steps The number of smoothing steps to apply. */ template void postsmooth(LevelContext& levelContext, size_t steps) { for(std::size_t i=0; i < steps; ++i) { // update defect levelContext.matrix->applyscaleadd(-1, *levelContext.lhs, *levelContext.rhs); *levelContext.lhs=0; levelContext.pinfo->project(*levelContext.rhs); SmootherApplier ::postSmooth(*levelContext.smoother, *levelContext.lhs, *levelContext.rhs); // Accumulate update *levelContext.update += *levelContext.lhs; } } template struct SmootherApplier > { typedef SeqSOR Smoother; typedef typename Smoother::range_type Range; typedef typename Smoother::domain_type Domain; static void preSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } static void postSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } }; template struct SmootherApplier > > { typedef BlockPreconditioner > Smoother; typedef typename Smoother::range_type Range; typedef typename Smoother::domain_type Domain; static void preSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } static void postSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } }; template struct SmootherApplier > > { typedef NonoverlappingBlockPreconditioner > Smoother; typedef typename Smoother::range_type Range; typedef typename Smoother::domain_type Domain; static void preSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } static void postSmooth(Smoother& smoother, Domain& v, Range& d) { smoother.template apply(v,d); } }; } // end namespace Amg // forward declarations template class SeqOverlappingSchwarz; struct MultiplicativeSchwarzMode; namespace Amg { template struct SmootherApplier > { typedef SeqOverlappingSchwarz Smoother; typedef typename Smoother::range_type Range; typedef typename Smoother::domain_type Domain; static void preSmooth(Smoother& smoother, Domain& v, const Range& d) { smoother.template apply(v,d); } static void postSmooth(Smoother& smoother, Domain& v, const Range& d) { smoother.template apply(v,d); } }; // template // class SeqOverlappingSchwarz; template struct SeqOverlappingSchwarzSmootherArgs : public DefaultSmootherArgs { enum Overlap {vertex, aggregate, pairwise, none}; Overlap overlap; bool onthefly; SeqOverlappingSchwarzSmootherArgs(Overlap overlap_=vertex, bool onthefly_=false) : overlap(overlap_), onthefly(onthefly_) {} }; template struct SmootherTraits > { typedef SeqOverlappingSchwarzSmootherArgs Arguments; }; template class ConstructionArgs > : public DefaultConstructionArgs > { typedef DefaultConstructionArgs > Father; public: typedef typename MatrixGraph::VertexDescriptor VertexDescriptor; typedef Dune::Amg::AggregatesMap AggregatesMap; typedef typename AggregatesMap::AggregateDescriptor AggregateDescriptor; typedef typename SeqOverlappingSchwarz::subdomain_vector Vector; typedef typename Vector::value_type Subdomain; virtual void setMatrix(const M& matrix, const AggregatesMap& amap) { Father::setMatrix(matrix); std::vector visited(amap.noVertices(), false); typedef IteratorPropertyMap::iterator,IdentityMap> VisitedMapType; VisitedMapType visitedMap(visited.begin()); MatrixGraph graph(matrix); typedef SeqOverlappingSchwarzSmootherArgs SmootherArgs; switch(Father::getArgs().overlap) { case SmootherArgs::vertex : { VertexAdder visitor(subdomains, amap); createSubdomains(matrix, graph, amap, visitor, visitedMap); } break; case SmootherArgs::pairwise : { createPairDomains(graph); } break; case SmootherArgs::aggregate : { AggregateAdder visitor(subdomains, amap, graph, visitedMap); createSubdomains(matrix, graph, amap, visitor, visitedMap); } break; case SmootherArgs::none : NoneAdder visitor; createSubdomains(matrix, graph, amap, visitor, visitedMap); break; default : DUNE_THROW(NotImplemented, "This overlapping scheme is not supported!"); } } void setMatrix(const M& matrix) { Father::setMatrix(matrix); /* Create aggregates map where each aggregate is just one vertex. */ AggregatesMap amap(matrix.N()); VertexDescriptor v=0; for(typename AggregatesMap::iterator iter=amap.begin(); iter!=amap.end(); ++iter) *iter=v++; std::vector visited(amap.noVertices(), false); typedef IteratorPropertyMap::iterator,IdentityMap> VisitedMapType; VisitedMapType visitedMap(visited.begin()); MatrixGraph graph(matrix); typedef SeqOverlappingSchwarzSmootherArgs SmootherArgs; switch(Father::getArgs().overlap) { case SmootherArgs::vertex : { VertexAdder visitor(subdomains, amap); createSubdomains(matrix, graph, amap, visitor, visitedMap); } break; case SmootherArgs::aggregate : { DUNE_THROW(NotImplemented, "Aggregate overlap is not supported yet"); /* AggregateAdder visitor(subdomains, amap, graph, visitedMap); createSubdomains(matrix, graph, amap, visitor, visitedMap); */ } break; case SmootherArgs::pairwise : { createPairDomains(graph); } break; case SmootherArgs::none : NoneAdder visitor; createSubdomains(matrix, graph, amap, visitor, visitedMap); } } const Vector& getSubDomains() { return subdomains; } private: struct VertexAdder { VertexAdder(Vector& subdomains_, const AggregatesMap& aggregates_) : subdomains(subdomains_), max(-1), subdomain(-1), aggregates(aggregates_) {} template void operator()(const T& edge) { if(aggregates[edge.target()]!=AggregatesMap::ISOLATED) subdomains[subdomain].insert(edge.target()); } int setAggregate(const AggregateDescriptor& aggregate_) { subdomain=aggregate_; max = std::max(subdomain, aggregate_); return subdomain; } int noSubdomains() const { return max+1; } private: Vector& subdomains; AggregateDescriptor max; AggregateDescriptor subdomain; const AggregatesMap& aggregates; }; struct NoneAdder { template void operator()(const T& edge) {} int setAggregate(const AggregateDescriptor& aggregate_) { return -1; } int noSubdomains() const { return -1; } }; template struct AggregateAdder { AggregateAdder(Vector& subdomains_, const AggregatesMap& aggregates_, const MatrixGraph& graph_, VM& visitedMap_) : subdomains(subdomains_), subdomain(-1), aggregates(aggregates_), adder(subdomains_, aggregates_), graph(graph_), visitedMap(visitedMap_) {} template void operator()(const T& edge) { subdomains[subdomain].insert(edge.target()); // If we (the neighbouring vertex of the aggregate) // are not isolated, add the aggregate we belong to // to the same subdomain using the OneOverlapAdder if(aggregates[edge.target()]!=AggregatesMap::ISOLATED) { assert(aggregates[edge.target()]!=aggregate); typename AggregatesMap::VertexList vlist; aggregates.template breadthFirstSearch(edge.target(), aggregate, graph, vlist, adder, adder, visitedMap); } } int setAggregate(const AggregateDescriptor& aggregate_) { adder.setAggregate(aggregate_); aggregate=aggregate_; return ++subdomain; } int noSubdomains() const { return subdomain+1; } private: AggregateDescriptor aggregate; Vector& subdomains; int subdomain; const AggregatesMap& aggregates; VertexAdder adder; const MatrixGraph& graph; VM& visitedMap; }; void createPairDomains(const MatrixGraph& graph) { typedef typename MatrixGraph::ConstVertexIterator VIter; typedef typename MatrixGraph::ConstEdgeIterator EIter; typedef typename M::size_type size_type; std::set > pairs; int total=0; for(VIter v=graph.begin(), ve=graph.end(); ve != v; ++v) for(EIter e = v.begin(), ee=v.end(); ee!=e; ++e) { ++total; if(e.source() >::const_iterator SIter; typename Vector::iterator subdomain=subdomains.begin(); for(SIter s=pairs.begin(), se =pairs.end(); se!=s; ++s) { subdomain->insert(s->first); subdomain->insert(s->second); ++subdomain; } std::size_t minsize=10000; std::size_t maxsize=0; int sum=0; for(typename Vector::size_type i=0; i < subdomains.size(); ++i) { sum+=subdomains[i].size(); minsize=std::min(minsize, subdomains[i].size()); maxsize=std::max(maxsize, subdomains[i].size()); } Dune::dinfo<<"Subdomain size: min="< LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} CMAKE_GUARD "SUPERLU_FOUND OR SuiteSparse_UMFPACK_FOUND") dune_add_test(NAME pthreaddirecttwoleveltest SOURCES pthreadtwoleveltest.cc LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} CMAKE_GUARD "SUPERLU_FOUND OR SuiteSparse_UMFPACK_FOUND") endif() # add an executable without SuperLU/UMFPack add_executable(amgtest amgtest.cc) target_link_libraries(amgtest ${DUNE_LIBS}) dune_add_test(TARGET amgtest) add_executable(fastamg fastamg.cc) target_link_libraries(fastamg ${DUNE_LIBS}) dune_add_test(TARGET fastamg) if(SUPERLU_FOUND) add_executable(superluamgtest amgtest.cc) add_dune_superlu_flags(superluamgtest) target_link_libraries(superluamgtest ${DUNE_LIBS}) dune_add_test(TARGET superluamgtest) add_executable(superlufastamgtest fastamg.cc) add_dune_superlu_flags(superlufastamgtest) target_link_libraries(superlufastamgtest ${DUNE_LIBS}) dune_add_test(TARGET superlufastamgtest) endif() dune_add_test(NAME umfpackamgtest SOURCES amgtest.cc CMAKE_GUARD SuiteSparse_UMFPACK_FOUND) dune_add_test(NAME umfpackfastamgtest SOURCES fastamg.cc CMAKE_GUARD SuiteSparse_UMFPACK_FOUND) dune_add_test(SOURCES twolevelmethodtest.cc) dune_add_test(SOURCES graphtest.cc) dune_add_test(SOURCES kamgtest.cc) dune_add_test(SOURCES transfertest.cc) dune_add_test(NAME twolevelmethodschwarztest SOURCES twolevelmethodtest.cc COMPILE_DEFINITIONS USE_OVERLAPPINGSCHWARZ) # These tests need MPI, even though they are only run sequentially dune_add_test(SOURCES galerkintest.cc CMAKE_GUARD MPI_FOUND) dune_add_test(SOURCES hierarchytest.cc CMAKE_GUARD MPI_FOUND) dune_add_test(NAME pamgtest SOURCES parallelamgtest.cc CMAKE_GUARD MPI_FOUND) dune_add_test(NAME pamg_comm_repart_test SOURCES parallelamgtest.cc COMPILE_DEFINITIONS -DAMG_REPART_ON_COMM_GRAPH CMAKE_GUARD MPI_FOUND) dune-istl-2.5.1/dune/istl/paamg/test/amgtest.cc000066400000000000000000000113461313314427100213540ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" /*#include"xreal.h" namespace std { HPA::xreal abs(const HPA::xreal& t) { return t>=0?t:-t; } }; */ #include "anisotropic.hh" #include #include #include #include #include #include #include #include #include typedef double XREAL; // typedef std::complex XREAL; /* typedef HPA::xreal XREAL; namespace Dune { template<> struct DoubleConverter { static double toDouble(const HPA::xreal& t) { return t._2double(); } }; } */ template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } template void testAMG(int N, int coarsenTarget, int ml) { std::cout<<"N="<::real_type>::value, Dune::Amg::FirstDiagonal, Dune::Amg::RowSum >::type Norm; typedef Dune::Amg::CoarsenCriterion > Criterion; typedef Dune::SeqSSOR Smoother; //typedef Dune::SeqSOR Smoother; //typedef Dune::SeqJac Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; typedef typename Dune::Amg::SmootherTraits::Arguments SmootherArgs; SmootherArgs smootherArgs; smootherArgs.iterations = 1; //smootherArgs.overlap=SmootherArgs::vertex; //smootherArgs.overlap=SmootherArgs::none; //smootherArgs.overlap=SmootherArgs::aggregate; smootherArgs.relaxationFactor = 1; Criterion criterion(15,coarsenTarget); criterion.setDefaultValuesIsotropic(2); criterion.setAlpha(.67); criterion.setBeta(1.0e-4); criterion.setMaxLevel(ml); criterion.setSkipIsolated(false); // specify pre/post smoother steps criterion.setNoPreSmoothSteps(1); criterion.setNoPostSmoothSteps(1); Dune::SeqScalarProduct sp; typedef Dune::Amg::AMG AMG; Smoother smoother(mat,1,1); AMG amg(fop, criterion, smootherArgs); double buildtime = watch.elapsed(); std::cout<<"Building hierarchy took "< amgCG(fop,amg,1e-6,80,2); //Dune::LoopSolver amgCG(fop, amg, 1e-4, 10000, 2); watch.reset(); Dune::InverseOperatorResult r; amgCG.apply(x,b,r); XREAL solvetime = watch.elapsed(); std::cout<<"AMG solving took "<1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); if(argc>3) ml = atoi(argv[3]); testAMG<1>(N, coarsenTarget, ml); testAMG<2>(N, coarsenTarget, ml); return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Dune reported an unknown error." << std::endl; exit(1); } dune-istl-2.5.1/dune/istl/paamg/test/anisotropic.hh000066400000000000000000000140401313314427100222460ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef ANISOTROPIC_HH #define ANISOTROPIC_HH #include #include #include #include #include #include #include typedef Dune::OwnerOverlapCopyAttributeSet GridAttributes; typedef GridAttributes::AttributeSet GridFlag; typedef Dune::ParallelLocalIndex LocalIndex; template void setupPattern(int N, M& mat, Dune::ParallelIndexSet& indices, int overlapStart, int overlapEnd, int start, int end); template void fillValues(int N, M& mat, int overlapStart, int overlapEnd, int start, int end); template M setupAnisotropic2d(int N, Dune::ParallelIndexSet& indices, const Dune::CollectiveCommunication& p, int *nout, typename M::block_type::value_type eps=1.0); template void setupPattern(int N, M& mat, Dune::ParallelIndexSet& indices, int overlapStart, int overlapEnd, int start, int end) { int n = overlapEnd - overlapStart; typename M::CreateIterator iter = mat.createbegin(); indices.beginResize(); for(int j=0; j < N; j++) for(int i=overlapStart; i < overlapEnd; i++, ++iter) { int global = j*N+i; GridFlag flag = GridAttributes::owner; bool isPublic = false; if((i 0) || (i>= end && i < N-1)) flag=GridAttributes::copy; if(i= end-1) { isPublic = true; indices.add(global, LocalIndex(iter.index(), flag, isPublic)); } iter.insert(iter.index()); // i direction if(i > overlapStart ) // We have a left neighbour iter.insert(iter.index()-1); if(i < overlapEnd-1) // We have a rigt neighbour iter.insert(iter.index()+1); // j direction // Overlap is a dirichlet border, discard neighbours if(flag != GridAttributes::copy) { if(j>0) // lower neighbour iter.insert(iter.index()-n); if(j void fillValues(int N, M& mat, int overlapStart, int overlapEnd, int start, int end, T eps) { DUNE_UNUSED_PARAMETER(N); typedef typename M::block_type Block; Block dval(0), bone(0), bmone(0), beps(0); for(typename Block::RowIterator b = dval.begin(); b != dval.end(); ++b) b->operator[](b.index())=2.0+2.0*eps; for(typename Block::RowIterator b=bone.begin(); b != bone.end(); ++b) b->operator[](b.index())=1.0; for(typename Block::RowIterator b=bmone.begin(); b != bmone.end(); ++b) b->operator[](b.index())=-1.0; for(typename Block::RowIterator b=beps.begin(); b != beps.end(); ++b) b->operator[](b.index())=-eps; int n = overlapEnd-overlapStart; typedef typename M::ColIterator ColIterator; typedef typename M::RowIterator RowIterator; for (RowIterator i = mat.begin(); i != mat.end(); ++i) { // calculate coordinate int y = i.index() / n; int x = overlapStart + i.index() - y * n; ColIterator endi = (*i).end(); if(x= end) { // || x==0 || x==N-1 || y==0 || y==N-1){ // overlap node is dirichlet border ColIterator j = (*i).begin(); for(; j.index() < i.index(); ++j) *j=0; *j = bone; for(++j; j != endi; ++j) *j=0; }else{ for(ColIterator j = (*i).begin(); j != endi; ++j) if(j.index() == i.index()) *j=dval; else if(j.index()+1==i.index() || j.index()-1==i.index()) *j=beps; else *j=bmone; } } } template void setBoundary(V& lhs, V& rhs, const G& n, Dune::ParallelIndexSet& indices) { typedef typename Dune::ParallelIndexSet::const_iterator Iter; for(Iter i=indices.begin(); i != indices.end(); ++i) { G x = i->global()/n; G y = i->global()%n; if(x==0 || y ==0 || x==n-1 || y==n-1) { //double h = 1.0 / ((double) (n-1)); lhs[i->local()]=rhs[i->local()]=0; //((double)x)*((double)y)*h*h; } } } template void setBoundary(V& lhs, V& rhs, const G& N) { typedef typename V::block_type Block; typedef typename Block::value_type T; for(int j=0; j < N; ++j) for(int i=0; i < N; i++) if(i==0 || j ==0 || i==N-1 || j==N-1) { T h = 1.0 / ((double) (N-1)); T x, y; if(i==N-1) x=1; else x = ((T) i)*h; if(j==N-1) y = 1; else y = ((T) j)*h; lhs[j*N+i]=rhs[j*N+i]=0; //x*y; } } template M setupAnisotropic2d(int N, Dune::ParallelIndexSet& indices, const Dune::CollectiveCommunication& p, int *nout, typename M::block_type::value_type eps) { int procs=p.size(), rank=p.rank(); typedef M BCRSMat; // calculate size of local matrix in the distributed direction int start, end, overlapStart, overlapEnd; int n = N/procs; // number of unknowns per process int bigger = N%procs; // number of process with n+1 unknows // Compute owner region if(rank0) overlapStart = start - 1; else overlapStart = start; if(end #include #include #include #include #include #include #include template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } template void testAMG(int N, int coarsenTarget, int ml) { std::cout<<"N="< > CriterionBase; typedef Dune::Amg::CoarsenCriterion Criterion; Criterion criterion(15,coarsenTarget); criterion.setDefaultValuesIsotropic(2); criterion.setAlpha(.67); criterion.setBeta(1.0e-4); criterion.setMaxLevel(ml); criterion.setSkipIsolated(false); Dune::SeqScalarProduct sp; typedef Dune::Amg::FastAMG AMG; Dune::Amg::Parameters parms; AMG amg(fop, criterion, parms); // check if recalculation of matrix hierarchy works amg.recalculateHierarchy(); double buildtime = watch.elapsed(); std::cout<<"Building hierarchy took "< amgCG(fop,amg,1e-6,80,2); //Dune::LoopSolver amgCG(fop, amg, 1e-4, 10000, 2); watch.reset(); Dune::InverseOperatorResult r; amgCG.apply(x,b,r); double solvetime = watch.elapsed(); std::cout<<"AMG solving took "<1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); if(argc>3) ml = atoi(argv[3]); testAMG<1>(N, coarsenTarget, ml); testAMG<2>(N, coarsenTarget, ml); return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Dune reported an unknown error." << std::endl; exit(1); } dune-istl-2.5.1/dune/istl/paamg/test/galerkintest.cc000066400000000000000000000142641313314427100224060ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "anisotropic.hh" template void testCoarsenIndices(int N) { int procs, rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &procs); typedef Dune::OwnerOverlapCopyCommunication ParallelInformation; typedef typename ParallelInformation::ParallelIndexSet ParallelIndexSet; typedef typename ParallelInformation::RemoteIndices RemoteIndices; typedef Dune::FieldMatrix Block; typedef Dune::BCRSMatrix BCRSMat; int n; ParallelInformation pinfo(MPI_COMM_WORLD); ParallelIndexSet& indices = pinfo.indexSet(); RemoteIndices& remoteIndices = pinfo.remoteIndices(); typedef Dune::CollectiveCommunication Comm; Comm cc(MPI_COMM_WORLD); BCRSMat mat = setupAnisotropic2d(N, indices, cc, &n); pinfo.remoteIndices().template rebuild(); typedef Dune::Amg::MatrixGraph MatrixGraph; typedef Dune::Amg::SubGraph,std::vector > SubGraph; typedef Dune::Amg::PropertiesGraph PropertiesGraph; typedef typename PropertiesGraph::VertexDescriptor Vertex; typedef Dune::Amg::SymmetricCriterion Criterion; MatrixGraph mg(mat); std::vector excluded(mat.N()); typedef ParallelIndexSet::iterator IndexIterator; IndexIterator iend = indices.end(); typename std::vector::iterator iter=excluded.begin(); for(IndexIterator index = indices.begin(); index != iend; ++index, ++iter) *iter = (index->local().attribute()==GridAttributes::copy); SubGraph sg(mg, excluded); PropertiesGraph pg(sg, Dune::IdentityMap(), sg.getEdgeIndexMap()); Dune::Amg::AggregatesMap aggregatesMap(pg.noVertices()); std::cout << "fine indices: "<::Type visitedMap = Dune::get(Dune::Amg::VertexVisitedTag(), pg); pinfo.buildGlobalLookup(aggregatesMap.noVertices()); int noCoarseVertices = Dune::Amg::IndicesCoarsener >::coarsen(pinfo, pg, visitedMap, aggregatesMap, coarseInfo, noAggregates); coarseInfo.buildGlobalLookup(noCoarseVertices); std::cout << rank <<": coarse indices: " <(), Dune::EnumItem()); Communicator communicator; typedef Dune::Amg::GlobalAggregatesMap GlobalMap; GlobalMap gmap(aggregatesMap, coarseInfo.globalLookup()); communicator.build(interface); Dune::Amg::printAggregates2d(aggregatesMap, n, N, std::cout); communicator.template forward >(gmap); std::cout<<"Communicated: "; Dune::Amg::printAggregates2d(aggregatesMap, n, N, std::cout); Dune::Amg::GalerkinProduct productBuilder; typedef Dune::IteratorPropertyMap VisitedMap2; /* Vector visited; visited.reserve(mg.maxVertex()); Iterator visitedIterator=visited.begin(); */ std::cout<()); delete[] visitedIterator; pinfo.freeGlobalLookup(); productBuilder.calculate(mat, aggregatesMap, *coarseMat, coarseInfo, Dune::EnumItem()); if(N<5) { Dune::printmatrix(std::cout,mat,"fine","row",9,1); Dune::printmatrix(std::cout,*coarseMat,"coarse","row",9,1); } } int main(int argc, char **argv) { MPI_Init(&argc, &argv); int N=5; if(argc>1) N = atoi(argv[1]); std::cout << "Galerkin test with N=" << N << std::endl; testCoarsenIndices<1>(N); MPI_Finalize(); } dune-istl-2.5.1/dune/istl/paamg/test/graphtest.cc000066400000000000000000000341741313314427100217150ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // start with including some headers #include "config.h" #include // for input/output to shell #include #include #include #include #include #include #include #include int testEdgeDepends(const Dune::Amg::EdgeProperties& flags) { int ret=0; if(!flags.depends()) { std::cerr << "Depends does not return true after setDepends! "<<__FILE__ <<":"<<__LINE__<0) std::cerr<<"Flags: "< void setupSparsityPattern(M& A) { for (typename M::CreateIterator i = A.createbegin(); i != A.createend(); ++i) { int x = i.index()%N; // x coordinate in the 2d field int y = i.index()/N; // y coordinate in the 2d field if(y>0) // insert lower neighbour i.insert(i.index()-N); if(x>0) // insert left neighbour i.insert(i.index()-1); // insert diagonal value i.insert(i.index()); if(x void setupAnisotropic(M& A, double eps) { typename M::block_type diagonal = 0, bone=0, beps=0; for(typename M::block_type::RowIterator b = diagonal.begin(); b != diagonal.end(); ++b) b->operator[](b.index())=2.0+2.0*eps; for(typename M::block_type::RowIterator b=bone.begin(); b != bone.end(); ++b) b->operator[](b.index())=-1.0; for(typename M::block_type::RowIterator b=beps.begin(); b != beps.end(); ++b) b->operator[](b.index())=-eps; for (typename M::RowIterator i = A.begin(); i != A.end(); ++i) { int x = i.index()%N; // x coordinate in the 2d field int y = i.index()/N; // y coordinate in the 2d field i->operator[](i.index())=diagonal; if(y>0) i->operator[](i.index()-N)=beps; if(yoperator[](i.index()+N)=beps; if(x>0) i->operator[](i.index()-1)=bone; if(x < N-1) i->operator[](i.index()+1)=bone; } } template void printWeightedGraph(G& graph, std::ostream& os, const N& norm=N()) { typedef typename std::remove_const::type Mutable; typedef typename std::conditional::value, typename G::VertexIterator, typename G::ConstVertexIterator>::type VertexIterator; typedef typename std::conditional::value, typename G::EdgeIterator, typename G::ConstEdgeIterator>::type EdgeIterator; for(VertexIterator vertex = graph.begin(); vertex!=graph.end(); ++vertex) { const EdgeIterator endEdge = vertex.end(); os<<"Edges starting from Vertex "<<*vertex<<" (weight="< void printPropertiesGraph(G& graph, std::ostream& os) { typedef typename std::remove_const::type Mutable; typedef typename std::conditional::value, typename G::VertexIterator, typename G::ConstVertexIterator>::type VertexIterator; typedef typename std::conditional::value, typename G::EdgeIterator, typename G::ConstEdgeIterator>::type EdgeIterator; for(VertexIterator vertex = graph.begin(); vertex!=graph.end(); ++vertex) { const EdgeIterator endEdge = vertex.end(); os<<"Edges starting from Vertex "<<*vertex<<" to vertices ("; os< void printGraph(G& graph, std::ostream& os) { typedef typename std::remove_const::type Mutable; typedef typename std::conditional::value, typename G::VertexIterator, typename G::ConstVertexIterator>::type VertexIterator; typedef typename std::conditional::value, typename G::EdgeIterator, typename G::ConstEdgeIterator>::type EdgeIterator; for(VertexIterator vertex = graph.begin(); vertex!=graph.end(); ++vertex) { const EdgeIterator endEdge = vertex.end(); os<<"Edges starting from Vertex "<<*vertex<<" to vertices "; for(EdgeIterator edge = vertex.begin(); edge != endEdge; ++edge) os< ScalarDouble; typedef Dune::BCRSMatrix BCRSMat; double diagonal=4, offdiagonal=-1; BCRSMat laplacian2d(N*N,N*N,N*N*5,BCRSMat::row_wise); setupSparsityPattern(laplacian2d); laplacian2d = offdiagonal; // Set the diagonal values for (BCRSMat::RowIterator i=laplacian2d.begin(); i!=laplacian2d.end(); ++i) i->operator[](i.index())=diagonal; //Dune::printmatrix(std::cout,laplacian2d,"2d Laplacian","row",9,1); typedef Dune::Amg::MatrixGraph MatrixGraph; MatrixGraph mg(laplacian2d); using Dune::Amg::FirstDiagonal; printWeightedGraph(mg,std::cout,FirstDiagonal()); printWeightedGraph(static_cast(mg), std::cout,FirstDiagonal()); std::vector excluded(N*N, false); for(int i=0; i < N; i++) { excluded[i]=excluded[(N-1)*N+i]=true; excluded[i*N]=excluded[i*N+N-1]=true; } typedef Dune::Amg::SubGraph,std::vector > SubGraph; SubGraph sub(mg, excluded); for(std::vector::iterator iter=excluded.begin(); iter != excluded.end(); ++iter) std::cout<<*iter<<" "; std::cout< PropertiesGraph; std::cout< saggregatesMap(pgraph.maxVertex()+1); saggregatesMap.buildAggregates(mat, spgraph, crit, false); Dune::Amg::printAggregates2d(saggregatesMap, N, N, std::cout); } int main (int argc , char ** argv) { try { testGraph(); testAggregate(); exit(testEdge()); } catch(std::exception& e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "unknown exception caught" << std::endl; exit(1); } return 0; } dune-istl-2.5.1/dune/istl/paamg/test/hierarchytest.cc000066400000000000000000000047611313314427100225710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include "mpi.h" #include #include #include #include #include #include #include "anisotropic.hh" template void testHierarchy(int N) { typedef int LocalId; typedef int GlobalId; typedef Dune::OwnerOverlapCopyCommunication Communication; typedef Communication::ParallelIndexSet ParallelIndexSet; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; int n; Communication pinfo(MPI_COMM_WORLD); ParallelIndexSet& indices = pinfo.indexSet(); typedef Dune::RemoteIndices RemoteIndices; RemoteIndices& remoteIndices = pinfo.remoteIndices(); typedef Dune::CollectiveCommunication Comm; Comm cc(MPI_COMM_WORLD); BCRSMat mat = setupAnisotropic2d(N, indices, cc, &n); Vector b(indices.size()); remoteIndices.rebuild(); typedef Dune::NegateSet OverlapFlags; typedef Dune::OverlappingSchwarzOperator Operator; typedef Dune::Amg::MatrixHierarchy Hierarchy; typedef Dune::Amg::Hierarchy VHierarchy; Operator op(mat, pinfo); Hierarchy hierarchy(op, pinfo); VHierarchy vh(b); typedef Dune::Amg::CoarsenCriterion > Criterion; Criterion criterion(100,4); Dune::Timer timer; hierarchy.template build(criterion); hierarchy.coarsenVector(vh); std::cout<<"Building hierarchy took "< data; hierarchy.getCoarsestAggregatesOnFinest(data); } int main(int argc, char** argv) { MPI_Init(&argc, &argv); const int BS=1; int N=10; if(argc>1) N = atoi(argv[1]); int procs, rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &procs); testHierarchy(N); MPI_Finalize(); } dune-istl-2.5.1/dune/istl/paamg/test/kamgtest.cc000066400000000000000000000102431313314427100215220ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include "anisotropic.hh" #include #include #include #include #include #include #include template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } template void testAMG(int N, int coarsenTarget, int ml) { std::cout<<"N="< > Criterion; typedef Dune::SeqSSOR Smoother; //typedef Dune::SeqSOR Smoother; //typedef Dune::SeqJac Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; typedef typename Dune::Amg::SmootherTraits::Arguments SmootherArgs; SmootherArgs smootherArgs; smootherArgs.iterations = 1; //smootherArgs.overlap=SmootherArgs::vertex; //smootherArgs.overlap=SmootherArgs::none; //smootherArgs.overlap=SmootherArgs::aggregate; smootherArgs.relaxationFactor = 1; Criterion criterion(15,coarsenTarget); criterion.setDefaultValuesIsotropic(2); criterion.setAlpha(.67); criterion.setBeta(1.0e-4); criterion.setMaxLevel(ml); criterion.setSkipIsolated(false); // specify pre/post smoother steps criterion.setNoPreSmoothSteps(1); criterion.setNoPostSmoothSteps(1); Dune::SeqScalarProduct sp; typedef Dune::Amg::KAMG AMG; AMG amg(fop, criterion, smootherArgs); double buildtime = watch.elapsed(); std::cout<<"Building hierarchy took "< amgCG(fop,amg,1e-6,80,2); Dune::CGSolver amgCG(fop,amg,1e-6,80,2); //Dune::LoopSolver amgCG(fop, amg, 1e-4, 10000, 2); watch.reset(); Dune::InverseOperatorResult r; amgCG.apply(x,b,r); double solvetime = watch.elapsed(); std::cout<<"AMG solving took "<1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); if(argc>3) ml = atoi(argv[3]); testAMG<1>(N, coarsenTarget, ml); testAMG<2>(N, coarsenTarget, ml); return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Dune reported an unknown error." << std::endl; exit(1); } dune-istl-2.5.1/dune/istl/paamg/test/parallelamgtest.cc000066400000000000000000000136731313314427100230760ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #ifdef TEST_AGGLO #define UNKNOWNS 10 #endif #include "anisotropic.hh" #include #include #include #include #include #include #include #include #include template class DoubleStepPreconditioner : public Dune::Preconditioner { public: typedef typename T::domain_type X; typedef typename T::range_type Y; enum {category = T::category}; DoubleStepPreconditioner(T& preconditioner_, C& comm) : preconditioner(&preconditioner_), comm_(comm) {} virtual void pre (X& x, Y& b) { preconditioner->pre(x,b); } virtual void apply(X& v, const Y& d) { preconditioner->apply(v,d); comm_.copyOwnerToAll(v,v); } virtual void post (X& x) { preconditioner->post(x); } private: T* preconditioner; C& comm_; }; class MPIError { public: /** @brief Constructor. */ MPIError(std::string s, int e) : errorstring(s), errorcode(e){} /** @brief The error string. */ std::string errorstring; /** @brief The mpi error code. */ int errorcode; }; void MPI_err_handler(MPI_Comm *comm, int *err_code, ...){ DUNE_UNUSED_PARAMETER(comm); char *err_string=new char[MPI_MAX_ERROR_STRING]; int err_length; MPI_Error_string(*err_code, err_string, &err_length); std::string s(err_string, err_length); std::cerr << "An MPI Error occurred:"< void testAmg(int N, int coarsenTarget) { std::cout<<"==================================================="< > Criterion; typedef Dune::SeqSSOR Smoother; //typedef Dune::SeqJac Smoother; //typedef Dune::SeqILU0 Smoother; //typedef Dune::SeqILUn Smoother; typedef Dune::BlockPreconditioner ParSmoother; typedef typename Dune::Amg::SmootherTraits::Arguments SmootherArgs; Dune::OverlappingSchwarzScalarProduct sp(comm); Dune::InverseOperatorResult r, r1; double buildtime; SmootherArgs smootherArgs; smootherArgs.iterations = 1; Criterion criterion(15,coarsenTarget); criterion.setDefaultValuesIsotropic(2); typedef Dune::Amg::AMG AMG; AMG amg(fop, criterion, smootherArgs, comm); buildtime = watch.elapsed(); if(rank==0) std::cout<<"Building hierarchy took "< amgCG(fop, sp, amg, 10e-8, 300, (rank==0) ? 2 : 0); watch.reset(); amgCG.apply(x,b,r); amg.recalculateHierarchy(); MPI_Barrier(MPI_COMM_WORLD); double solvetime = watch.elapsed(); b=0; x=100; setBoundary(x, b, N, comm.indexSet()); Dune::CGSolver amgCG1(fop, sp, amg, 10e-8, 300, (rank==0) ? 2 : 0); amgCG1.apply(x,b,r); if(!r.converged && rank==0) std::cerr<<" AMG Cg solver did not converge!"< struct AMGTester { static void test(int N, int coarsenTarget) { testAmg(N, coarsenTarget); const int next = (BSStart+BSStep>BSEnd) ? BSEnd : BSStart+BSStep; AMGTester::test(N, coarsenTarget); } } ; template struct AMGTester { static void test(int N, int coarsenTarget) { testAmg(N, coarsenTarget); } }; int main(int argc, char** argv) { MPI_Init(&argc, &argv); MPI_Errhandler handler; MPI_Errhandler_create(MPI_err_handler, &handler); MPI_Errhandler_set(MPI_COMM_WORLD, handler); int N=100; int coarsenTarget=200; if(argc>1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); #ifdef TEST_AGGLO N=UNKNOWNS; #endif AMGTester<1,1>::test(N, coarsenTarget); //AMGTester<1,5>::test(N, coarsenTarget); // AMGTester<10,10>::test(N, coarsenTarget); MPI_Finalize(); } dune-istl-2.5.1/dune/istl/paamg/test/pthreadamgtest.cc000066400000000000000000000136121313314427100227220ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" /*#include"xreal.h" namespace std { HPA::xreal abs(const HPA::xreal& t) { return t>=0?t:-t; } }; */ #include "anisotropic.hh" #include #include #include #include #include #include #include #include #include #include #define NUM_THREADS 3 typedef double XREAL; /* typedef HPA::xreal XREAL; namespace Dune { template<> struct DoubleConverter { static double toDouble(const HPA::xreal& t) { return t._2double(); } }; } */ template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } typedef Dune::ParallelIndexSet ParallelIndexSet; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; typedef Dune::CollectiveCommunication Comm; typedef Dune::SeqSSOR Smoother; typedef Dune::Amg::SmootherTraits::Arguments SmootherArgs; struct thread_arg { MYAMG *amg; Vector *b; Vector *x; Operator *fop; }; void *solve(void* arg) { thread_arg *amgarg=(thread_arg*) arg; Dune::GeneralizedPCGSolver amgCG(*amgarg->fop,*amgarg->amg,1e-6,80,2); //Dune::LoopSolver amgCG(fop, amg, 1e-4, 10000, 2); Dune::Timer watch; Dune::InverseOperatorResult r; amgCG.apply(*amgarg->x,*amgarg->b,r); double solvetime = watch.elapsed(); std::cout<<"AMG solving took "<x=0; (*amgarg->amg).apply(*amgarg->x,*amgarg->b); (*amgarg->amg).post(*amgarg->x); return 0; } void *solve2(void* arg) { thread_arg *amgarg=(thread_arg*) arg; *amgarg->x=0; (*amgarg->amg).pre(*amgarg->x,*amgarg->b); (*amgarg->amg).apply(*amgarg->x,*amgarg->b); (*amgarg->amg).post(*amgarg->x); return 0; } template void testAMG(int N, int coarsenTarget, int ml) { std::cout<<"N="< > Criterion; //typedef Dune::SeqSOR Smoother; //typedef Dune::SeqJac Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; //typedef Dune::SeqOverlappingSchwarz Smoother; SmootherArgs smootherArgs; smootherArgs.iterations = 1; //smootherArgs.overlap=SmootherArgs::vertex; //smootherArgs.overlap=SmootherArgs::none; //smootherArgs.overlap=SmootherArgs::aggregate; smootherArgs.relaxationFactor = 1; Criterion criterion(15,coarsenTarget); criterion.setDefaultValuesIsotropic(2); criterion.setAlpha(.67); criterion.setBeta(1.0e-4); criterion.setMaxLevel(ml); criterion.setSkipIsolated(false); Dune::SeqScalarProduct sp; Smoother smoother(mat,1,1); AMG amg(fop, criterion); double buildtime = watch.elapsed(); std::cout<<"Building hierarchy took "< amgs(NUM_THREADS, amg); std::vector args(NUM_THREADS); std::vector threads(NUM_THREADS); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve, (void*) &args[i]); } void* retval; for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); amgs.clear(); args.clear(); amg.pre(x, b); amgs.resize(NUM_THREADS, amg); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve1, (void*) &args[i]); } for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); amgs.clear(); args.clear(); amg.pre(x, b); amgs.resize(NUM_THREADS, amg); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve2, (void*) &args[i]); } for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); } int main(int argc, char** argv) try { int N=100; int coarsenTarget=1200; int ml=10; if(argc>1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); if(argc>3) ml = atoi(argv[3]); testAMG<1,MYAMG>(N, coarsenTarget, ml); //testAMG<2>(N, coarsenTarget, ml); return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Dune reported an unknown error." << std::endl; exit(1); } dune-istl-2.5.1/dune/istl/paamg/test/pthreadtwoleveltest.cc000066400000000000000000000153741313314427100240260ustar00rootroot00000000000000#include"config.h" #include "anisotropic.hh" #include #include #include #include #include #include #include #include #define NUM_THREADS 3 template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } typedef double XREAL; typedef Dune::ParallelIndexSet ParallelIndexSet; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; typedef Dune::CollectiveCommunication Comm; typedef Dune::SeqSSOR Smoother; typedef Dune::Amg::SmootherTraits::Arguments SmootherArgs; #ifndef USE_OVERLAPPINGSCHWARZ typedef Dune::SeqSSOR FSmoother; #else typedef Dune::SeqOverlappingSchwarz FSmoother; #endif typedef Dune::SeqJac CSmoother; typedef Dune::Amg::CoarsenCriterion< Dune::Amg::UnSymmetricCriterion > Criterion; typedef Dune::Amg::OneStepAMGCoarseSolverPolicy CoarsePolicy; // Policy for coarse solver creation typedef Dune::Amg::TwoLevelMethod AMG; struct thread_arg { AMG *amg; Vector *b; Vector *x; Operator *fop; }; void *solve(void* arg) { thread_arg *amgarg=(thread_arg*) arg; Dune::GeneralizedPCGSolver amgCG(*amgarg->fop,*amgarg->amg,1e-4,80,2); //Dune::LoopSolver amgCG(fop, amg, 1e-4, 10000, 2); Dune::Timer watch; Dune::InverseOperatorResult r; amgCG.apply(*amgarg->x,*amgarg->b,r); double solvetime = watch.elapsed(); std::cout<<"AMG solving took "<x=0; (*amgarg->amg).apply(*amgarg->x,*amgarg->b); (*amgarg->amg).post(*amgarg->x); return 0; } void *solve2(void* arg) { thread_arg *amgarg=(thread_arg*) arg; *amgarg->x=0; (*amgarg->amg).pre(*amgarg->x,*amgarg->b); (*amgarg->amg).apply(*amgarg->x,*amgarg->b); (*amgarg->amg).post(*amgarg->x); return 0; } void testTwoLevelMethod() { const int BS=1; int N=100; typedef Dune::ParallelIndexSet ParallelIndexSet; ParallelIndexSet indices; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; typedef Dune::CollectiveCommunication Comm; Comm c; int n; BCRSMat mat = setupAnisotropic2d(N, indices, c, &n, 1); Vector b(mat.N()), x(mat.M()); x=0; randomize(mat, b); #ifndef USE_OVERLAPPINGSCHWARZ // Smoother used for the finest level FSmoother fineSmoother(mat,1,1.0); #else std::cout << "Use ovlps" << std::endl; // Smoother used for the finest level. There is an additional // template parameter to provide the subdomain solver. // Type of the subdomain vector typedef FSmoother::subdomain_vector SubdomainVector; // Create subdomain. std::size_t stride=2; SubdomainVector subdomains((((N-1)/stride)+1)*(((N-1)/stride)+1)); for(int i=0; i CSmoother; typedef Dune::Amg::CoarsenCriterion< Dune::Amg::UnSymmetricCriterion > Criterion; typedef Dune::Amg::AggregationLevelTransferPolicy TransferPolicy; // Policy for coarse linear system creation typedef Dune::Amg::OneStepAMGCoarseSolverPolicy CoarsePolicy; // Policy for coarse solver creation typedef Dune::Amg::SmootherTraits::Arguments SmootherArgs; Criterion crit; CoarsePolicy coarsePolicy=CoarsePolicy(SmootherArgs(), crit); TransferPolicy transferPolicy(crit); Operator fop(mat); Dune::Amg::TwoLevelMethod preconditioner(fop, Dune::stackobject_to_shared_ptr(fineSmoother), transferPolicy, coarsePolicy); Dune::GeneralizedPCGSolver amgCG(fop,preconditioner,.8,80,2); Dune::Amg::TwoLevelMethod preconditioner1(preconditioner); Dune::InverseOperatorResult res; std::vector amgs(NUM_THREADS, preconditioner1); std::vector args(NUM_THREADS); std::vector threads(NUM_THREADS); std::vector xs(NUM_THREADS, x); std::vector bs(NUM_THREADS, b); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve, (void*) &args[i]); } void* retval; for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); amgs.clear(); args.clear(); preconditioner.pre(x, b); amgs.resize(NUM_THREADS, preconditioner); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve1, (void*) &args[i]); } for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); amgs.clear(); args.clear(); preconditioner.pre(x, b); amgs.resize(NUM_THREADS, preconditioner); for(int i=0; i < NUM_THREADS; ++i) { args[i].amg=&amgs[i]; args[i].b=&bs[i]; args[i].x=&xs[i]; args[i].fop=&fop; pthread_create(&threads[i], NULL, solve2, (void*) &args[i]); } for(int i=0; i < NUM_THREADS; ++i) pthread_join(threads[i], &retval); // amgCG.apply(x,b,res); } int main() { testTwoLevelMethod(); return 0; } dune-istl-2.5.1/dune/istl/paamg/test/transfertest.cc000066400000000000000000000021421313314427100224260ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include template int createAggregates(Dune::Amg::AggregatesMap& aggregates, int size) { int index=0; int i=0; for(i=1; index VectorBlock; typedef Dune::BlockVector Vector; Vector b(20); Dune::Amg::AggregatesMap amap(20); int aggregates = createAggregates(amap, 20); Vector c(aggregates); b=100; typedef Dune::Amg::SequentialInformation SequentialInformation; SequentialInformation info; Dune::Amg::Transfer::restrictVector(amap, c, b, info); Dune::Amg::Transfer::prolongateVector(amap, c, b, 1); return 0; } dune-istl-2.5.1/dune/istl/paamg/test/twolevelmethodtest.cc000066400000000000000000000067361313314427100236610ustar00rootroot00000000000000#include"config.h" #include "anisotropic.hh" #include #include #include #include #include #include #include #include template void randomize(const M& mat, V& b) { V x=b; srand((unsigned)std::clock()); typedef typename V::iterator iterator; for(iterator i=x.begin(); i != x.end(); ++i) *i=(rand() / (RAND_MAX + 1.0)); mat.mv(static_cast(x), b); } void testTwoLevelMethod() { const int BS=1; int N=100; typedef Dune::ParallelIndexSet ParallelIndexSet; ParallelIndexSet indices; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; typedef Dune::CollectiveCommunication Comm; Comm c; int n; BCRSMat mat = setupAnisotropic2d(N, indices, c, &n, 1); Vector b(mat.N()), x(mat.M()); x=0; randomize(mat, b); #ifndef USE_OVERLAPPINGSCHWARZ // Smoother used for the finest level typedef Dune::SeqSSOR FSmoother; FSmoother fineSmoother(mat,1,1.0); #else // Smoother used for the finest level. There is an additional // template parameter to provide the subdomain solver. typedef Dune::SeqOverlappingSchwarz FSmoother; // Type of the subdomain vector typedef FSmoother::subdomain_vector SubdomainVector; // Create subdomain. std::size_t stride=2; SubdomainVector subdomains((((N-1)/stride)+1)*(((N-1)/stride)+1)); for(int i=0; i CSmoother; typedef Dune::Amg::SmootherTraits::Arguments SmootherArgs; typedef Dune::Amg::CoarsenCriterion< Dune::Amg::UnSymmetricCriterion > Criterion; typedef Dune::Amg::AggregationLevelTransferPolicy TransferPolicy; typedef Dune::Amg::OneStepAMGCoarseSolverPolicy CoarsePolicy; // Policy for coarse solver creation Criterion crit; CoarsePolicy coarsePolicy=CoarsePolicy(SmootherArgs(), crit); TransferPolicy transferPolicy(crit); Operator fop(mat); Dune::Amg::TwoLevelMethod preconditioner(fop, Dune::stackobject_to_shared_ptr(fineSmoother), transferPolicy, coarsePolicy); Dune::GeneralizedPCGSolver amgCG(fop,preconditioner,.8,80,2); Dune::Amg::TwoLevelMethod preconditioner1(preconditioner); Dune::InverseOperatorResult res; amgCG.apply(x,b,res); } int main() { testTwoLevelMethod(); return 0; } dune-istl-2.5.1/dune/istl/paamg/transfer.hh000066400000000000000000000202761313314427100205710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_AMGTRANSFER_HH #define DUNE_AMGTRANSFER_HH #include #include #include #include #include #include #include namespace Dune { namespace Amg { /** * @addtogroup ISTL_PAAMG * * @{ */ /** @file * @author Markus Blatt * @brief Prolongation and restriction for amg. */ template class Transfer { public: typedef V1 Vertex; typedef V2 Vector; template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, Vector& fineRedist,T1 damp, R& redistributor=R()); template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, T1 damp); static void restrictVector(const AggregatesMap& aggregates, Vector& coarse, const Vector& fine, T& comm); }; template class Transfer { public: typedef V Vertex; typedef V1 Vector; typedef RedistributeInformation Redist; template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, Vector& fineRedist, T1 damp, const SequentialInformation& comm=SequentialInformation(), const Redist& redist=Redist()); template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, T1 damp, const SequentialInformation& comm=SequentialInformation()); static void restrictVector(const AggregatesMap& aggregates, Vector& coarse, const Vector& fine, const SequentialInformation& comm); }; #if HAVE_MPI template class Transfer > { public: typedef V Vertex; typedef V1 Vector; typedef RedistributeInformation > Redist; template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, Vector& fineRedist, T3 damp, OwnerOverlapCopyCommunication& comm, const Redist& redist); template static void prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, T3 damp, OwnerOverlapCopyCommunication& comm); static void restrictVector(const AggregatesMap& aggregates, Vector& coarse, const Vector& fine, OwnerOverlapCopyCommunication& comm); }; #endif template template inline void Transfer::prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, Vector& fineRedist, T damp, const SequentialInformation& comm, const Redist& redist) { DUNE_UNUSED_PARAMETER(fineRedist); DUNE_UNUSED_PARAMETER(comm); DUNE_UNUSED_PARAMETER(redist); prolongateVector(aggregates, coarse, fine, damp); } template template inline void Transfer::prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, T damp, const SequentialInformation& comm) { DUNE_UNUSED_PARAMETER(comm); typedef typename Vector::iterator Iterator; Iterator end = coarse.end(); Iterator begin= coarse.begin(); for(; begin!=end; ++begin) *begin*=damp; end=fine.end(); begin=fine.begin(); for(Iterator block=begin; block != end; ++block) { std::ptrdiff_t index=block-begin; const Vertex& vertex = aggregates[index]; if(vertex != AggregatesMap::ISOLATED) *block += coarse[aggregates[index]]; } } template inline void Transfer::restrictVector(const AggregatesMap& aggregates, Vector& coarse, const Vector& fine, const SequentialInformation& comm) { DUNE_UNUSED_PARAMETER(comm); // Set coarse vector to zero coarse=0; typedef typename Vector::const_iterator Iterator; Iterator end = fine.end(); Iterator begin=fine.begin(); for(Iterator block=begin; block != end; ++block) { const Vertex& vertex = aggregates[block-begin]; if(vertex != AggregatesMap::ISOLATED) coarse[vertex] += *block; } } #if HAVE_MPI template template inline void Transfer >::prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, Vector& fineRedist, T3 damp, OwnerOverlapCopyCommunication& comm, const Redist& redist) { if(fineRedist.size()>0) // we operated on the coarse level Transfer::prolongateVector(aggregates, coarse, fineRedist, damp); // TODO This could be accomplished with one communication, too! redist.redistributeBackward(fine, fineRedist); comm.copyOwnerToAll(fine,fine); } template template inline void Transfer >::prolongateVector(const AggregatesMap& aggregates, Vector& coarse, Vector& fine, T3 damp, OwnerOverlapCopyCommunication& comm) { DUNE_UNUSED_PARAMETER(comm); Transfer::prolongateVector(aggregates, coarse, fine, damp); } template inline void Transfer >::restrictVector(const AggregatesMap& aggregates, Vector& coarse, const Vector& fine, OwnerOverlapCopyCommunication& comm) { Transfer::restrictVector(aggregates, coarse, fine, SequentialInformation()); // We need this here to avoid it in the smoothers on the coarse level. // There (in the preconditioner d is const. comm.project(coarse); } #endif /** @} */ } // namspace Amg } // namspace Dune #endif dune-istl-2.5.1/dune/istl/paamg/twolevelmethod.hh000066400000000000000000000414461313314427100220110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_TWOLEVELMETHOD_HH #define DUNE_ISTL_TWOLEVELMETHOD_HH #include #include #include"amg.hh" #include"galerkin.hh" #include #include /** * @addtogroup ISTL_PAAMG * @{ * @file * @author Markus Blatt * @brief Algebraic twolevel methods. */ namespace Dune { namespace Amg { /** * @brief Abstract base class for transfer between levels and creation * of the coarse level system. * * @tparam FO The type of the linear operator of the finel level system. Has to be * derived from AssembledLinearOperator. * @tparam CO The type of the linear operator of the coarse level system. Has to be * derived from AssembledLinearOperator. */ template class LevelTransferPolicy { public: /** * @brief The linear operator of the finel level system. Has to be * derived from AssembledLinearOperator. */ typedef FO FineOperatorType; /** * @brief The type of the range of the fine level operator. */ typedef typename FineOperatorType::range_type FineRangeType; /** * @brief The type of the domain of the fine level operator. */ typedef typename FineOperatorType::domain_type FineDomainType; /** * @brief The linear operator of the finel level system. Has to be * derived from AssembledLinearOperator. */ typedef CO CoarseOperatorType; /** * @brief The type of the range of the coarse level operator. */ typedef typename CoarseOperatorType::range_type CoarseRangeType; /** * @brief The type of the domain of the coarse level operator. */ typedef typename CoarseOperatorType::domain_type CoarseDomainType; /** * @brief Get the coarse level operator. * @return A shared pointer to the coarse level system. */ std::shared_ptr& getCoarseLevelOperator() { return operator_; } /** * @brief Get the coarse level right hand side. * @return The coarse level right hand side. */ CoarseRangeType& getCoarseLevelRhs() { return rhs_; } /** * @brief Get the coarse level left hand side. * @return The coarse level leftt hand side. */ CoarseDomainType& getCoarseLevelLhs() { return lhs_; } /** * @brief Transfers the data to the coarse level. * * Restricts the residual to the right hand side of the * coarse level system and initialies the left hand side * of the coarse level system. These can afterwards be accessed * usinf getCoarseLevelRhs() and getCoarseLevelLhs(). * @param fineDefect The current residual of the fine level system. */ virtual void moveToCoarseLevel(const FineRangeType& fineRhs)=0; /** * @brief Updates the fine level linear system after the correction * of the coarse levels system. * * After returning from this function the coarse level correction * will have been added to fine level system. * @param[inout] fineLhs The left hand side of the fine level to update * with the coarse level correction. */ virtual void moveToFineLevel(FineDomainType& fineLhs)=0; /** * @brief Algebraically creates the coarse level system. * * After returning from this function the coarse level operator * can be accessed using getCoarseLevelOperator(). * @param fineOperator The operator of the fine level system. */ virtual void createCoarseLevelSystem(const FineOperatorType& fineOperator)=0; /** @brief Clone the current object. */ virtual LevelTransferPolicy* clone() const =0; /** @brief Destructor. */ virtual ~LevelTransferPolicy(){} protected: /** @brief The coarse level rhs. */ CoarseRangeType rhs_; /** @brief The coarse level lhs. */ CoarseDomainType lhs_; /** @brief the coarse level linear operator. */ std::shared_ptr operator_; }; /** * @brief A LeveTransferPolicy that used aggregation to construct the coarse level system. * @tparam O The type of the fine and coarse level operator. * @tparam C The criterion that describes the aggregation procedure. */ template class AggregationLevelTransferPolicy : public LevelTransferPolicy { typedef Dune::Amg::AggregatesMap AggregatesMap; public: typedef LevelTransferPolicy FatherType; typedef C Criterion; typedef SequentialInformation ParallelInformation; AggregationLevelTransferPolicy(const Criterion& crit) : criterion_(crit) {} void createCoarseLevelSystem(const O& fineOperator) { prolongDamp_ = criterion_.getProlongationDampingFactor(); GalerkinProduct productBuilder; typedef typename Dune::Amg::MatrixGraph MatrixGraph; typedef typename Dune::Amg::PropertiesGraph PropertiesGraph; MatrixGraph mg(fineOperator.getmat()); PropertiesGraph pg(mg,Dune::IdentityMap(),Dune::IdentityMap()); typedef NegateSet OverlapFlags; aggregatesMap_.reset(new AggregatesMap(pg.maxVertex()+1)); int noAggregates, isoAggregates, oneAggregates, skippedAggregates; std::tie(noAggregates, isoAggregates, oneAggregates, skippedAggregates) = aggregatesMap_->buildAggregates(fineOperator.getmat(), pg, criterion_, true); std::cout<<"no aggregates="< class SeqPardiso : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; typedef typename M::RowIterator RowIterator; typedef typename M::ColIterator ColIterator; // define the category enum { //! \brief The category the preconditioner is part of category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param A The matrix to operate on. */ SeqPardiso (const M& A) : A_(A) { mtype_ = 11; nrhs_ = 1; num_procs_ = 1; maxfct_ = 1; mnum_ = 1; msglvl_ = 0; error_ = 0; n_ = A_.N(); int nnz = 0; RowIterator endi = A_.end(); for (RowIterator i = A_.begin(); i != endi; ++i) { ColIterator endj = (*i).end(); for (ColIterator j = (*i).begin(); j != endj; ++j) { if (j->size() != 1) DUNE_THROW(NotImplemented, "SeqPardiso: column blocksize != 1."); nnz++; } } std::cout << "dimension = " << n_ << ", number of nonzeros = " << nnz << std::endl; a_ = new double[nnz]; ia_ = new int[n_+1]; ja_ = new int[nnz]; int count = 0; for (RowIterator i = A_.begin(); i != endi; ++i) { ia_[i.index()] = count+1; ColIterator endj = (*i).end(); for (ColIterator j = (*i).begin(); j != endj; ++j) { a_[count] = *j; ja_[count] = j.index()+1; count++; } } ia_[n_] = count+1; pardisoinit(pt_, &mtype_, &solver_, iparm_, dparm_, &error_); int phase = 11; int idum; double ddum; iparm_[2] = num_procs_; pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase, &n_, a_, ia_, ja_, &idum, &nrhs_, iparm_, &msglvl_, &ddum, &ddum, &error_, dparm_); if (error_ != 0) DUNE_THROW(MathError, "Constructor SeqPardiso: Factorization failed. Error code " << error_); std::cout << "Constructor SeqPardiso: Factorization completed." << std::endl; } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) {} /*! \brief Apply the preconditioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { int phase = 33; iparm_[7] = 1; /* Max numbers of iterative refinement steps. */ int idum; double x[n_]; double b[n_]; for (int i = 0; i < n_; i++) { x[i] = v[i]; b[i] = d[i]; } pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase, &n_, a_, ia_, ja_, &idum, &nrhs_, iparm_, &msglvl_, b, x, &error_, dparm_); if (error_ != 0) DUNE_THROW(MathError, "SeqPardiso.apply: Backsolve failed. Error code " << error_); for (int i = 0; i < n_; i++) v[i] = x[i]; std::cout << "SeqPardiso: Backsolve completed." << std::endl; } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) {} ~SeqPardiso() { int phase = -1; // Release internal memory. int idum; double ddum; pardiso(pt_, &maxfct_, &mnum_, &mtype_, &phase, &n_, &ddum, ia_, ja_, &idum, &nrhs_, iparm_, &msglvl_, &ddum, &ddum, &error_, dparm_); delete[] a_; delete[] ia_; delete[] ja_; } private: M A_; //!< The matrix we operate on. int n_; //!< dimension of the system double *a_; //!< matrix values int *ia_; //!< indices to rows int *ja_; //!< column indices int mtype_; //!< matrix type, currently only 11 (real unsymmetric matrix) is supported int solver_; //!< solver method int nrhs_; //!< number of right hand sides void *pt_[64]; //!< internal solver memory pointer int iparm_[64]; //!< Pardiso integer control parameters double dparm_[64]; //!< Pardiso double control parameters int maxfct_; //!< Maximum number of numerical factorizations int mnum_; //!< Which factorization to use int msglvl_; //!< flag to print statistical information int error_; //!< error flag int num_procs_; //!< number of processors }; template struct IsDirectSolver > { enum { value=true}; }; } // end namespace Dune #endif //HAVE_PARDISO #endif dune-istl-2.5.1/dune/istl/preconditioner.hh000066400000000000000000000054471313314427100207070ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_PRECONDITIONER_HH #define DUNE_ISTL_PRECONDITIONER_HH namespace Dune { /** * @addtogroup ISTL_Prec * @{ */ //===================================================================== /*! \brief Base class for matrix free definition of preconditioners. Note that the operator, which is the basis for the preconditioning, is supplied to the preconditioner from the outside in the constructor or some other method. This interface allows the encapsulation of all parallelization aspects into the preconditioners. \tparam X Type of the update \tparam Y Type of the defect */ //===================================================================== template class Preconditioner { public: //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; /*! \brief Prepare the preconditioner. A solver solves a linear operator equation A(x)=b by applying one or several steps of the preconditioner. The method pre() is called before the first apply operation. b and x are right hand side and solution vector of the linear system respectively. It may. e.g., scale the system, allocate memory or compute a (I)LU decomposition. Note: The ILU decomposition could also be computed in the constructor or with a separate method of the derived method if several linear systems with the same matrix are to be solved. \param x The left hand side of the equation. \param b The right hand side of the equation. */ virtual void pre (X& x, Y& b) = 0; /*! \brief Apply one step of the preconditioner to the system A(v)=d. On entry v=0 and d=b-A(x) (although this might not be computed in that way. On exit v contains the update, i.e one step computes \f$ v = M^{-1} d \f$ where \f$ M \f$ is the approximate inverse of the operator \f$ A \f$ characterizing the preconditioner. \param[out] v The update to be computed \param d The current defect. */ virtual void apply (X& v, const Y& d) = 0; /*! \brief Clean up. This method is called after the last apply call for the linear system to be solved. Memory may be deallocated safely here. x is the solution of the linear equation. \param x The right hand side of the equation. */ virtual void post (X& x) = 0; // every abstract base class has a virtual destructor virtual ~Preconditioner () {} }; /** * @} */ } #endif dune-istl-2.5.1/dune/istl/preconditioners.hh000066400000000000000000000437701313314427100210730ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_PRECONDITIONERS_HH #define DUNE_ISTL_PRECONDITIONERS_HH #include #include #include #include #include #include #include "preconditioner.hh" #include "solver.hh" #include "solvercategory.hh" #include "istlexception.hh" #include "matrixutils.hh" #include "gsetc.hh" #include "ilu.hh" namespace Dune { /** @defgroup ISTL_Prec Preconditioners * @ingroup ISTL_Solvers * * All of our \ref ISTL_Solvers "Krylow solvers" are preconditioned versions. * There are sequential preconditioners (e,g. SeqJacobi, SeqSOR, SeqSSOR) as well as parallel preconditioners * (e.g. AMG, BlockPreconditioner) available for plugging them into the solvers * together with matching ScalarProducts. * * Some of the available preconditioners (e.g. SeqJacobi, SeqSOR, SeqSSOR)) * may be given an aditional int as a template parameter, the block recursion level. * These preconditioners * can be used on block-recursive matrices with an arbitrary hierarchy depth * (eg. BCRSMatrix > >. Given a block recursion level * \f$k\f$ those preconditioners work as * normal on the offdiagonal blocks, treating them as traditional matrix * entries. For the diagonal values a special procedure applies: If * \f$k>1\f$ the diagonal is treated as a matrix itself and the preconditioner * is applied recursively on the matrix representing the diagonal value * \f$D=A_{ii}\f$ with block level \f$k-1\f$. For the case that \f$k=1\f$ the diagonal * is treated as a * matrix entry resulting in a linear solve or an identity operation * depending on the algorithm. */ /** @addtogroup ISTL_Prec @{ */ /** \file \brief Define general preconditioner interface Wrap the methods implemented by ISTL in this interface. However, the interface is extensible such that new preconditioners can be implemented and used with the solvers. */ /** * @brief Turns an InverseOperator into a Preconditioner. * @tparam O The type of the inverse operator to wrap. */ template class InverseOperator2Preconditioner : public Preconditioner { public: //! \brief The domain type of the preconditioner. typedef typename O::domain_type domain_type; //! \brief The range type of the preconditioner. typedef typename O::range_type range_type; //! \brief The field type of the preconditioner. typedef typename range_type::field_type field_type; typedef O InverseOperator; // define the category enum { //! \brief The category the preconditioner is part of. category=c }; /** * @brief Construct the preconditioner from the solver * @param inverse_operator The inverse operator to wrap. */ InverseOperator2Preconditioner(InverseOperator& inverse_operator) : inverse_operator_(inverse_operator) {} void pre(domain_type&,range_type&) {} void apply(domain_type& v, const range_type& d) { InverseOperatorResult res; range_type copy(d); inverse_operator_.apply(v, copy, res); } void post(domain_type&) {} private: InverseOperator& inverse_operator_; }; //===================================================================== // Implementation of this interface for sequential ISTL-preconditioners //===================================================================== /*! \brief Sequential SSOR preconditioner. Wraps the naked ISTL generic SSOR preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l The block level to invert. Default is 1 */ template class SeqSSOR : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. */ SeqSSOR (const M& A, int n, field_type w) : _A_(A), _n(n), _w(w) { CheckIfDiagonalPresent::check(_A_); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the preconditioner \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { for (int i=0; i<_n; i++) { bsorf(_A_,v,d,_w,BL()); bsorb(_A_,v,d,_w,BL()); } } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief The matrix we operate on. const M& _A_; //! \brief The number of steps to do in apply int _n; //! \brief The relaxation factor to use field_type _w; }; /*! \brief Sequential SOR preconditioner. Wraps the naked ISTL generic SOR preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l The block level to invert. Default is 1 */ template class SeqSOR : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. */ SeqSOR (const M& A, int n, field_type w) : _A_(A), _n(n), _w(w) { CheckIfDiagonalPresent::check(_A_); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the preconditioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { this->template apply(v,d); } /*! \brief Apply the preconditioner in a special direction. The template parameter forward indications the direction the smoother is applied. If true The application is started at the lowest index in the vector v, if false at the highest index of vector v. */ template void apply(X& v, const Y& d) { if(forward) for (int i=0; i<_n; i++) { bsorf(_A_,v,d,_w,BL()); } else for (int i=0; i<_n; i++) { bsorb(_A_,v,d,_w,BL()); } } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief the matrix we operate on. const M& _A_; //! \brief The number of steps to perform in apply. int _n; //! \brief The relaxation factor to use. field_type _w; }; /*! \brief Sequential Gauss Seidel preconditioner Wraps the naked ISTL generic block Gauss-Seidel preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l The block level to invert. Default is 1 */ template class SeqGS : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. */ SeqGS (const M& A, int n, field_type w) : _A_(A), _n(n), _w(w) { CheckIfDiagonalPresent::check(_A_); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the preconditioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { for (int i=0; i<_n; i++) { dbgs(_A_,v,d,_w,BL()); } } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief The matrix we operate on. const M& _A_; //! \brief The number of iterations to perform in apply. int _n; //! \brief The relaxation factor to use. field_type _w; }; /*! \brief The sequential jacobian preconditioner. Wraps the naked ISTL generic block Jacobi preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l The block level to invert. Default is 1 */ template class SeqJac : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. */ SeqJac (const M& A, int n, field_type w) : _A_(A), _n(n), _w(w) { CheckIfDiagonalPresent::check(_A_); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the preconditioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { for (int i=0; i<_n; i++) { dbjac(_A_,v,d,_w,BL()); } } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief The matrix we operate on. const M& _A_; //! \brief The number of steps to perform during apply. int _n; //! \brief The relaxation parameter to use. field_type _w; }; /*! \brief Sequential ILU0 preconditioner. Wraps the naked ISTL generic ILU0 preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l Ignored. Just there to have the same number of template arguments as other preconditioners. */ template class SeqILU0 : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param w The relaxation factor. */ SeqILU0 (const M& A, field_type w) : ILU(A) // copy A { _w =w; bilu0_decomposition(ILU); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the preconditoner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { bilu_backsolve(ILU,v,d); v *= _w; } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief The relaxation factor to use. field_type _w; //! \brief The ILU0 decomposition of the matrix. matrix_type ILU; }; /*! \brief Sequential ILU(n) preconditioner. Wraps the naked ISTL generic ILU(n) preconditioner into the solver framework. \tparam M The matrix type to operate on \tparam X Type of the update \tparam Y Type of the defect \tparam l Ignored. Just there to have the same number of template arguments as other preconditioners. */ template class SeqILUn : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef typename std::remove_const::type matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. */ SeqILUn (const M& A, int n, field_type w) : ILU(A.N(),A.M(),M::row_wise) { _n = n; _w = w; bilu_decomposition(A,n,ILU); } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the precondioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { bilu_backsolve(ILU,v,d); v *= _w; } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief ILU(n) decomposition of the matrix we operate on. matrix_type ILU; //! \brief The number of steps to perform in apply. int _n; //! \brief The relaxation factor to use. field_type _w; }; /*! \brief Richardson preconditioner. Multiply simply by a constant. \tparam X Type of the update \tparam Y Type of the defect */ template class Richardson : public Preconditioner { public: //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; // define the category enum { //! \brief The category the preconditioner is part of. category=SolverCategory::sequential }; /*! \brief Constructor. Constructor gets all parameters to operate the prec. \param w The relaxation factor. */ Richardson (field_type w=1.0) { _w = w; } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(b); } /*! \brief Apply the precondioner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { v = d; v *= _w; } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { DUNE_UNUSED_PARAMETER(x); } private: //! \brief The relaxation factor to use. field_type _w; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/repartition.hh000066400000000000000000002013201313314427100202070ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_REPARTITION_HH #define DUNE_ISTL_REPARTITION_HH #include #include #include #if HAVE_PARMETIS // Explicitly use C linkage as scotch does not extern "C" in its headers. // Works because ParMETIS/METIS checks whether compiler is C++ and otherwise // does not use extern "C". Therfore no nested extern "C" will be created extern "C" { #include } #endif #include #include #include #include #include #include #include #include #include #include #include /** * @file * @brief Functionality for redistributing a parallel index set using graph partitioning. * * Refactored version of an intern. * @author Markus Blatt */ namespace Dune { #if HAVE_MPI /** * @brief Fills the holes in an index set. * * In general the index set only needs to know those indices * where communication my occur. In usual FE computations these * are just those near the processor boundaries. * * For the repartitioning we need to know all all indices for which data is stored. * The missing indices will be created in this method. * * @param graph The graph to reparition. * @param oocomm The communication information. */ template void fillIndexSetHoles(const G& graph, Dune::OwnerOverlapCopyCommunication& oocomm) { typedef typename Dune::OwnerOverlapCopyCommunication::ParallelIndexSet IndexSet; typedef typename IndexSet::LocalIndex::Attribute Attribute; IndexSet& indexSet = oocomm.indexSet(); const typename Dune::OwnerOverlapCopyCommunication::GlobalLookupIndexSet& lookup =oocomm.globalLookup(); // The type of the const vertex iterator. typedef typename G::ConstVertexIterator VertexIterator; std::size_t sum=0, needed = graph.noVertices()-indexSet.size(); std::vector neededall(oocomm.communicator().size(), 0); MPI_Allgather(&needed, 1, MPITraits::getType() , &(neededall[0]), 1, MPITraits::getType(), oocomm.communicator()); for(int i=0; iglobal()); //Process p creates global indices consecutively //starting atmaxgi+\sum_{i=1}^p neededall[i] // All created indices are owned by the process maxgi=oocomm.communicator().max(maxgi); ++maxgi; //Sart with the next free index. for(int i=0; i > > globalIndices; storeGlobalIndicesOfRemoteIndices(globalIndices, oocomm.remoteIndices()); indexSet.beginResize(); for(VertexIterator vertex = graph.begin(), vend=graph.end(); vertex != vend; ++vertex) { const typename IndexSet::IndexPair* pair=lookup.pair(*vertex); if(pair==0) { // No index yet, add new one indexSet.add(maxgi, typename IndexSet::LocalIndex(*vertex, OwnerOverlapCopyAttributeSet::owner, false)); ++maxgi; } } indexSet.endResize(); repairLocalIndexPointers(globalIndices, oocomm.remoteIndices(), indexSet); oocomm.freeGlobalLookup(); oocomm.buildGlobalLookup(); #ifdef DEBUG_REPART std::cout<<"Holes are filled!"< 3 typedef idx_t idxtype; #else typedef int idxtype; #endif // PARMETIS_MAJOR_VERSION > 3 #else typedef std::size_t idxtype; #endif // #if HAVE_PARMETIS template ParmetisDuneIndexMap(const Graph& graph, const OOComm& com); int toParmetis(int i) const { return duneToParmetis[i]; } int toLocalParmetis(int i) const { return duneToParmetis[i]-base_; } int operator[](int i) const { return duneToParmetis[i]; } int toDune(int i) const { return parmetisToDune[i]; } std::vector::size_type numOfOwnVtx() const { return parmetisToDune.size(); } idxtype* vtxDist() { return &vtxDist_[0]; } int globalOwnerVertices; private: int base_; std::vector duneToParmetis; std::vector parmetisToDune; // range of vertices for processor i: vtxdist[i] to vtxdist[i+1] (parmetis global) std::vector vtxDist_; }; template ParmetisDuneIndexMap::ParmetisDuneIndexMap(const G& graph, const OOComm& oocomm) : duneToParmetis(graph.noVertices(), -1), vtxDist_(oocomm.communicator().size()+1) { int npes=oocomm.communicator().size(), mype=oocomm.communicator().rank(); typedef typename OOComm::ParallelIndexSet::const_iterator Iterator; typedef typename OOComm::OwnerSet OwnerSet; int numOfOwnVtx=0; Iterator end = oocomm.indexSet().end(); for(Iterator index = oocomm.indexSet().begin(); index != end; ++index) { if (OwnerSet::contains(index->local().attribute())) { numOfOwnVtx++; } } parmetisToDune.resize(numOfOwnVtx); std::vector globalNumOfVtx(npes); // make this number available to all processes MPI_Allgather(&numOfOwnVtx, 1, MPI_INT, &(globalNumOfVtx[0]), 1, MPI_INT, oocomm.communicator()); int base=0; vtxDist_[0] = 0; for(int i=0; ilocal().attribute())) { // assign and count the index parmetisToDune[base-base_]=index->local(); duneToParmetis[index->local()] = base++; } } // At this point, every process knows the ParMETIS global index // of it's owner vertices. The next step is to get the // ParMETIS global index of the overlap vertices from the // associated processes. To do this, the Dune::Interface class // is used. #ifdef DEBUG_REPART std::cout < void buildSendInterface(const std::vector& toPart, const IS& idxset) { std::map sizes; typedef typename IS::const_iterator IIter; for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i) if(Flags::contains(i->local().attribute())) ++sizes[toPart[i->local()]]; // Allocate the necessary space typedef std::map::const_iterator MIter; for(MIter i=sizes.begin(), end=sizes.end(); i!=end; ++i) interfaces()[i->first].first.reserve(i->second); //Insert the interface information typedef typename IS::const_iterator IIter; for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i) if(Flags::contains(i->local().attribute())) interfaces()[toPart[i->local()]].first.add(i->local()); } void reserveSpaceForReceiveInterface(int proc, int size) { interfaces()[proc].second.reserve(size); } void addReceiveIndex(int proc, std::size_t idx) { interfaces()[proc].second.add(idx); } template void buildReceiveInterface(std::vector >& indices) { typedef typename std::vector >::const_iterator VIter; std::size_t i=0; for(VIter idx=indices.begin(); idx!= indices.end(); ++idx) { interfaces()[idx->second].second.add(i++); } } ~RedistributeInterface() {} }; namespace { // idxtype is given by ParMETIS package typedef ParmetisDuneIndexMap :: idxtype idxtype ; /** * @brief Fills send buffer with global indices. * * @param ownerVec the owner vertices to send * @param overlapSet the overlap vertices to send * @param sendBuf the send buffer * @param buffersize The size of the send buffer * @param comm Communicator for the send. */ template void createSendBuf(std::vector& ownerVec, std::set& overlapVec, std::set& neighbors, char *sendBuf, int buffersize, MPI_Comm comm) { // Pack owner vertices std::size_t s=ownerVec.size(); int pos=0; if(s==0) ownerVec.resize(1); // otherwise would read beyond the memory bound MPI_Pack(&s, 1, MPITraits::getType(), sendBuf, buffersize, &pos, comm); MPI_Pack(&(ownerVec[0]), s, MPITraits::getType(), sendBuf, buffersize, &pos, comm); s = overlapVec.size(); MPI_Pack(&s, 1, MPITraits::getType(), sendBuf, buffersize, &pos, comm); typedef typename std::set::iterator Iter; for(Iter i=overlapVec.begin(), end= overlapVec.end(); i != end; ++i) MPI_Pack(const_cast(&(*i)), 1, MPITraits::getType(), sendBuf, buffersize, &pos, comm); s=neighbors.size(); MPI_Pack(&s, 1, MPITraits::getType(), sendBuf, buffersize, &pos, comm); typedef typename std::set::iterator IIter; for(IIter i=neighbors.begin(), end= neighbors.end(); i != end; ++i) MPI_Pack(const_cast(&(*i)), 1, MPI_INT, sendBuf, buffersize, &pos, comm); } /** * @brief save the values of the received MPI buffer to the owner/overlap vectors * * @param recvBuf the receive buffer. * @param ownerVec the vector to store the owner indices in. * @param overlapVec the set to store the overlap indices in. * @param comm The communicator used in the receive. */ template void saveRecvBuf(char *recvBuf, int bufferSize, std::vector >& ownerVec, std::set& overlapVec, std::set& neighbors, RedistributeInterface& inf, int from, MPI_Comm comm) { std::size_t size; int pos=0; // unpack owner vertices MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits::getType(), comm); inf.reserveSpaceForReceiveInterface(from, size); ownerVec.reserve(ownerVec.size()+size); for(; size!=0; --size) { GI gi; MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits::getType(), comm); ownerVec.push_back(std::make_pair(gi,from)); } // unpack overlap vertices MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits::getType(), comm); typename std::set::iterator ipos = overlapVec.begin(); Dune::dverb << "unpacking "<::getType(), comm); ipos=overlapVec.insert(ipos, gi); } //unpack neighbors MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits::getType(), comm); Dune::dverb << "unpacking "<::iterator npos = neighbors.begin(); for(; size!=0; --size) { int n; MPI_Unpack(recvBuf, bufferSize, &pos, &n, 1, MPI_INT, comm); npos=neighbors.insert(npos, n); } } /** * @brief Find the optimal domain number for a given process * * The estimation is necessary because the result of ParMETIS for * the new partition is only a domain/set number and not a process number. * * @param comm the MPI communicator * @param *part the result array of the ParMETIS repartition * @param numOfOwnVtx the number of owner vertices * @param nparts the number of target partitions/processes * @param *myDomain the optimal output domain number * @param domainMapping[] the array of output domain mapping */ template void getDomain(const MPI_Comm& comm, T *part, int numOfOwnVtx, int nparts, int *myDomain, std::vector &domainMapping) { int npes, mype; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &mype); MPI_Status status; *myDomain = -1; int i=0; int j=0; std::vector domain(nparts, 0); std::vector assigned(npes, 0); // init domain Mapping domainMapping.assign(domainMapping.size(), -1); // count the occurrence of domains for (i=0; i domainMatrix(npes * nparts, -1); // init buffer with the own domain int *buf = new int[nparts]; for (i=0; i unassigned; for(i=0; i::iterator next_free = assigned.begin(); for(typename std::set::iterator domain = unassigned.begin(), end = unassigned.end(); domain != end; ++domain) { next_free = std::find_if(next_free, assigned.end(), std::bind2nd(std::less(), 1)); assert(next_free != assigned.end()); domainMapping[*domain] = next_free-assigned.begin(); *next_free = 1; } } struct SortFirst { template bool operator()(const T& t1, const T& t2) const { return t1 void mergeVec(std::vector >& ownerVec, std::set& overlapSet) { typedef typename std::vector >::const_iterator VIter; #ifdef DEBUG_REPART // Safety check for duplicates. if(ownerVec.size()>0) { VIter old=ownerVec.begin(); for(VIter i=old+1, end=ownerVec.end(); i != end; old=i++) { if(i->first==old->first) { std::cerr<<"Value at indes"<first<<","<second<<"]==[" <first<<","<second<<"]"<::iterator SIter; VIter v=ownerVec.begin(), vend=ownerVec.end(); for(SIter s=overlapSet.begin(), send=overlapSet.end(); s!=send;) { while(v!=vend && v->first<*s) ++v; if(v!=vend && v->first==*s) { // Move to the next element before erasing // thus s stays valid! SIter tmp=s; ++s; overlapSet.erase(tmp); }else ++s; } } /** * @brief get the non-owner neighbors of a given vertex * * For a given vertex, get the index of all non-owner neighbor vertices are * computed. * * @param g the local graph * @param part Where the vertices become owner * @param vtx the given vertex * @param parmetisVtxMapping mapping between Dune and ParMETIS vertices * @param indexSet the indexSet * @param neighbor the output set to store the neighbor indices in. */ template void getNeighbor(const Graph& g, std::vector& part, typename Graph::VertexDescriptor vtx, const IS& indexSet, int toPe, std::set& neighbor, std::set& neighborProcs) { typedef typename Graph::ConstEdgeIterator Iter; for(Iter edge=g.beginEdges(vtx), end=g.endEdges(vtx); edge!=end; ++edge) { const typename IS::IndexPair* pindex = indexSet.pair(edge.target()); assert(pindex); if(part[pindex->local()]!=toPe || !OwnerSet::contains(pindex->local().attribute())) { // is sent to another process and therefore becomes overlap neighbor.insert(pindex->global()); neighborProcs.insert(part[pindex->local()]); } } } template void my_push_back(std::vector& ownerVec, const I& index, int proc) { DUNE_UNUSED_PARAMETER(proc); ownerVec.push_back(index); } template void my_push_back(std::vector >& ownerVec, const I& index, int proc) { ownerVec.push_back(std::make_pair(index,proc)); } template void reserve(std::vector&, RedistributeInterface&, int) {} template void reserve(std::vector >& ownerVec, RedistributeInterface& redist, int proc) { redist.reserveSpaceForReceiveInterface(proc, ownerVec.size()); } /** * @brief get the owner- and overlap vertices for giving source and destination processes. * * The estimation is based on the vtxdist and the global PARMETIS mapping * generated before. The owner- and overlap vertices are stored in two * separate vectors * * @param graph The local graph. * @param part The target domain of the local vertices (result of PARMETIS). * @param indexSet The indexSet of the given graph. * @param parmetisVtxMapping The mapping between PARMETIS index * and DUNE global index. * @param myPe The source process number. * @param toPe The target process number. * @param ownerVec The output vector containing all owner vertices. * @param overlapSet The output vector containing all overlap vertices. */ template void getOwnerOverlapVec(const G& graph, std::vector& part, IS& indexSet, int myPe, int toPe, std::vector& ownerVec, std::set& overlapSet, RedistributeInterface& redist, std::set& neighborProcs) { DUNE_UNUSED_PARAMETER(myPe); //typedef typename IndexSet::const_iterator Iterator; typedef typename IS::const_iterator Iterator; for(Iterator index = indexSet.begin(); index != indexSet.end(); ++index) { // Only Process owner vertices, the others are not in the parmetis graph. if(OwnerSet::contains(index->local().attribute())) { if(part[index->local()]==toPe) { getNeighbor(graph, part, index->local(), indexSet, toPe, overlapSet, neighborProcs); my_push_back(ownerVec, index->global(), toPe); } } } reserve(ownerVec, redist, toPe); } /** * @brief check if the given vertex is a owner vertex * * @param indexSet the indexSet * @param index the given vertex index */ template inline bool isOwner(IS& indexSet, int index) { const typename IS::IndexPair* pindex=indexSet.pair(index); assert(pindex); return F::contains(pindex->local().attribute()); } class BaseEdgeFunctor { public: BaseEdgeFunctor(idxtype* adj,const ParmetisDuneIndexMap& data) : i_(), adj_(adj), data_(data) {} template void operator()(const T& edge) { // Get the egde weight // const Weight& weight=edge.weight(); adj_[i_] = data_.toParmetis(edge.target()); i_++; } std::size_t index() { return i_; } private: std::size_t i_; idxtype* adj_; const ParmetisDuneIndexMap& data_; }; template struct EdgeFunctor : public BaseEdgeFunctor { EdgeFunctor(idxtype* adj, const ParmetisDuneIndexMap& data, std::size_t) : BaseEdgeFunctor(adj, data) {} idxtype* getWeights() { return NULL; } void free(){} }; template class EdgeFunctor > : public BaseEdgeFunctor { public: EdgeFunctor(idxtype* adj, const ParmetisDuneIndexMap& data, std::size_t s) : BaseEdgeFunctor(adj, data) { weight_=new idxtype[s]; } template void operator()(const T& edge) { weight_[index()]=edge.properties().depends() ? 3 : 1; BaseEdgeFunctor::operator()(edge); } idxtype* getWeights() { return weight_; } void free(){ if(weight_!=0) { delete weight_; weight_=0; } } private: idxtype* weight_; }; /** * @brief Create the "adjncy" and "xadj" arrays for using ParMETIS * * This function builds the ParMETIS "adjncy" and "xadj" array according * to the ParMETIS documentation. These arrays are generated by * traversing the graph object. The assigned index to the * "adjncy" array is the ParMETIS global index calculated before. * * @param graph the local graph. * @param indexSet the local indexSet. * @param &xadj the ParMETIS xadj array * @param ew Funcot to setup adjacency info. */ template void getAdjArrays(G& graph, IS& indexSet, idxtype *xadj, EW& ew) { int j=0; // The type of the const vertex iterator. typedef typename G::ConstVertexIterator VertexIterator; //typedef typename IndexSet::const_iterator Iterator; typedef typename IS::const_iterator Iterator; VertexIterator vend = graph.end(); Iterator end; for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) { if (isOwner(indexSet,*vertex)) { // The type of const edge iterator. typedef typename G::ConstEdgeIterator EdgeIterator; EdgeIterator eend = vertex.end(); xadj[j] = ew.index(); j++; for(EdgeIterator edge = vertex.begin(); edge != eend; ++edge) { ew(edge); } } } xadj[j] = ew.index(); } } // end anonymous namespace template bool buildCommunication(const G& graph, std::vector& realparts, Dune::OwnerOverlapCopyCommunication& oocomm, Dune::OwnerOverlapCopyCommunication*& outcomm, RedistributeInterface& redistInf, bool verbose=false); #if HAVE_PARMETIS #ifndef METIS_VER_MAJOR extern "C" { // backwards compatibility to parmetis < 4.0.0 void METIS_PartGraphKway(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, int *options, int *edgecut, idxtype *part); void METIS_PartGraphRecursive(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, int *options, int *edgecut, idxtype *part); } #endif #endif // HAVE_PARMETIS template inline void print_carray(S& os, T* array, std::size_t l) { for(T *cur=array, *end=array+l; cur!=end; ++cur) os<<*cur<<" "; } template inline bool isValidGraph(std::size_t noVtx, std::size_t gnoVtx, S noEdges, T* xadj, T* adjncy, bool checkSymmetry) { bool correct=true; for(idxtype vtx=0; vtx<(idxtype)noVtx; ++vtx) { if(xadj[vtx]>noEdges||xadj[vtx]<0) { std::cerr <<"Check graph: xadj["<" <noEdges||xadj[vtx+1]<0) { std::cerr <<"Check graph: xadj["<" <gnoVtx) { std::cerr<<" Edge "< bool commGraphRepartition(const M& mat, Dune::OwnerOverlapCopyCommunication& oocomm, idxtype nparts, Dune::OwnerOverlapCopyCommunication*& outcomm, RedistributeInterface& redistInf, bool verbose=false) { if(verbose && oocomm.communicator().rank()==0) std::cout<<"Repartitioning from "<1) { part[0]=rank; { // sublock for automatic memory deletion // Build the graph of the communication scheme and create an appropriate indexset. // calculate the neighbour vertices int noNeighbours = oocomm.remoteIndices().neighbours(); typedef typename Dune::OwnerOverlapCopyCommunication::RemoteIndices RemoteIndices; typedef typename RemoteIndices::const_iterator NeighbourIterator; for(NeighbourIterator n= oocomm.remoteIndices().begin(); n != oocomm.remoteIndices().end(); ++n) if(n->first==rank) { //do not include ourselves. --noNeighbours; break; } // A parmetis graph representing the communication graph. // The diagonal entries are the number of nodes on the process. // The offdiagonal entries are the number of edges leading to other processes. idxtype *xadj=new idxtype[2]; idxtype *vtxdist=new idxtype[oocomm.communicator().size()+1]; idxtype *adjncy=new idxtype[noNeighbours]; #ifdef USE_WEIGHTS idxtype *vwgt = 0; idxtype *adjwgt = 0; #endif // each process has exactly one vertex! for(int i=0; i owner(mat.N(), oocomm.communicator().rank()); // for(NeighbourIterator n= oocomm.remoteIndices().begin(); n != oocomm.remoteIndices().end(); // ++n) // { // if(n->first!=oocomm.communicator().rank()){ // typedef typename RemoteIndices::RemoteIndexList RIList; // const RIList& rlist = *(n->second.first); // typedef typename RIList::const_iterator LIter; // for(LIter entry=rlist.begin(); entry!=rlist.end(); ++entry){ // if(entry->attribute()==OwnerOverlapCopyAttributeSet::owner) // owner[entry->localIndexPair().local()] = n->first; // } // } // } // std::map edgecount; // edges to other processors // typedef typename M::ConstRowIterator RIter; // typedef typename M::ConstColIterator CIter; // // calculate edge count // for(RIter row=mat.begin(), endr=mat.end(); row != endr; ++row) // if(owner[row.index()]==OwnerOverlapCopyAttributeSet::owner) // for(CIter entry= row->begin(), ende = row->end(); entry != ende; ++entry) // ++edgecount[owner[entry.index()]]; // setup edge and weight pattern typedef typename RemoteIndices::const_iterator NeighbourIterator; idxtype* adjp=adjncy; #ifdef USE_WEIGHTS vwgt = new idxtype[1]; vwgt[0]= mat.N(); // weight is numer of rows TODO: Should actually be the nonzeros. adjwgt = new idxtype[noNeighbours]; idxtype* adjwp=adjwgt; #endif for(NeighbourIterator n= oocomm.remoteIndices().begin(); n != oocomm.remoteIndices().end(); ++n) if(n->first != rank) { *adjp=n->first; ++adjp; #ifdef USE_WEIGHTS *adjwp=1; //edgecount[n->first]; ++adjwp; #endif } assert(isValidGraph(vtxdist[rank+1]-vtxdist[rank], vtxdist[oocomm.communicator().size()], noNeighbours, xadj, adjncy, false)); idxtype wgtflag=0, numflag=0; idxtype edgecut; #ifdef USE_WEIGHTS wgtflag=3; #endif float *tpwgts = new float[nparts]; for(int i=0; i::getType(), gxadj,noxs,xdispl,MPITraits::getType(), comm); MPI_Allgatherv(adjncy,noNeighbours,MPITraits::getType(), gadjncy,noedges,displ,MPITraits::getType(), comm); #ifdef USE_WEIGHTS MPI_Allgatherv(adjwgt,noNeighbours,MPITraits::getType(), gadjwgt,noedges,displ,MPITraits::getType(), comm); MPI_Allgatherv(vwgt,localNoVtx,MPITraits::getType(), gvwgt,novs,vdispl,MPITraits::getType(), comm); #endif if(verbose && oocomm.communicator().rank()==0) std::cout<<"Gathering global graph data took "<(gxadjlen)); increment = *(start-1); std::transform(start+offset, start+l+offset, start, std::bind2nd(std::plus(), increment)); } Dune::dinfo<= 5 idxtype ncon = 1; idxtype moptions[METIS_NOPTIONS]; METIS_SetDefaultOptions(moptions); moptions[METIS_OPTION_NUMBERING] = numflag; METIS_PartGraphRecursive(&noVertices, &ncon, gxadj, gadjncy, gvwgt, NULL, gadjwgt, &nparts, NULL, NULL, moptions, &edgecut, gpart); #else // Call metis METIS_PartGraphRecursive(&noVertices, gxadj, gadjncy, gvwgt, gadjwgt, &wgtflag, &numflag, &nparts, options, &edgecut, gpart); #endif if(verbose && oocomm.communicator().rank()==0) std::cout<<"METIS took "<::getType(), part, 1, MPITraits::getType(), 0, comm); { // release remaining memory delete[] gpart; delete[] noedges; delete[] displ; } #endif delete[] xadj; delete[] vtxdist; delete[] adjncy; #ifdef USE_WEIGHTS delete[] vwgt; delete[] adjwgt; #endif delete[] tpwgts; } }else{ part[0]=0; } #endif Dune::dinfo<<" repart "< "<< part[0]< realpart(mat.N(), part[0]); delete[] part; oocomm.copyOwnerToAll(realpart, realpart); if(verbose && oocomm.communicator().rank()==0) std::cout<<"Scattering repartitioning took "< graph(const_cast(mat)); fillIndexSetHoles(graph, oocomm); if(verbose && oocomm.communicator().rank()==0) std::cout<<"Filling index set took "< bool graphRepartition(const G& graph, Dune::OwnerOverlapCopyCommunication& oocomm, idxtype nparts, Dune::OwnerOverlapCopyCommunication*& outcomm, RedistributeInterface& redistInf, bool verbose=false) { Timer time; MPI_Comm comm=oocomm.communicator(); oocomm.buildGlobalLookup(graph.noVertices()); fillIndexSetHoles(graph, oocomm); if(verbose && oocomm.communicator().rank()==0) std::cout<<"Filling holes took "< OOComm; typedef typename OOComm::OwnerSet OwnerSet; // Create the vtxdist array and parmetisVtxMapping. // Global communications are necessary // The parmetis global identifiers for the owner vertices. ParmetisDuneIndexMap indexMap(graph,oocomm); #if HAVE_PARMETIS idxtype *part = new idxtype[indexMap.numOfOwnVtx()]; #else std::size_t *part = new std::size_t[indexMap.numOfOwnVtx()]; #endif for(std::size_t i=0; i < indexMap.numOfOwnVtx(); ++i) part[i]=mype; #if !HAVE_PARMETIS if(oocomm.communicator().rank()==0 && nparts>1) std::cerr<<"ParMETIS not activated. Will repartition to 1 domain instead of requested " <1) { // Create the xadj and adjncy arrays idxtype *xadj = new idxtype[indexMap.numOfOwnVtx()+1]; idxtype *adjncy = new idxtype[graph.noEdges()]; EdgeFunctor ef(adjncy, indexMap, graph.noEdges()); getAdjArrays(graph, oocomm.globalLookup(), xadj, ef); // // 2) Call ParMETIS // // idxtype numflag=0, wgtflag=0, options[3], edgecut=0, ncon=1; //float *tpwgts = NULL; float *tpwgts = new float[nparts]; for(int i=0; i(comm)); delete[] xadj; delete[] adjncy; delete[] tpwgts; ef.free(); #ifdef DEBUG_REPART if (mype == 0) { std::cout< domainMapping(nparts); if(nparts>1) getDomain(comm, part, indexMap.numOfOwnVtx(), nparts, &myDomain, domainMapping); else domainMapping[0]=0; #ifdef DEBUG_REPART std::cout< setPartition(oocomm.indexSet().size(), -1); typedef typename OOComm::ParallelIndexSet::const_iterator Iterator; std::size_t i=0; // parmetis index for(Iterator index = oocomm.indexSet().begin(); index != oocomm.indexSet().end(); ++index) if(OwnerSet::contains(index->local().attribute())) { setPartition[index->local()]=domainMapping[part[i++]]; } delete[] part; oocomm.copyOwnerToAll(setPartition, setPartition); // communication only needed for ALU // (ghosts with same global id as owners on the same process) if (oocomm.getSolverCategory() == static_cast(SolverCategory::nonoverlapping)) oocomm.copyCopyToAll(setPartition, setPartition); bool ret = buildCommunication(graph, setPartition, oocomm, outcomm, redistInf, verbose); if(verbose) { oocomm.communicator().barrier(); if(oocomm.communicator().rank()==0) std::cout<<"Creating indexsets took "< bool buildCommunication(const G& graph, std::vector& setPartition, Dune::OwnerOverlapCopyCommunication& oocomm, Dune::OwnerOverlapCopyCommunication*& outcomm, RedistributeInterface& redistInf, bool verbose) { typedef typename Dune::OwnerOverlapCopyCommunication OOComm; typedef typename OOComm::OwnerSet OwnerSet; Timer time; // Build the send interface redistInf.buildSendInterface(setPartition, oocomm.indexSet()); #ifdef PERF_REPART // stop the time for step 3) t3=MPI_Wtime()-t3; // reset timer for step 4) t4=MPI_Wtime(); #endif // // 4) Create the output IndexSet and RemoteIndices // 4.1) Determine the "send to" and "receive from" relation // according to the new partition using a MPI ring // communication. // // 4.2) Depends on the "send to" and "receive from" vector, // the processes will exchange the vertices each other // // 4.3) Create the IndexSet, RemoteIndices and the new MPI // communicator // // // 4.1) Let's start... // int npes = oocomm.communicator().size(); int *sendTo = 0; int noSendTo = 0; std::set recvFrom; // the max number of vertices is stored in the sendTo buffer, // not the number of vertices to send! Because the max number of Vtx // is used as the fixed buffer size by the MPI send/receive calls typedef typename std::vector::const_iterator VIter; int mype = oocomm.communicator().rank(); { std::set tsendTo; for(VIter i=setPartition.begin(), iend = setPartition.end(); i!=iend; ++i) tsendTo.insert(*i); noSendTo = tsendTo.size(); sendTo = new int[noSendTo]; typedef std::set::const_iterator iterator; int idx=0; for(iterator i=tsendTo.begin(); i != tsendTo.end(); ++i, ++idx) sendTo[idx]=*i; } // int* gnoSend= new int[oocomm.communicator().size()]; int* gsendToDispl = new int[oocomm.communicator().size()+1]; MPI_Allgather(&noSendTo, 1, MPI_INT, gnoSend, 1, MPI_INT, oocomm.communicator()); // calculate total receive message size int totalNoRecv = 0; for(int i=0; i0; // Delete memory delete[] gnoSend; delete[] gsendToDispl; delete[] gsendTo; #ifdef DEBUG_REPART if(recvFrom.size()) { std::cout<::const_iterator siter; for(siter i=recvFrom.begin(); i!= recvFrom.end(); ++i) { std::cout<<*i<<" "; } } std::cout< GlobalVector; std::vector > myOwnerVec; std::set myOverlapSet; GlobalVector sendOwnerVec; std::set sendOverlapSet; std::set myNeighbors; // getOwnerOverlapVec(graph, setPartition, oocomm.globalLookup(), // mype, mype, myOwnerVec, myOverlapSet, redistInf, myNeighbors); char **sendBuffers=new char*[noSendTo]; MPI_Request *requests = new MPI_Request[noSendTo]; // Create all messages to be sent for(int i=0; i < noSendTo; ++i) { // clear the vector for sending sendOwnerVec.clear(); sendOverlapSet.clear(); // get all owner and overlap vertices for process j and save these // in the vectors sendOwnerVec and sendOverlapSet std::set neighbors; getOwnerOverlapVec(graph, setPartition, oocomm.globalLookup(), mype, sendTo[i], sendOwnerVec, sendOverlapSet, redistInf, neighbors); // +2, we need 2 integer more for the length of each part // (owner/overlap) of the array int buffersize=0; int tsize; MPI_Pack_size(1, MPITraits::getType(), oocomm.communicator(), &buffersize); MPI_Pack_size(sendOwnerVec.size(), MPITraits::getType(), oocomm.communicator(), &tsize); buffersize +=tsize; MPI_Pack_size(1, MPITraits::getType(), oocomm.communicator(), &tsize); buffersize +=tsize; MPI_Pack_size(sendOverlapSet.size(), MPITraits::getType(), oocomm.communicator(), &tsize); buffersize += tsize; MPI_Pack_size(1, MPITraits::getType(), oocomm.communicator(), &tsize); buffersize += tsize; MPI_Pack_size(neighbors.size(), MPI_INT, oocomm.communicator(), &tsize); buffersize += tsize; sendBuffers[i] = new char[buffersize]; #ifdef DEBUG_REPART std::cout<0) { // probe for an incoming message MPI_Status stat; MPI_Probe(MPI_ANY_SOURCE, 99, oocomm.communicator(), &stat); int buffersize; MPI_Get_count(&stat, MPI_PACKED, &buffersize); if(oldbuffersizecommunicator().rank(); int *newranks=new int[oocomm.communicator().size()]; std::vector tneighbors; tneighbors.reserve(myNeighbors.size()); typename OOComm::ParallelIndexSet& outputIndexSet = outcomm->indexSet(); MPI_Allgather(&newrank, 1, MPI_INT, newranks, 1, MPI_INT, oocomm.communicator()); typedef typename std::set::const_iterator IIter; #ifdef DEBUG_REPART std::cout<=0); std::cout<<*i<<"->"< >::const_iterator VPIter; int i=0; for(VPIter g=myOwnerVec.begin(), end =myOwnerVec.end(); g!=end; ++g, ++i ) { outputIndexSet.add(g->first,LocalIndex(i, OwnerOverlapCopyAttributeSet::owner, true)); redistInf.addReceiveIndex(g->second, i); } if(verbose) { oocomm.communicator().barrier(); if(oocomm.communicator().rank()==0) std::cout<<" Adding owner indices took "<< time.elapsed()<::const_iterator SIter; for(SIter g=myOverlapSet.begin(), end=myOverlapSet.end(); g!=end; ++g, i++) { outputIndexSet.add(*g,LocalIndex(i, OwnerOverlapCopyAttributeSet::copy, true)); } myOverlapSet.clear(); outputIndexSet.endResize(); #ifdef DUNE_ISTL_WITH_CHECKING int numOfOwnVtx =0; typedef typename OOComm::ParallelIndexSet::const_iterator Iterator; Iterator end = outputIndexSet.end(); for(Iterator index = outputIndexSet.begin(); index != end; ++index) { if (OwnerSet::contains(index->local().attribute())) { numOfOwnVtx++; } } numOfOwnVtx = oocomm.communicator().sum(numOfOwnVtx); // if(numOfOwnVtx!=indexMap.globalOwnerVertices) // { // std::cerr<global()>index->global()) DUNE_THROW(ISTLError, "Index set's globalindex not sorted correctly"); } } #endif if(verbose) { oocomm.communicator().barrier(); if(oocomm.communicator().rank()==0) std::cout<<" Adding overlap indices took "<< time.elapsed()<remoteIndices().setNeighbours(tneighbors); outcomm->remoteIndices().template rebuild(); } // release the memory delete[] sendTo; if(verbose) { oocomm.communicator().barrier(); if(oocomm.communicator().rank()==0) std::cout<<" Storing indexsets took "<< time.elapsed()< bool graphRepartition(const G& graph, P& oocomm, int nparts, P*& outcomm, R& redistInf, bool v=false) { if(nparts!=oocomm.size()) DUNE_THROW(NotImplemented, "only available for MPI programs"); } template bool commGraphRepartition(const G& graph, P& oocomm, int nparts, P*& outcomm, R& redistInf, bool v=false) { if(nparts!=oocomm.size()) DUNE_THROW(NotImplemented, "only available for MPI programs"); } #endif // HAVE_MPI } // end of namespace Dune #endif dune-istl-2.5.1/dune/istl/scalarproducts.hh000066400000000000000000000076431313314427100207140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SCALARPRODUCTS_HH #define DUNE_ISTL_SCALARPRODUCTS_HH #include #include #include #include #include #include "bvector.hh" #include "solvercategory.hh" namespace Dune { /** * @defgroup ISTL_SP Scalar products * @ingroup ISTL_Solvers * @brief Scalar products for the use in iterative solvers */ /** @addtogroup ISTL_SP @{ */ /** \file \brief Define base class for scalar product and norm. These classes have to be implemented differently for different data partitioning strategies. Default implementations for the sequential case are provided. */ /*! \brief Base class for scalar product and norm computation Krylov space methods need to compute scalar products and norms (for convergence test only). These methods have to know about the underlying data decomposition. For the sequential case a default implementation is provided. */ template class ScalarProduct { public: //! export types, they come from the derived class typedef X domain_type; typedef typename X::field_type field_type; typedef typename FieldTraits::real_type real_type; /*! \brief Dot product of two vectors. It is assumed that the vectors are consistent on the interior+border partition. */ virtual field_type dot (const X& x, const X& y) = 0; /*! \brief Norm of a right-hand side vector. The vector must be consistent on the interior+border partition */ virtual real_type norm (const X& x) = 0; //! every abstract base class has a virtual destructor virtual ~ScalarProduct () {} }; /** * \brief Choose the approriate scalar product for a solver category. * * As there is only one scalar product for each solver category it is * possible to choose the appropriate product at compile time. * * In each specialization of the this struct there will be a typedef ScalarProduct * available the defines the type of the scalar product. */ template struct ScalarProductChooser { /** @brief The type of the communication object. */ typedef C communication_type; enum { /** @brief The solver category. */ solverCategory=c }; }; //===================================================================== // Implementation for ISTL-matrix based operator //===================================================================== //! Default implementation for the scalar case template class SeqScalarProduct : public ScalarProduct { public: //! export types typedef X domain_type; typedef typename X::field_type field_type; typedef typename FieldTraits::real_type real_type; //! define the category enum {category=SolverCategory::sequential}; /*! \brief Dot product of two vectors. In the complex case, the first argument is conjugated. It is assumed that the vectors are consistent on the interior+border partition. */ virtual field_type dot (const X& x, const X& y) { return x.dot(y); } /*! \brief Norm of a right-hand side vector. The vector must be consistent on the interior+border partition */ virtual real_type norm (const X& x) { return x.two_norm(); } }; template struct ScalarProductChooser { /** @brief The type of the scalar product for the sequential case. */ typedef SeqScalarProduct ScalarProduct; enum { /** @brief The solver category. */ solverCategory=SolverCategory::sequential }; static ScalarProduct* construct(const C&) { return new ScalarProduct(); } }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/scaledidmatrix.hh000066400000000000000000000303111313314427100206440ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SCALEDIDMATRIX_HH #define DUNE_ISTL_SCALEDIDMATRIX_HH /*! \file \brief This file implements a quadratic matrix of fixed size which is a multiple of the identity. */ #include #include #include #include #include #include #include #include namespace Dune { /** @brief A multiple of the identity matrix of static size */ template class ScaledIdentityMatrix { typedef DiagonalMatrixWrapper< ScaledIdentityMatrix > WrapperType; public: //===== type definitions and constants //! export the type representing the field typedef K field_type; //! export the type representing the components typedef K block_type; //! The type used for the index access and size operations. typedef std::size_t size_type; //! We are at the leaf of the block recursion enum { //! The number of block levels we contain. This is 1. blocklevel = 1 }; //! Each row is implemented by a field vector typedef DiagonalRowVector row_type; typedef row_type reference; typedef DiagonalRowVectorConst const_row_type; typedef const_row_type const_reference; //! export size enum { //! The number of rows. rows = n, //! The number of columns. cols = n }; //===== constructors /** \brief Default constructor */ ScaledIdentityMatrix () {} /** \brief Constructor initializing the whole matrix with a scalar */ ScaledIdentityMatrix (const K& k) : p_(k) {} //===== assignment from scalar ScaledIdentityMatrix& operator= (const K& k) { p_ = k; return *this; } // check if matrix is identical to other matrix (not only identical values) bool identical(const ScaledIdentityMatrix& other) const { return (this==&other); } //===== iterator interface to rows of the matrix //! Iterator class for sequential access typedef ContainerWrapperIterator Iterator; //! typedef for stl compliant access typedef Iterator iterator; //! rename the iterators for easier access typedef Iterator RowIterator; //! rename the iterators for easier access typedef typename row_type::Iterator ColIterator; //! begin iterator Iterator begin () { return Iterator(WrapperType(this),0); } //! end iterator Iterator end () { return Iterator(WrapperType(this),n); } //! @returns an iterator that is positioned before //! the end iterator of the rows, i.e. at the last row. Iterator beforeEnd () { return Iterator(WrapperType(this),n-1); } //! @returns an iterator that is positioned before //! the first row of the matrix. Iterator beforeBegin () { return Iterator(WrapperType(this),-1); } //! Iterator class for sequential access typedef ContainerWrapperIterator ConstIterator; //! typedef for stl compliant access typedef ConstIterator const_iterator; //! rename the iterators for easier access typedef ConstIterator ConstRowIterator; //! rename the iterators for easier access typedef typename const_row_type::ConstIterator ConstColIterator; //! begin iterator ConstIterator begin () const { return ConstIterator(WrapperType(this),0); } //! end iterator ConstIterator end () const { return ConstIterator(WrapperType(this),n); } //! @returns an iterator that is positioned before //! the end iterator of the rows. i.e. at the last row. ConstIterator beforeEnd() const { return ConstIterator(WrapperType(this),n-1); } //! @returns an iterator that is positioned before //! the first row of the matrix. ConstIterator beforeBegin () const { return ConstIterator(WrapperType(this),-1); } //===== vector space arithmetic //! vector space addition ScaledIdentityMatrix& operator+= (const ScaledIdentityMatrix& y) { p_ += y.p_; return *this; } //! vector space subtraction ScaledIdentityMatrix& operator-= (const ScaledIdentityMatrix& y) { p_ -= y.p_; return *this; } //! addition to the diagonal ScaledIdentityMatrix& operator+= (const K& k) { p_ += k; return *this; } //! subtraction from the diagonal ScaledIdentityMatrix& operator-= (const K& k) { p_ -= k; return *this; } //! vector space multiplication with scalar ScaledIdentityMatrix& operator*= (const K& k) { p_ *= k; return *this; } //! vector space division by scalar ScaledIdentityMatrix& operator/= (const K& k) { p_ /= k; return *this; } //===== comparison ops //! comparison operator bool operator==(const ScaledIdentityMatrix& other) const { return p_==other.scalar(); } //! incomparison operator bool operator!=(const ScaledIdentityMatrix& other) const { return p_!=other.scalar(); } //===== linear maps //! y = A x template void mv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void mtv (const X& x, Y& y) const { mv(x, y); } //! y += A x template void umv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void umtv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void umhv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void mmv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void mmtv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void mmhv (const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void usmv (const K& alpha, const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void usmtv (const K& alpha, const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i void usmhv (const K& alpha, const X& x, Y& y) const { #ifdef DUNE_FMatrix_WITH_CHECKING if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range"); #endif for (size_type i=0; i::real_type frobenius_norm () const { return fvmeta::sqrt(n*p_*p_); } //! square of frobenius norm, need for block recursion typename FieldTraits::real_type frobenius_norm2 () const { return n*p_*p_; } //! infinity norm (row sum norm, how to generalize for blocks?) typename FieldTraits::real_type infinity_norm () const { return std::abs(p_); } //! simplified infinity norm (uses Manhattan norm for complex values) typename FieldTraits::real_type infinity_norm_real () const { return fvmeta::absreal(p_); } //===== solve /** \brief Solve system A x = b */ template void solve (V& x, const V& b) const { for (int i=0; i=n) DUNE_THROW(FMatrixError,"row index out of range"); if (j<0 || j>=n) DUNE_THROW(FMatrixError,"column index out of range"); #endif return i==j; } //===== conversion operator /** \brief Sends the matrix to an output stream */ friend std::ostream& operator<< (std::ostream& s, const ScaledIdentityMatrix& a) { for (size_type i=0; i(&p_), i); } //! Return const_reference object as row replacement const_reference operator[](size_type i) const { return const_reference(const_cast(&p_), i); } //! Get const reference to diagonal entry const K& diagonal(size_type /*i*/) const { return p_; } //! Get reference to diagonal entry K& diagonal(size_type /*i*/) { return p_; } /** \brief Get const reference to the scalar diagonal value */ const K& scalar() const { return p_; } /** \brief Get reference to the scalar diagonal value */ K& scalar() { return p_; } private: // the data, very simply a single number K p_; }; template struct DenseMatrixAssigner> { static void apply(DenseMatrix& denseMatrix, ScaledIdentityMatrix const& rhs) { assert(denseMatrix.M() == N); assert(denseMatrix.N() == N); denseMatrix = field(0); for (int i = 0; i < N; ++i) denseMatrix[i][i] = rhs.scalar(); } }; } // end namespace #endif dune-istl-2.5.1/dune/istl/schwarz.hh000066400000000000000000000337141313314427100173420ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SCHWARZ_HH #define DUNE_ISTL_SCHWARZ_HH #include // for input/output to shell #include // for input/output to files #include // STL vector class #include #include // Yes, we do some math here #include #include "io.hh" #include "bvector.hh" #include "vbvector.hh" #include "bcrsmatrix.hh" #include "io.hh" #include "gsetc.hh" #include "ilu.hh" #include "operators.hh" #include "solvers.hh" #include "preconditioners.hh" #include "scalarproducts.hh" #include "owneroverlapcopy.hh" namespace Dune { /** * @defgroup ISTL_Parallel Parallel Solvers * @ingroup ISTL_Solvers * Instead of using parallel data structures (matrices and vectors) that * (implicitly) know the data distribution and communication patterns, * there is a clear separation of the parallel data composition together * with the communication APIs from the data structures. This allows for * implementing overlapping and nonoverlapping domain decompositions as * well as data parallel parallelisation approaches. * * The \ref ISTL_Solvers "solvers" can easily be turned into parallel solvers * initializing them with matching parallel subclasses of the base classes * ScalarProduct, Preconditioner and LinearOperator. * * The information of the data distribution is provided by OwnerOverlapCopyCommunication * of \ref ISTL_Comm "communication API". * * Currently only data parallel versions are shipped with dune-istl. Domain * decomposition can be found in module dune-dd. */ /** @addtogroup ISTL_Operators @{ */ /** * \brief An overlapping schwarz operator. * * This operator represents a parallel matrix product using * sequential data structures together with a parallel index set * describing an overlapping domain decomposition and the communication. * \tparam M The type of the sequential matrix to use, * e.g. BCRSMatrix or another matrix type fulfilling the * matrix interface of ISTL. * \tparam X The type of the sequential vector to use for the left hand side, * e.g. BlockVector or another type fulfilling the ISTL * vector interface. * \tparam Y The type of the sequential vector to use for the right hand side, * e..g. BlockVector or another type fulfilling the ISTL * vector interface. * \tparam C The type of the communication object. * This must either be OwnerOverlapCopyCommunication or a type * implementing the same interface. */ template class OverlappingSchwarzOperator : public AssembledLinearOperator { public: //! \brief The type of the matrix we operate on. //! //! E.g. BCRSMatrix or another matrix type fulfilling the //! matrix interface of ISTL typedef M matrix_type; //! \brief The type of the domain. //! //! E.g. BlockVector or another type fulfilling the ISTL //! vector interface. typedef X domain_type; //! \brief The type of the range. //! //! E.g. BlockVector or another type fulfilling the ISTL //! vector interface. typedef Y range_type; //! \brief The field type of the range typedef typename X::field_type field_type; //! \brief The type of the communication object. //! //! This must either be OwnerOverlapCopyCommunication or a type //! implementing the same interface. typedef C communication_type; enum { //! \brief The solver category. category=SolverCategory::overlapping }; /** * @brief constructor: just store a reference to a matrix. * * @param A The assembled matrix. * @param com The communication object for syncing overlap and copy * data points. (E.~g. OwnerOverlapCopyCommunication ) */ OverlappingSchwarzOperator (const matrix_type& A, const communication_type& com) : _A_(A), communication(com) {} //! apply operator to x: \f$ y = A(x) \f$ virtual void apply (const X& x, Y& y) const { y = 0; _A_.umv(x,y); // result is consistent on interior+border communication.project(y); // we want this here to avoid it before the preconditioner // since there d is const! } //! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$ virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const { _A_.usmv(alpha,x,y); // result is consistent on interior+border communication.project(y); // we want this here to avoid it before the preconditioner // since there d is const! } //! get the sequential assembled linear operator. virtual const matrix_type& getmat () const { return _A_; } private: const matrix_type& _A_; const communication_type& communication; }; /** @} */ /** * @addtogroup ISTL_SP * @{ */ /** * \brief Scalar product for overlapping schwarz methods. * * Consistent vectors in interior and border are assumed. * \tparam X The type of the sequential vector to use for the left hand side, * e.g. BlockVector or another type fulfilling the ISTL * vector interface. * \tparam C The type of the communication object. * This must either be OwnerOverlapCopyCommunication or a type * implementing the same interface. */ template class OverlappingSchwarzScalarProduct : public ScalarProduct { public: //! \brief The type of the vector to compute the scalar product on. //! //! E.g. BlockVector or another type fulfilling the ISTL //! vector interface. typedef X domain_type; //! \brief The field type used by the vector type domain_type. typedef typename X::field_type field_type; typedef typename FieldTraits::real_type real_type; //! \brief The type of the communication object. //! //! This must either be OwnerOverlapCopyCommunication or a type //! implementing the same interface. typedef C communication_type; //! define the category enum {category=SolverCategory::overlapping}; /*! \brief Constructor needs to know the grid * \param com The communication object for syncing overlap and copy * data points. (E.~g. OwnerOverlapCopyCommunication ) */ OverlappingSchwarzScalarProduct (const communication_type& com) : communication(com) {} /*! \brief Dot product of two vectors. It is assumed that the vectors are consistent on the interior+border partition. */ virtual field_type dot (const X& x, const X& y) { field_type result; communication.dot(x,y,result); return result; } /*! \brief Norm of a right-hand side vector. The vector must be consistent on the interior+border partition */ virtual real_type norm (const X& x) { return communication.norm(x); } private: const communication_type& communication; }; template struct ScalarProductChooser { /** @brief The type of the scalar product for the overlapping case. */ typedef OverlappingSchwarzScalarProduct ScalarProduct; /** @brief The type of the communication object to use. */ typedef C communication_type; enum { /** @brief The solver category. */ solverCategory=SolverCategory::overlapping }; static ScalarProduct* construct(const communication_type& comm) { return new ScalarProduct(comm); } }; /** * @} * * @addtogroup ISTL_Prec * @{ */ //! \brief A parallel SSOR preconditioner. //! \tparam M The type of the sequential matrix to use, //! e.g. BCRSMatrix or another matrix type fulfilling the //! matrix interface of ISTL. //! \tparam X The type of the sequential vector to use for the left hand side, //! e.g. BlockVector or another type fulfilling the ISTL //! vector interface. //! \tparam Y The type of the sequential vector to use for the right hand side, //! e..g. BlockVector or another type fulfilling the ISTL //! vector interface. //! \tparam C The type of the communication object. //! This must either be OwnerOverlapCopyCommunication or a type //! implementing the same interface. template class ParSSOR : public Preconditioner { public: //! \brief The matrix type the preconditioner is for. typedef M matrix_type; //! \brief The domain type of the preconditioner. typedef X domain_type; //! \brief The range type of the preconditioner. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; //! \brief The type of the communication object. typedef C communication_type; // define the category enum { //! \brief The category the precondtioner is part of. category=SolverCategory::overlapping }; /*! \brief Constructor. constructor gets all parameters to operate the prec. \param A The matrix to operate on. \param n The number of iterations to perform. \param w The relaxation factor. \param c The communication object for syncing overlap and copy * data points. (E.~g. OwnerOverlapCopyCommunication ) */ ParSSOR (const matrix_type& A, int n, field_type w, const communication_type& c) : _A_(A), _n(n), _w(w), communication(c) { } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { communication.copyOwnerToAll(x,x); // make dirichlet values consistent } /*! \brief Apply the precondtioner \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { for (int i=0; i<_n; i++) { bsorf(_A_,v,d,_w); bsorb(_A_,v,d,_w); } communication.copyOwnerToAll(v,v); } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) {} private: //! \brief The matrix we operate on. const matrix_type& _A_; //! \brief The number of steps to do in apply int _n; //! \brief The relaxation factor to use field_type _w; //! \brief the communication object const communication_type& communication; }; namespace Amg { template class ConstructionTraits; } /** * @brief Block parallel preconditioner. * * This is essentially a wrapper that takes a sequential * preconditioner. In each step the sequential preconditioner * is applied and then all owner data points are updated on * all other processes. * \tparam M The type of the sequential matrix to use, * e.g. BCRSMatrix or another matrix type fulfilling the * matrix interface of ISTL. * \tparam X The type of the sequential vector to use for the left hand side, * e.g. BlockVector or another type fulfilling the ISTL * vector interface. * \tparam Y The type of the sequential vector to use for the right hand side, * e..g. BlockVector or another type fulfilling the ISTL * vector interface. * \tparam C The type of the communication object. * This must either be OwnerOverlapCopyCommunication or a type * implementing the same interface. * \tparam The type of the sequential preconditioner to use * for approximately solving the local matrix block consisting of unknowns * owned by the process. Has to implement the Preconditioner interface. */ template > class BlockPreconditioner : public Preconditioner { friend class Amg::ConstructionTraits >; public: //! \brief The domain type of the preconditioner. //! //! E.g. BlockVector or another type fulfilling the ISTL //! vector interface. typedef X domain_type; //! \brief The range type of the preconditioner. //! //! E.g. BlockVector or another type fulfilling the ISTL //! vector interface. typedef Y range_type; //! \brief The field type of the preconditioner. typedef typename X::field_type field_type; //! \brief The type of the communication object.. //! //! This must either be OwnerOverlapCopyCommunication or a type //! implementing the same interface. typedef C communication_type; // define the category enum { //! \brief The category the precondtioner is part of. category=SolverCategory::overlapping }; /*! \brief Constructor. constructor gets all parameters to operate the prec. \param p The sequential preconditioner. \param c The communication object for syncing overlap and copy data points. (E.~g. OwnerOverlapCopyCommunication ) */ BlockPreconditioner (T& p, const communication_type& c) : preconditioner(p), communication(c) { } /*! \brief Prepare the preconditioner. \copydoc Preconditioner::pre(X&,Y&) */ virtual void pre (X& x, Y& b) { communication.copyOwnerToAll(x,x); // make dirichlet values consistent preconditioner.pre(x,b); } /*! \brief Apply the preconditioner \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { preconditioner.apply(v,d); communication.copyOwnerToAll(v,v); } template void apply (X& v, const Y& d) { preconditioner.template apply(v,d); communication.copyOwnerToAll(v,v); } /*! \brief Clean up. \copydoc Preconditioner::post(X&) */ virtual void post (X& x) { preconditioner.post(x); } private: //! \brief a sequential preconditioner T& preconditioner; //! \brief the communication object const communication_type& communication; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/solver.hh000066400000000000000000000110531313314427100171630ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SOLVER_HH #define DUNE_ISTL_SOLVER_HH #include #include namespace Dune { /** * @addtogroup ISTL_Solvers * @{ */ /** \file \brief Define general, extensible interface for inverse operators. Implementation here covers only inversion of linear operators, but the implementation might be used for nonlinear operators as well. */ /** \brief Statistics about the application of an inverse operator The return value of an application of the inverse operator delivers some important information about the iteration. */ struct InverseOperatorResult { /** \brief Default constructor */ InverseOperatorResult () { clear(); } /** \brief Resets all data */ void clear () { iterations = 0; reduction = 0; converged = false; conv_rate = 1; elapsed = 0; } /** \brief Number of iterations */ int iterations; /** \brief Reduction achieved: \f$ \|b-A(x^n)\|/\|b-A(x^0)\|\f$ */ double reduction; /** \brief True if convergence criterion has been met */ bool converged; /** \brief Convergence rate (average reduction per step) */ double conv_rate; /** \brief Elapsed time in seconds */ double elapsed; }; //===================================================================== /*! \brief Abstract base class for all solvers. An InverseOperator computes the solution of \f$ A(x)=b\f$ where \f$ A : X \to Y \f$ is an operator. Note that the solver "knows" which operator to invert and which preconditioner to apply (if any). The user is only interested in inverting the operator. InverseOperator might be a Newton scheme, a Krylov subspace method, or a direct solver or just anything. */ template class InverseOperator { public: //! \brief Type of the domain of the operator to be inverted. typedef X domain_type; //! \brief Type of the range of the operator to be inverted. typedef Y range_type; /** \brief The field type of the operator. */ typedef typename X::field_type field_type; /** \brief Apply inverse operator, \warning Note: right hand side b may be overwritten! \param x The left hand side to store the result in. \param b The right hand side \param res Object to store the statistics about applying the operator. \throw SolverAbort When the solver detects a problem and cannot continue */ virtual void apply (X& x, Y& b, InverseOperatorResult& res) = 0; /*! \brief apply inverse operator, with given convergence criteria. \warning Right hand side b may be overwritten! \param x The left hand side to store the result in. \param b The right hand side \param reduction The minimum defect reduction to achieve. \param res Object to store the statistics about applying the operator. \throw SolverAbort When the solver detects a problem and cannot continue */ virtual void apply (X& x, Y& b, double reduction, InverseOperatorResult& res) = 0; //! \brief Destructor virtual ~InverseOperator () {} protected: // spacing values enum { iterationSpacing = 5 , normSpacing = 16 }; //! helper function for printing header of solver output void printHeader(std::ostream& s) const { s << std::setw(iterationSpacing) << " Iter"; s << std::setw(normSpacing) << "Defect"; s << std::setw(normSpacing) << "Rate" << std::endl; } //! helper function for printing solver output template void printOutput(std::ostream& s, const CountType& iter, const DataType& norm, const DataType& norm_old) const { const DataType rate = norm/norm_old; s << std::setw(iterationSpacing) << iter << " "; s << std::setw(normSpacing) << norm << " "; s << std::setw(normSpacing) << rate << std::endl; } //! helper function for printing solver output template void printOutput(std::ostream& s, const CountType& iter, const DataType& norm) const { s << std::setw(iterationSpacing) << iter << " "; s << std::setw(normSpacing) << norm << std::endl; } }; /** * @} */ } #endif dune-istl-2.5.1/dune/istl/solvercategory.hh000066400000000000000000000011571313314427100207250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SOLVERCATEGORY_HH #define DUNE_ISTL_SOLVERCATEGORY_HH namespace Dune { /** @addtogroup ISTL_Solvers @{ */ /** * @brief Categories for the solvers. */ struct SolverCategory { enum Category { //! \brief Category for sequential solvers sequential, //! \brief Category for non-overlapping solvers nonoverlapping, //! \brief Category for overlapping solvers overlapping }; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/dune/istl/solvers.hh000066400000000000000000001557671313314427100173730ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SOLVERS_HH #define DUNE_ISTL_SOLVERS_HH #include #include #include #include #include #include #include #include #include "istlexception.hh" #include "operators.hh" #include "scalarproducts.hh" #include "solver.hh" #include "preconditioner.hh" #include #include #include #include #include namespace Dune { /** @defgroup ISTL_Solvers Iterative Solvers @ingroup ISTL */ /** @addtogroup ISTL_Solvers @{ */ /** \file \brief Implementations of the inverse operator interface. This file provides various preconditioned Krylov methods. */ //===================================================================== // Implementation of this interface //===================================================================== /*! \brief Preconditioned loop solver. Implements a preconditioned loop. Using this class every Preconditioner can be turned into a solver. The solver will apply one preconditioner step in each iteration loop. */ template class LoopSolver : public InverseOperator { public: //! \brief The domain type of the operator that we do the inverse for. typedef X domain_type; //! \brief The range type of the operator that we do the inverse for. typedef X range_type; //! \brief The field type of the operator that we do the inverse for. typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up Loop solver. \param op The operator we solve. \param prec The preconditioner to apply in each iteration of the loop. Has to inherit from Preconditioner. \param reduction The relative defect reduction to achieve when applying the operator. \param maxit The maximum number of iteration steps allowed when applying the operator. \param verbose The verbosity level. Verbose levels are:
  • 0 : print nothing
  • 1 : print initial and final defect and statistics
  • 2 : print line for each iteration
*/ template LoopSolver (L& op, P& prec, real_type reduction, int maxit, int verbose) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P have to have the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L has to be sequential!"); } /** \brief Set up loop solver \param op The operator we solve. \param sp The scalar product to use, e. g. SeqScalarproduct. \param prec The preconditioner to apply in each iteration of the loop. Has to inherit from Preconditioner. \param reduction The relative defect reduction to achieve when applying the operator. \param maxit The maximum number of iteration steps allowed when applying the operator. \param verbose The verbosity level. Verbose levels are:
  • 0 : print nothing
  • 1 : print initial and final defect and statistics
  • 2 : print line for each iteration
*/ template LoopSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S must have the same category!"); } //! \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) virtual void apply (X& x, X& b, InverseOperatorResult& res) { // clear solver statistics res.clear(); // start a timer Timer watch; // prepare preconditioner _prec.pre(x,b); // overwrite b with defect _op.applyscaleadd(-1,x,b); // compute norm, \todo parallelization real_type def0 = _sp.norm(b); // printing if (_verbose>0) { std::cout << "=== LoopSolver" << std::endl; if (_verbose>1) { this->printHeader(std::cout); this->printOutput(std::cout,0,def0); } } // allocate correction vector X v(x); // iteration loop int i=1; real_type def=def0; for ( ; i<=_maxit; i++ ) { v = 0; // clear correction _prec.apply(v,b); // apply preconditioner x += v; // update solution _op.applyscaleadd(-1,v,b); // update defect real_type defnew=_sp.norm(b); // comp defect norm if (_verbose>1) // print this->printOutput(std::cout,i,defnew,def); //std::cout << i << " " << defnew << " " << defnew/def << std::endl; def = defnew; // update norm if (defprintOutput(std::cout,i,def); // postprocess preconditioner _prec.post(x); // fill statistics res.iterations = i; res.reduction = def/def0; res.conv_rate = pow(res.reduction,1.0/i); res.elapsed = watch.elapsed(); // final print if (_verbose>0) { std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/i << ", IT=" << i << std::endl; } } //! \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res) { real_type saved_reduction = _reduction; _reduction = reduction; (*this).apply(x,b,res); _reduction = saved_reduction; } private: SeqScalarProduct ssp; LinearOperator& _op; Preconditioner& _prec; ScalarProduct& _sp; real_type _reduction; int _maxit; int _verbose; }; // all these solvers are taken from the SUMO library //! gradient method template class GradientSolver : public InverseOperator { public: //! \brief The domain type of the operator that we do the inverse for. typedef X domain_type; //! \brief The range type of the operator that we do the inverse for. typedef X range_type; //! \brief The field type of the operator that we do the inverse for. typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) */ template GradientSolver (L& op, P& prec, real_type reduction, int maxit, int verbose) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P have to have the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L has to be sequential!"); } /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) */ template GradientSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P have to have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S have to have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) */ virtual void apply (X& x, X& b, InverseOperatorResult& res) { res.clear(); // clear solver statistics Timer watch; // start a timer _prec.pre(x,b); // prepare preconditioner _op.applyscaleadd(-1,x,b); // overwrite b with defect X p(x); // create local vectors X q(b); real_type def0 = _sp.norm(b); // compute norm if (_verbose>0) // printing { std::cout << "=== GradientSolver" << std::endl; if (_verbose>1) { this->printHeader(std::cout); this->printOutput(std::cout,0,def0); } } int i=1; real_type def=def0; // loop variables field_type lambda; for ( ; i<=_maxit; i++ ) { p = 0; // clear correction _prec.apply(p,b); // apply preconditioner _op.apply(p,q); // q=Ap lambda = _sp.dot(p,b)/_sp.dot(q,p); // minimization x.axpy(lambda,p); // update solution b.axpy(-lambda,q); // update defect real_type defnew=_sp.norm(b); // comp defect norm if (_verbose>1) // print this->printOutput(std::cout,i,defnew,def); def = defnew; // update norm if (defprintOutput(std::cout,i,def); _prec.post(x); // postprocess preconditioner res.iterations = i; // fill statistics res.reduction = static_cast(def/def0); res.conv_rate = static_cast(pow(res.reduction,1.0/i)); res.elapsed = watch.elapsed(); if (_verbose>0) // final print std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/i << ", IT=" << i << std::endl; } /*! \brief Apply inverse operator with given reduction factor. \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) */ virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res) { real_type saved_reduction = _reduction; _reduction = reduction; (*this).apply(x,b,res); _reduction = saved_reduction; } private: SeqScalarProduct ssp; LinearOperator& _op; Preconditioner& _prec; ScalarProduct& _sp; real_type _reduction; int _maxit; int _verbose; }; //! \brief conjugate gradient method template class CGSolver : public InverseOperator { public: //! \brief The domain type of the operator to be inverted. typedef X domain_type; //! \brief The range type of the operator to be inverted. typedef X range_type; //! \brief The field type of the operator to be inverted. typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up conjugate gradient solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) */ template CGSolver (L& op, P& prec, real_type reduction, int maxit, int verbose) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L must be sequential!"); } /*! \brief Set up conjugate gradient solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) */ template CGSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S must have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) \note Currently, the CGSolver aborts when a NaN or infinite defect is detected. However, -ffinite-math-only (implied by -ffast-math) can inhibit a result from becoming NaN that really should be NaN. E.g. numeric_limits::quiet_NaN()*0.0==0.0 with gcc-5.3 -ffast-math. */ virtual void apply (X& x, X& b, InverseOperatorResult& res) { using std::isfinite; res.clear(); // clear solver statistics Timer watch; // start a timer _prec.pre(x,b); // prepare preconditioner _op.applyscaleadd(-1,x,b); // overwrite b with defect X p(x); // the search direction X q(x); // a temporary vector real_type def0 = _sp.norm(b); // compute norm if (!isfinite(def0)) // check for inf or NaN { if (_verbose>0) std::cout << "=== CGSolver: abort due to infinite or NaN initial defect" << std::endl; DUNE_THROW(SolverAbort, "CGSolver: initial defect=" << def0 << " is infinite or NaN"); } if (def0<1E-30) // convergence check { res.converged = true; res.iterations = 0; // fill statistics res.reduction = 0; res.conv_rate = 0; res.elapsed=0; if (_verbose>0) // final print std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed << ", IT=0" << std::endl; return; } if (_verbose>0) // printing { std::cout << "=== CGSolver" << std::endl; if (_verbose>1) { this->printHeader(std::cout); this->printOutput(std::cout,real_type(0),def0); } } // some local variables real_type def=def0; // loop variables field_type rho,rholast,lambda,alpha,beta; // determine initial search direction p = 0; // clear correction _prec.apply(p,b); // apply preconditioner rholast = _sp.dot(p,b); // orthogonalization // the loop int i=1; for ( ; i<=_maxit; i++ ) { // minimize in given search direction p _op.apply(p,q); // q=Ap alpha = _sp.dot(p,q); // scalar product lambda = rholast/alpha; // minimization x.axpy(lambda,p); // update solution b.axpy(-lambda,q); // update defect // convergence test real_type defnew=_sp.norm(b); // comp defect norm if (_verbose>1) // print this->printOutput(std::cout,real_type(i),defnew,def); def = defnew; // update norm if (!isfinite(def)) // check for inf or NaN { if (_verbose>0) std::cout << "=== CGSolver: abort due to infinite or NaN defect" << std::endl; DUNE_THROW(SolverAbort, "CGSolver: defect=" << def << " is infinite or NaN"); } if (defprintOutput(std::cout,real_type(i),def); _prec.post(x); // postprocess preconditioner res.iterations = i; // fill statistics res.reduction = static_cast(def/def0); res.conv_rate = static_cast(pow(res.reduction,1.0/i)); res.elapsed = watch.elapsed(); if (_verbose>0) // final print { std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/i << ", IT=" << i << std::endl; } } /*! \brief Apply inverse operator with given reduction factor. \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) \note Currently, the CGSolver aborts when a NaN or infinite defect is detected. However, -ffinite-math-only (implied by -ffast-math) can inhibit a result from becoming NaN that really should be NaN. E.g. numeric_limits::quiet_NaN()*0.0==0.0 with gcc-5.3 -ffast-math. */ virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res) { real_type saved_reduction = _reduction; _reduction = reduction; (*this).apply(x,b,res); _reduction = saved_reduction; } private: SeqScalarProduct ssp; LinearOperator& _op; Preconditioner& _prec; ScalarProduct& _sp; real_type _reduction; int _maxit; int _verbose; }; // Ronald Kriemanns BiCG-STAB implementation from Sumo //! \brief Bi-conjugate Gradient Stabilized (BiCG-STAB) template class BiCGSTABSolver : public InverseOperator { public: //! \brief The domain type of the operator to be inverted. typedef X domain_type; //! \brief The range type of the operator to be inverted. typedef X range_type; //! \brief The field type of the operator to be inverted typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) */ template BiCGSTABSolver (L& op, P& prec, real_type reduction, int maxit, int verbose) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must be of the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L must be sequential!"); } /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) */ template BiCGSTABSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S must have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) \note Currently, the BiCGSTABSolver aborts when it detects a breakdown. */ virtual void apply (X& x, X& b, InverseOperatorResult& res) { using std::abs; const real_type EPSILON=1e-80; double it; field_type rho, rho_new, alpha, beta, h, omega; real_type norm, norm_old, norm_0; // // get vectors and matrix // X& r=b; X p(x); X v(x); X t(x); X y(x); X rt(x); // // begin iteration // // r = r - Ax; rt = r res.clear(); // clear solver statistics Timer watch; // start a timer _prec.pre(x,r); // prepare preconditioner _op.applyscaleadd(-1,x,r); // overwrite b with defect rt=r; norm = norm_old = norm_0 = _sp.norm(r); p=0; v=0; rho = 1; alpha = 1; omega = 1; if (_verbose>0) // printing { std::cout << "=== BiCGSTABSolver" << std::endl; if (_verbose>1) { this->printHeader(std::cout); this->printOutput(std::cout,0,norm_0); //std::cout << " Iter Defect Rate" << std::endl; //std::cout << " 0" << std::setw(14) << norm_0 << std::endl; } } if ( norm < (_reduction * norm_0) || norm<1E-30) { res.converged = 1; _prec.post(x); // postprocess preconditioner res.iterations = 0; // fill statistics res.reduction = 0; res.conv_rate = 0; res.elapsed = watch.elapsed(); return; } // // iteration // for (it = 0.5; it < _maxit; it+=.5) { // // preprocess, set vecsizes etc. // // rho_new = < rt , r > rho_new = _sp.dot(rt,r); // look if breakdown occurred if (abs(rho) <= EPSILON) DUNE_THROW(SolverAbort,"breakdown in BiCGSTAB - rho " << rho << " <= EPSILON " << EPSILON << " after " << it << " iterations"); if (abs(omega) <= EPSILON) DUNE_THROW(SolverAbort,"breakdown in BiCGSTAB - omega " << omega << " <= EPSILON " << EPSILON << " after " << it << " iterations"); if (it<1) p = r; else { beta = ( rho_new / rho ) * ( alpha / omega ); p.axpy(-omega,v); // p = r + beta (p - omega*v) p *= beta; p += r; } // y = W^-1 * p y = 0; _prec.apply(y,p); // apply preconditioner // v = A * y _op.apply(y,v); // alpha = rho_new / < rt, v > h = _sp.dot(rt,v); if (abs(h) < EPSILON) DUNE_THROW(SolverAbort,"abs(h) < EPSILON in BiCGSTAB - abs(h) " << abs(h) << " < EPSILON " << EPSILON << " after " << it << " iterations"); alpha = rho_new / h; // apply first correction to x // x <- x + alpha y x.axpy(alpha,y); // r = r - alpha*v r.axpy(-alpha,v); // // test stop criteria // norm = _sp.norm(r); if (_verbose>1) // print { this->printOutput(std::cout,it,norm,norm_old); } if ( norm < (_reduction * norm_0) ) { res.converged = 1; break; } it+=.5; norm_old = norm; // y = W^-1 * r y = 0; _prec.apply(y,r); // t = A * y _op.apply(y,t); // omega = < t, r > / < t, t > omega = _sp.dot(t,r)/_sp.dot(t,t); // apply second correction to x // x <- x + omega y x.axpy(omega,y); // r = s - omega*t (remember : r = s) r.axpy(-omega,t); rho = rho_new; // // test stop criteria // norm = _sp.norm(r); if (_verbose > 1) // print { this->printOutput(std::cout,it,norm,norm_old); } if ( norm < (_reduction * norm_0) || norm<1E-30) { res.converged = 1; break; } norm_old = norm; } // end for //correct i which is wrong if convergence was not achieved. it=std::min(static_cast(_maxit),it); if (_verbose==1) // printing for non verbose this->printOutput(std::cout,it,norm); _prec.post(x); // postprocess preconditioner res.iterations = static_cast(std::ceil(it)); // fill statistics res.reduction = static_cast(norm/norm_0); res.conv_rate = static_cast(pow(res.reduction,1.0/it)); res.elapsed = watch.elapsed(); if (_verbose>0) // final print std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/it << ", IT=" << it << std::endl; } /*! \brief Apply inverse operator with given reduction factor. \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) \note Currently, the BiCGSTABSolver aborts when it detects a breakdown. */ virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res) { real_type saved_reduction = _reduction; _reduction = reduction; (*this).apply(x,b,res); _reduction = saved_reduction; } private: SeqScalarProduct ssp; LinearOperator& _op; Preconditioner& _prec; ScalarProduct& _sp; real_type _reduction; int _maxit; int _verbose; }; /*! \brief Minimal Residual Method (MINRES) Symmetrically Preconditioned MINRES as in A. Greenbaum, 'Iterative Methods for Solving Linear Systems', pp. 121 Iterative solver for symmetric indefinite operators. Note that in order to ensure the (symmetrically) preconditioned system to remain symmetric, the preconditioner has to be spd. */ template class MINRESSolver : public InverseOperator { public: //! \brief The domain type of the operator to be inverted. typedef X domain_type; //! \brief The range type of the operator to be inverted. typedef X range_type; //! \brief The field type of the operator to be inverted. typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up MINRES solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) */ template MINRESSolver (L& op, P& prec, real_type reduction, int maxit, int verbose) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L must be sequential!"); } /*! \brief Set up MINRES solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) */ template MINRESSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S must have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) */ virtual void apply (X& x, X& b, InverseOperatorResult& res) { using std::sqrt; using std::abs; // clear solver statistics res.clear(); // start a timer Dune::Timer watch; watch.reset(); // prepare preconditioner _prec.pre(x,b); // overwrite rhs with defect _op.applyscaleadd(-1,x,b); // compute residual norm real_type def0 = _sp.norm(b); // printing if(_verbose > 0) { std::cout << "=== MINRESSolver" << std::endl; if(_verbose > 1) { this->printHeader(std::cout); this->printOutput(std::cout,0,def0); } } // check for convergence if(def0 < 1e-30 ) { res.converged = true; res.iterations = 0; res.reduction = 0; res.conv_rate = 0; res.elapsed = 0.0; // final print if(_verbose > 0) std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed << ", IT=" << res.iterations << std::endl; return; } // the defect norm real_type def = def0; // recurrence coefficients as computed in Lanczos algorithm field_type alpha, beta; // diagonal entries of givens rotation std::array c{{0.0,0.0}}; // off-diagonal entries of givens rotation std::array s{{0.0,0.0}}; // recurrence coefficients (column k of tridiag matrix T_k) std::array T{{0.0,0.0,0.0}}; // the rhs vector of the min problem std::array xi{{1.0,0.0}}; // some temporary vectors X z(b), dummy(b); // initialize and clear correction z = 0.0; _prec.apply(z,b); // beta is real and positive in exact arithmetic // since it is the norm of the basis vectors (in unpreconditioned case) beta = sqrt(_sp.dot(b,z)); field_type beta0 = beta; // the search directions std::array p{{b,b,b}}; p[0] = 0.0; p[1] = 0.0; p[2] = 0.0; // orthonormal basis vectors (in unpreconditioned case) std::array q{{b,b,b}}; q[0] = 0.0; q[1] *= 1.0/beta; q[2] = 0.0; z *= 1.0/beta; // the loop int i = 1; for( ; i<=_maxit; i++) { dummy = z; int i1 = i%3, i0 = (i1+2)%3, i2 = (i1+1)%3; // symmetrically preconditioned Lanczos algorithm (see Greenbaum p.121) _op.apply(z,q[i2]); // q[i2] = Az q[i2].axpy(-beta,q[i0]); // alpha is real since it is the diagonal entry of the hermitian tridiagonal matrix // from the Lanczos Algorithm // so the order in the scalar product doesn't matter even for the complex case alpha = _sp.dot(z,q[i2]); q[i2].axpy(-alpha,q[i1]); z = 0.0; _prec.apply(z,q[i2]); // beta is real and positive in exact arithmetic // since it is the norm of the basis vectors (in unpreconditioned case) beta = sqrt(_sp.dot(q[i2],z)); q[i2] *= 1.0/beta; z *= 1.0/beta; // QR Factorization of recurrence coefficient matrix // apply previous givens rotations to last column of T T[1] = T[2]; if(i>2) { T[0] = s[i%2]*T[1]; T[1] = c[i%2]*T[1]; } if(i>1) { T[2] = c[(i+1)%2]*alpha - s[(i+1)%2]*T[1]; T[1] = c[(i+1)%2]*T[1] + s[(i+1)%2]*alpha; } else T[2] = alpha; // update QR factorization generateGivensRotation(T[2],beta,c[i%2],s[i%2]); // to last column of T_k T[2] = c[i%2]*T[2] + s[i%2]*beta; // and to the rhs xi of the min problem xi[i%2] = -s[i%2]*xi[(i+1)%2]; xi[(i+1)%2] *= c[i%2]; // compute correction direction p[i2] = dummy; p[i2].axpy(-T[1],p[i1]); p[i2].axpy(-T[0],p[i0]); p[i2] *= 1.0/T[2]; // apply correction/update solution x.axpy(beta0*xi[(i+1)%2],p[i2]); // remember beta_old T[2] = beta; // check for convergence // the last entry in the rhs of the min-problem is the residual real_type defnew = abs(beta0*xi[i%2]); if(_verbose > 1) this->printOutput(std::cout,i,defnew,def); def = defnew; if(def < def0*_reduction || def < 1e-30 || i == _maxit ) { res.converged = true; break; } } // end for if(_verbose == 1) this->printOutput(std::cout,i,def); // postprocess preconditioner _prec.post(x); // fill statistics res.iterations = i; res.reduction = static_cast(def/def0); res.conv_rate = static_cast(pow(res.reduction,1.0/i)); res.elapsed = watch.elapsed(); // final print if(_verbose > 0) { std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/i << ", IT=" << i << std::endl; } } /*! \brief Apply inverse operator with given reduction factor. \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) */ virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res) { real_type saved_reduction = _reduction; _reduction = reduction; (*this).apply(x,b,res); _reduction = saved_reduction; } private: void generateGivensRotation(field_type &dx, field_type &dy, real_type &cs, field_type &sn) { using std::sqrt; using std::abs; real_type norm_dx = abs(dx); real_type norm_dy = abs(dy); if(norm_dy < 1e-15) { cs = 1.0; sn = 0.0; } else if(norm_dx < 1e-15) { cs = 0.0; sn = 1.0; } else if(norm_dy > norm_dx) { real_type temp = norm_dx/norm_dy; cs = 1.0/sqrt(1.0 + temp*temp); sn = cs; cs *= temp; sn *= dx/norm_dx; // dy is real in exact arithmetic // so we don't need to conjugate here sn *= dy/norm_dy; } else { real_type temp = norm_dy/norm_dx; cs = 1.0/sqrt(1.0 + temp*temp); sn = cs; sn *= dy/dx; // dy and dx is real in exact arithmetic // so we don't have to conjugate both of them } } SeqScalarProduct ssp; LinearOperator& _op; Preconditioner& _prec; ScalarProduct& _sp; real_type _reduction; int _maxit; int _verbose; }; /** \brief implements the Generalized Minimal Residual (GMRes) method GMRes solves the unsymmetric linear system Ax = b using the Generalized Minimal Residual method as described the SIAM Templates book (http://www.netlib.org/templates/templates.pdf). \tparam X trial vector, vector type of the solution \tparam Y test vector, vector type of the RHS \tparam F vector type for orthonormal basis of Krylov space */ template class RestartedGMResSolver : public InverseOperator { public: //! \brief The domain type of the operator to be inverted. typedef X domain_type; //! \brief The range type of the operator to be inverted. typedef Y range_type; //! \brief The field type of the operator to be inverted typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; //! \brief The field type of the basis vectors typedef F basis_type; template DUNE_DEPRECATED_MSG("recalc_defect is a unused parameter! Use RestartedGMResSolver(L& op, P& prec, real_type reduction, int restart, int maxit, int verbose) instead") RestartedGMResSolver (L& op, P& prec, real_type reduction, int restart, int maxit, int verbose, bool recalc_defect) : _A(op) , _W(prec) , ssp() , _sp(ssp) , _restart(restart) , _reduction(reduction) , _maxit(maxit) , _verbose(verbose) { static_assert(static_cast(P::category) == static_cast(L::category), "P and L must be the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L must be sequential!"); } /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) \param restart number of GMRes cycles before restart */ template RestartedGMResSolver (L& op, P& prec, real_type reduction, int restart, int maxit, int verbose) : _A(op), _W(prec), ssp(), _sp(ssp), _restart(restart), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(P::category) == static_cast(L::category), "P and L must be the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L must be sequential!"); } template DUNE_DEPRECATED_MSG("recalc_defect is a unused parameter! Use RestartedGMResSolver(L& op, S& sp, P& prec, real_type reduction, int restart, int maxit, int verbose) instead") RestartedGMResSolver(L& op, S& sp, P& prec, real_type reduction, int restart, int maxit, int verbose, bool recalc_defect) : _A(op) , _W(prec) , _sp(sp) , _restart(restart) , _reduction(reduction) , _maxit(maxit) , _verbose(verbose) { static_assert(static_cast(P::category) == static_cast(L::category), " P and L must have the same category!"); static_assert(static_cast(P::category) == static_cast(S::category), "P and S must have the same category!"); } /*! \brief Set up solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) \param restart number of GMRes cycles before restart */ template RestartedGMResSolver (L& op, S& sp, P& prec, real_type reduction, int restart, int maxit, int verbose) : _A(op), _W(prec), _sp(sp), _restart(restart), _reduction(reduction), _maxit(maxit), _verbose(verbose) { static_assert(static_cast(P::category) == static_cast(L::category), "P and L must have the same category!"); static_assert(static_cast(P::category) == static_cast(S::category), "P and S must have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) \note Currently, the RestartedGMResSolver aborts when it detects a breakdown. */ virtual void apply (X& x, Y& b, InverseOperatorResult& res) { apply(x,b,_reduction,res); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) \note Currently, the RestartedGMResSolver aborts when it detects a breakdown. */ virtual void apply (X& x, Y& b, double reduction, InverseOperatorResult& res) { using std::abs; const real_type EPSILON = 1e-80; const int m = _restart; real_type norm, norm_old = 0.0, norm_0; int j = 1; std::vector s(m+1), sn(m); std::vector cs(m); // need copy of rhs if GMRes has to be restarted Y b2(b); // helper vector Y w(b); std::vector< std::vector > H(m+1,s); std::vector v(m+1,b); // start timer Dune::Timer watch; watch.reset(); // clear solver statistics and set res.converged to false res.clear(); _W.pre(x,b); // calculate defect and overwrite rhs with it _A.applyscaleadd(-1.0,x,b); // b -= Ax // calculate preconditioned defect v[0] = 0.0; _W.apply(v[0],b); // r = W^-1 b norm_0 = _sp.norm(v[0]); norm = norm_0; norm_old = norm; // print header if(_verbose > 0) { std::cout << "=== RestartedGMResSolver" << std::endl; if(_verbose > 1) { this->printHeader(std::cout); this->printOutput(std::cout,0,norm_0); } } if(norm_0 < EPSILON) { _W.post(x); res.converged = true; if(_verbose > 0) // final print print_result(res); } while(j <= _maxit && res.converged != true) { int i = 0; v[0] *= 1.0/norm; s[0] = norm; for(i=1; i 1) { this->printOutput(std::cout,j,norm,norm_old); } norm_old = norm; // check convergence if(norm < reduction * norm_0) res.converged = true; } // end for // calculate update vector w = 0.0; update(w,i,H,s,v); // and current iterate x += w; // restart GMRes if convergence was not achieved, // i.e. linear defect has not reached desired reduction // and if j < _maxit if( res.converged != true && j <= _maxit ) { if(_verbose > 0) std::cout << "=== GMRes::restart" << std::endl; // get saved rhs b = b2; // calculate new defect _A.applyscaleadd(-1.0,x,b); // b -= Ax; // calculate preconditioned defect v[0] = 0.0; _W.apply(v[0],b); norm = _sp.norm(v[0]); norm_old = norm; } } //end while // postprocess preconditioner _W.post(x); // save solver statistics res.iterations = j-1; // it has to be j-1!!! res.reduction = static_cast(norm/norm_0); res.conv_rate = static_cast(pow(res.reduction,1.0/(j-1))); res.elapsed = watch.elapsed(); if(_verbose>0) print_result(res); } private : void print_result(const InverseOperatorResult& res) const { int k = res.iterations>0 ? res.iterations : 1; std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed/k << ", IT=" << res.iterations << std::endl; } void update(X& w, int i, const std::vector >& H, const std::vector& s, const std::vector& v) { // solution vector of the upper triangular system std::vector y(s); // backsolve for(int a=i-1; a>=0; a--) { field_type rhs(s[a]); for(int b=a+1; b typename std::enable_if::value,T>::type conjugate(const T& t) { return t; } template typename std::enable_if::value,T>::type conjugate(const T& t) { return conj(t); } void generatePlaneRotation(field_type &dx, field_type &dy, real_type &cs, field_type &sn) { using std::sqrt; using std::abs; real_type norm_dx = abs(dx); real_type norm_dy = abs(dy); if(norm_dy < 1e-15) { cs = 1.0; sn = 0.0; } else if(norm_dx < 1e-15) { cs = 0.0; sn = 1.0; } else if(norm_dy > norm_dx) { real_type temp = norm_dx/norm_dy; cs = 1.0/sqrt(1.0 + temp*temp); sn = cs; cs *= temp; sn *= dx/norm_dx; sn *= conjugate(dy)/norm_dy; } else { real_type temp = norm_dy/norm_dx; cs = 1.0/sqrt(1.0 + temp*temp); sn = cs; sn *= conjugate(dy/dx); } } void applyPlaneRotation(field_type &dx, field_type &dy, real_type &cs, field_type &sn) { field_type temp = cs * dx + sn * dy; dy = -conjugate(sn) * dx + cs * dy; dx = temp; } LinearOperator& _A; Preconditioner& _W; SeqScalarProduct ssp; ScalarProduct& _sp; int _restart; real_type _reduction; int _maxit; int _verbose; }; /** * @brief Generalized preconditioned conjugate gradient solver. * * A preconditioned conjugate gradient that allows * the preconditioner to change between iterations. * * One example for such preconditioner is AMG when used without * a direct coarse solver. In this case the number of iterations * performed on the coarsest level might change between applications. * * In contrast to CGSolver the search directions are stored and * the orthogonalization is done explicitly. */ template class GeneralizedPCGSolver : public InverseOperator { public: //! \brief The domain type of the operator to be inverted. typedef X domain_type; //! \brief The range type of the operator to be inverted. typedef X range_type; //! \brief The field type of the operator to be inverted. typedef typename X::field_type field_type; //! \brief The real type of the field type (is the same if using real numbers, but differs for std::complex) typedef typename FieldTraits::real_type real_type; /*! \brief Set up nonlinear preconditioned conjugate gradient solver. \copydoc LoopSolver::LoopSolver(L&,P&,double,int,int) \param restart When to restart the construction of the Krylov search space. */ template GeneralizedPCGSolver (L& op, P& prec, real_type reduction, int maxit, int verbose, int restart=10) : ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose), _restart(std::min(maxit,restart)) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P have to have the same category!"); static_assert(static_cast(L::category) == static_cast(SolverCategory::sequential), "L has to be sequential!"); } /*! \brief Set up nonlinear preconditioned conjugate gradient solver. \copydoc LoopSolver::LoopSolver(L&,S&,P&,double,int,int) \param restart When to restart the construction of the Krylov search space. */ template GeneralizedPCGSolver (L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose, int restart=10) : _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose), _restart(std::min(maxit,restart)) { static_assert(static_cast(L::category) == static_cast(P::category), "L and P must have the same category!"); static_assert(static_cast(L::category) == static_cast(S::category), "L and S must have the same category!"); } /*! \brief Apply inverse operator. \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) */ virtual void apply (X& x, X& b, InverseOperatorResult& res) { res.clear(); // clear solver statistics Timer watch; // start a timer _prec.pre(x,b); // prepare preconditioner _op.applyscaleadd(-1,x,b); // overwrite b with defect std::vector > p(_restart); std::vector pp(_restart); X q(x); // a temporary vector X prec_res(x); // a temporary vector for preconditioner output p[0].reset(new X(x)); real_type def0 = _sp.norm(b); // compute norm if (def0<1E-30) // convergence check { res.converged = true; res.iterations = 0; // fill statistics res.reduction = 0; res.conv_rate = 0; res.elapsed=0; if (_verbose>0) // final print std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed << ", IT=0" << std::endl; return; } if (_verbose>0) // printing { std::cout << "=== GeneralizedPCGSolver" << std::endl; if (_verbose>1) { this->printHeader(std::cout); this->printOutput(std::cout,0,def0); } } // some local variables real_type def=def0; // loop variables field_type rho, lambda; int i=0; int ii=0; // determine initial search direction *(p[0]) = 0; // clear correction _prec.apply(*(p[0]),b); // apply preconditioner rho = _sp.dot(*(p[0]),b); // orthogonalization _op.apply(*(p[0]),q); // q=Ap pp[0] = _sp.dot(*(p[0]),q); // scalar product lambda = rho/pp[0]; // minimization x.axpy(lambda,*(p[0])); // update solution b.axpy(-lambda,q); // update defect // convergence test real_type defnew=_sp.norm(b); // comp defect norm if (_verbose>1) // print this->printOutput(std::cout,++i,defnew,def); def = defnew; // update norm if (def0) // final print { std::cout << "=== rate=" << res.conv_rate << ", T=" << res.elapsed << ", TIT=" << res.elapsed << ", IT=" << 1 << std::endl; } return; } while(i<_maxit) { // the loop int end=std::min(_restart, _maxit-i+1); for (ii=1; ii supported)"); cc_ = new cholmod_common(); cholmod_l_start(cc_); setMatrix(matrix); } /** @brief Constructor for compatibility with SuperLU standard constructor * * This computes the matrix decomposition, and may take a long time * (and use a lot of memory). * * @param matrix the matrix to solve for * @param verbose, 0 or 1, set the verbosity level, defaults to 0 */ SPQR(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false), verbose_(verbose) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in SPQR (only double and std::complex supported)"); cc_ = new cholmod_common(); cholmod_l_start(cc_); setMatrix(matrix); } /** @brief Default constructor. */ SPQR() : matrixIsLoaded_(false), verbose_(0) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in SPQR (only double and std::complex supported)"); cc_ = new cholmod_common(); cholmod_l_start(cc_); } /** @brief Destructor. */ virtual ~SPQR() { if ((spqrMatrix_.N() + spqrMatrix_.M() > 0) || matrixIsLoaded_) free(); cholmod_l_finish(cc_); } /** \copydoc InverseOperator::apply(X&, Y&, InverseOperatorResult&) */ virtual void apply(domain_type& x, range_type& b, InverseOperatorResult& res) { const std::size_t dimMat(spqrMatrix_.N()); // fill B for(std::size_t k = 0; k != dimMat; ++k) (static_cast(B_->x))[k] = b[k]; cholmod_dense* BTemp = B_; B_ = SuiteSparseQR_qmult(0, spqrfactorization_, B_, cc_); cholmod_dense* X = SuiteSparseQR_solve(1, spqrfactorization_, B_, cc_); cholmod_l_free_dense(&BTemp, cc_); // fill x for(std::size_t k = 0; k != dimMat; ++k) x [k] = (static_cast(X->x))[k]; cholmod_l_free_dense(&X, cc_); // this is a direct solver res.iterations = 1; res.converged = true; if(verbose_ > 0) { std::cout<SPQR_flopcount<SPQR_analyze_time<<" s"<SPQR_factorize_time<<" s"<SPQR_solve_time<<" s"<memory_usage<<" bytes"<SPQR_istat[4]< 0) || matrixIsLoaded_) free(); spqrMatrix_ = matrix; decompose(); } template void setSubMatrix(const Matrix& matrix, const S& rowIndexSet) { if ((spqrMatrix_.N() + spqrMatrix_.M() > 0) || matrixIsLoaded_) free(); spqrMatrix_.setMatrix(matrix,rowIndexSet); decompose(); } /** * @brief Sets the verbosity level for the solver. * @param v verbosity level: 0 only error messages, 1 a bit of statistics. */ inline void setVerbosity(int v) { verbose_=v; } /** * @brief Return the matrix factorization. * @warning It is up to the user to keep consistency. */ inline SuiteSparseQR_factorization* getFactorization() { return spqrfactorization_; } /** * @brief Return the column coppressed matrix. * @warning It is up to the user to keep consistency. */ inline SPQRMatrix& getInternalMatrix() { return spqrMatrix_; } /** * @brief Free allocated space. * @warning Later calling apply will result in an error. */ void free() { cholmod_l_free_sparse(&A_, cc_); cholmod_l_free_dense(&B_, cc_); SuiteSparseQR_free(&spqrfactorization_, cc_); spqrMatrix_.free(); matrixIsLoaded_ = false; } /** @brief Get method name. */ inline const char* name() { return "SPQR"; } private: template friend class SeqOverlappingSchwarz; friend struct SeqOverlappingSchwarzAssemblerHelper,true>; /** @brief Computes the QR decomposition. */ void decompose() { const std::size_t dimMat(spqrMatrix_.N()); const std::size_t nnz(spqrMatrix_.getColStart()[dimMat]); // initialise the matrix A (sorted, packed, unsymmetric, real entries) A_ = cholmod_l_allocate_sparse(dimMat, dimMat, nnz, 1, 1, 0, 1, cc_); // copy all the entries of Ap, Ai, Ax for(std::size_t k = 0; k != (dimMat+1); ++k) (static_cast(A_->p))[k] = spqrMatrix_.getColStart()[k]; for(std::size_t k = 0; k != nnz; ++k) { (static_cast(A_->i))[k] = spqrMatrix_.getRowIndex()[k]; (static_cast(A_->x))[k] = spqrMatrix_.getValues()[k]; } // initialise the vector B B_ = cholmod_l_allocate_dense(dimMat, 1, dimMat, A_->xtype, cc_); // compute factorization of A spqrfactorization_=SuiteSparseQR_factorize(SPQR_ORDERING_DEFAULT,SPQR_DEFAULT_TOL,A_,cc_); } SPQRMatrix spqrMatrix_; bool matrixIsLoaded_; int verbose_; cholmod_common* cc_; cholmod_sparse* A_; cholmod_dense* B_; SuiteSparseQR_factorization* spqrfactorization_; }; template struct IsDirectSolver,A> > > { enum {value = true}; }; template struct StoresColumnCompressed,A> > > { enum {value = true}; }; } #endif //HAVE_SUITESPARSE_SPQR #endif //DUNE_ISTL_SPQR_HH dune-istl-2.5.1/dune/istl/superlu.hh000066400000000000000000000547611313314427100173650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SUPERLU_HH #define DUNE_ISTL_SUPERLU_HH #if HAVE_SUPERLU #ifdef TRUE #undef TRUE #endif #ifdef FALSE #undef FALSE #endif #ifndef SUPERLU_NTYPE #define SUPERLU_NTYPE 1 #endif #if SUPERLU_NTYPE==0 #include "slu_sdefs.h" #endif #if SUPERLU_NTYPE==1 #include "slu_ddefs.h" #endif #if SUPERLU_NTYPE==2 #include "slu_cdefs.h" #endif #if SUPERLU_NTYPE>=3 #include "slu_zdefs.h" #endif #include "solvers.hh" #include "supermatrix.hh" #include #include #include "bcrsmatrix.hh" #include "bvector.hh" #include "istlexception.hh" #include #include #include #include namespace Dune { /** * @addtogroup ISTL * * @{ */ /** * @file * @author Markus Blatt * @brief Classes for using SuperLU with ISTL matrices. */ template class SuperLU {}; template class SeqOverlappingSchwarz; template struct SeqOverlappingSchwarzAssemblerHelper; template struct SuperLUSolveChooser {}; template struct SuperLUDenseMatChooser {}; template struct SuperLUQueryChooser {}; template struct QuerySpaceChooser {}; #if SUPERLU_NTYPE==0 template<> struct SuperLUDenseMatChooser { static void create(SuperMatrix *mat, int n, int m, float *dat, int n1, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { sCreate_Dense_Matrix(mat, n, m, dat, n1, stype, dtype, mtype); } static void destroy(SuperMatrix*) {} }; template<> struct SuperLUSolveChooser { static void solve(superlu_options_t *options, SuperMatrix *mat, int *perm_c, int *perm_r, int *etree, char *equed, float *R, float *C, SuperMatrix *L, SuperMatrix *U, void *work, int lwork, SuperMatrix *B, SuperMatrix *X, float *rpg, float *rcond, float *ferr, float *berr, mem_usage_t *memusage, SuperLUStat_t *stat, int *info) { #if SUPERLU_MIN_VERSION_5 GlobalLU_t gLU; sgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, &gLU, memusage, stat, info); #else sgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, memusage, stat, info); #endif } }; template<> struct QuerySpaceChooser { static void querySpace(SuperMatrix* L, SuperMatrix* U, mem_usage_t* memusage) { sQuerySpace(L,U,memusage); } }; #endif #if SUPERLU_NTYPE==1 template<> struct SuperLUDenseMatChooser { static void create(SuperMatrix *mat, int n, int m, double *dat, int n1, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { dCreate_Dense_Matrix(mat, n, m, dat, n1, stype, dtype, mtype); } static void destroy(SuperMatrix * /* mat */) {} }; template<> struct SuperLUSolveChooser { static void solve(superlu_options_t *options, SuperMatrix *mat, int *perm_c, int *perm_r, int *etree, char *equed, double *R, double *C, SuperMatrix *L, SuperMatrix *U, void *work, int lwork, SuperMatrix *B, SuperMatrix *X, double *rpg, double *rcond, double *ferr, double *berr, mem_usage_t *memusage, SuperLUStat_t *stat, int *info) { #if SUPERLU_MIN_VERSION_5 GlobalLU_t gLU; dgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, &gLU, memusage, stat, info); #else dgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, memusage, stat, info); #endif } }; template<> struct QuerySpaceChooser { static void querySpace(SuperMatrix* L, SuperMatrix* U, mem_usage_t* memusage) { dQuerySpace(L,U,memusage); } }; #endif #if SUPERLU_NTYPE>=3 template<> struct SuperLUDenseMatChooser > { static void create(SuperMatrix *mat, int n, int m, std::complex *dat, int n1, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { zCreate_Dense_Matrix(mat, n, m, reinterpret_cast(dat), n1, stype, dtype, mtype); } static void destroy(SuperMatrix*) {} }; template<> struct SuperLUSolveChooser > { static void solve(superlu_options_t *options, SuperMatrix *mat, int *perm_c, int *perm_r, int *etree, char *equed, double *R, double *C, SuperMatrix *L, SuperMatrix *U, void *work, int lwork, SuperMatrix *B, SuperMatrix *X, double *rpg, double *rcond, double *ferr, double *berr, mem_usage_t *memusage, SuperLUStat_t *stat, int *info) { #if SUPERLU_MIN_VERSION_5 GlobalLU_t gLU; zgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, &gLU, memusage, stat, info); #else zgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, memusage, stat, info); #endif } }; template<> struct QuerySpaceChooser > { static void querySpace(SuperMatrix* L, SuperMatrix* U, mem_usage_t* memusage) { zQuerySpace(L,U,memusage); } }; #endif #if SUPERLU_NTYPE==2 template<> struct SuperLUDenseMatChooser > { static void create(SuperMatrix *mat, int n, int m, std::complex *dat, int n1, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { cCreate_Dense_Matrix(mat, n, m, reinterpret_cast< ::complex*>(dat), n1, stype, dtype, mtype); } static void destroy(SuperMatrix* /* mat */) {} }; template<> struct SuperLUSolveChooser > { static void solve(superlu_options_t *options, SuperMatrix *mat, int *perm_c, int *perm_r, int *etree, char *equed, float *R, float *C, SuperMatrix *L, SuperMatrix *U, void *work, int lwork, SuperMatrix *B, SuperMatrix *X, float *rpg, float *rcond, float *ferr, float *berr, mem_usage_t *memusage, SuperLUStat_t *stat, int *info) { #if SUPERLU_MIN_VERSION_5 GlobalLU_t gLU; cgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, &gLU, memusage, stat, info); #else cgssvx(options, mat, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X, rpg, rcond, ferr, berr, memusage, stat, info); #endif } }; template<> struct QuerySpaceChooser > { static void querySpace(SuperMatrix* L, SuperMatrix* U, mem_usage_t* memusage) { cQuerySpace(L,U,memusage); } }; #endif /** * @brief SuperLu Solver * * Uses the well known
SuperLU * package to solve the * system. * * SuperLU supports single and double precision floating point and complex * numbers. Unfortunately these cannot be used at the same time. * Therfore users must set SUPERLU_NTYPE (0: float, 1: double, * 2: std::complex, 3: std::complex) * if the numeric type should be different from double. */ template class SuperLU,A > > : public InverseOperator< BlockVector, typename A::template rebind >::other>, BlockVector, typename A::template rebind >::other> > { public: /** @brief The matrix type. */ typedef Dune::BCRSMatrix,A> Matrix; typedef Dune::BCRSMatrix,A> matrix_type; /** @brief The corresponding SuperLU Matrix type.*/ typedef Dune::SuperLUMatrix SuperLUMatrix; /** @brief Type of an associated initializer class. */ typedef SuperMatrixInitializer,A> > MatrixInitializer; /** @brief The type of the domain of the solver. */ typedef Dune::BlockVector< FieldVector, typename A::template rebind >::other> domain_type; /** @brief The type of the range of the solver. */ typedef Dune::BlockVector< FieldVector, typename A::template rebind >::other> range_type; /** * @brief Constructs the SuperLU solver. * * During the construction the matrix will be decomposed. * That means that in each apply call forward and backward * substitutions take place (and no decomposition). * @param mat The matrix of the system to solve. * @param verbose If true some statistics are printed. * @param reusevector Default value is true. If true the two vectors are allocate in * the first call to apply. These get resused in subsequent calls to apply * and are deallocated in the destructor. If false these vectors are allocated * at the beginning and deallocated at the end of each apply method. This allows * using the same instance of superlu from different threads. */ explicit SuperLU(const Matrix& mat, bool verbose=false, bool reusevector=true); /** * @brief Empty default constructor. * * Use setMatrix to tell SuperLU for what matrix it solves. * Using this constructor no vectors will be reused. */ SuperLU(); ~SuperLU(); /** * \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&) */ void apply(domain_type& x, range_type& b, InverseOperatorResult& res); /** * \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) */ void apply (domain_type& x, range_type& b, double reduction, InverseOperatorResult& res) { DUNE_UNUSED_PARAMETER(reduction); apply(x,b,res); } /** * @brief Apply SuperLu to C arrays. */ void apply(T* x, T* b); /** @brief Initialize data from given matrix. */ void setMatrix(const Matrix& mat); typename SuperLUMatrix::size_type nnz() const { return mat.nnz(); } template void setSubMatrix(const Matrix& mat, const S& rowIndexSet); void setVerbosity(bool v); /** * @brief free allocated space. * @warning later calling apply will result in an error. */ void free(); const char* name() { return "SuperLU"; } private: friend class std::mem_fun_ref_t; template friend class SeqOverlappingSchwarz; friend struct SeqOverlappingSchwarzAssemblerHelper,true>; SuperLUMatrix& getInternalMatrix() { return mat; } /** @brief computes the LU Decomposition */ void decompose(); SuperLUMatrix mat; SuperMatrix L, U, B, X; int *perm_c, *perm_r, *etree; typename GetSuperLUType::float_type *R, *C; T *bstore; superlu_options_t options; char equed; void *work; int lwork; bool first, verbose, reusevector; }; template SuperLU,A> > ::~SuperLU() { if(mat.N()+mat.M()>0) free(); } template void SuperLU,A> >::free() { delete[] perm_c; delete[] perm_r; delete[] etree; delete[] R; delete[] C; if(lwork>=0) { Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); } lwork=0; if(!first && reusevector) { SUPERLU_FREE(B.Store); SUPERLU_FREE(X.Store); } mat.free(); } template SuperLU,A> > ::SuperLU(const Matrix& mat_, bool verbose_, bool reusevector_) : work(0), lwork(0), first(true), verbose(verbose_), reusevector(reusevector_) { setMatrix(mat_); } template SuperLU,A> >::SuperLU() : work(0), lwork(0),verbose(false), reusevector(false) {} template void SuperLU,A> >::setVerbosity(bool v) { verbose=v; } template void SuperLU,A> >::setMatrix(const Matrix& mat_) { if(mat.N()+mat.M()>0) { free(); } lwork=0; work=0; //a=&mat_; mat=mat_; decompose(); } template template void SuperLU,A> >::setSubMatrix(const Matrix& mat_, const S& mrs) { if(mat.N()+mat.M()>0) { free(); } lwork=0; work=0; //a=&mat_; mat.setMatrix(mat_,mrs); decompose(); } template void SuperLU,A> >::decompose() { first = true; perm_c = new int[mat.M()]; perm_r = new int[mat.N()]; etree = new int[mat.M()]; R = new typename GetSuperLUType::float_type[mat.N()]; C = new typename GetSuperLUType::float_type[mat.M()]; set_default_options(&options); // Do the factorization B.ncol=0; B.Stype=SLU_DN; B.Dtype=GetSuperLUType::type; B.Mtype= SLU_GE; DNformat fakeFormat; fakeFormat.lda=mat.N(); B.Store=&fakeFormat; X.Stype=SLU_DN; X.Dtype=GetSuperLUType::type; X.Mtype= SLU_GE; X.ncol=0; X.Store=&fakeFormat; typename GetSuperLUType::float_type rpg, rcond, ferr=1e10, berr=1e10; int info; mem_usage_t memusage; SuperLUStat_t stat; StatInit(&stat); SuperLUSolveChooser::solve(&options, &static_cast(mat), perm_c, perm_r, etree, &equed, R, C, &L, &U, work, lwork, &B, &X, &rpg, &rcond, &ferr, &berr, &memusage, &stat, &info); if(verbose) { dinfo<<"LU factorization: dgssvx() returns info "<< info< 0 && lwork == -1 ) { dinfo<<"** Estimated memory: "<< info - n<colptr[i]; c < Ustore->colptr[i+1]; ++c) //if(Ustore->rowind[c]==i) std::cout<rowind[c]<<"->"<<((double*)Ustore->nzval)[c]<<" "; if(k==0){ // k=-1; }std::cout<colptr[i]; c < Ustore->colptr[i+1]; ++c) //if(Ustore->rowind[c]==i) std::cout<rowind[c]<<"->"<<((double*)Ustore->nzval)[c]<<" "; if(k==0){ // k=-1; }std::cout< void SuperLU,A> > ::apply(domain_type& x, range_type& b, InverseOperatorResult& res) { if (mat.N() != b.dim()) DUNE_THROW(ISTLError, "Size of right-hand-side vector b does not match the number of matrix rows!"); if (mat.M() != x.dim()) DUNE_THROW(ISTLError, "Size of solution vector x does not match the number of matrix columns!"); if (mat.M()+mat.N()==0) DUNE_THROW(ISTLError, "Matrix of SuperLU is null!"); SuperMatrix* mB = &B; SuperMatrix* mX = &X; SuperMatrix rB, rX; if (reusevector) { if(first) { SuperLUDenseMatChooser::create(&B, (int)mat.N(), 1, reinterpret_cast(&b[0]), (int)mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); SuperLUDenseMatChooser::create(&X, (int)mat.N(), 1, reinterpret_cast(&x[0]), (int)mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); first=false; }else{ ((DNformat*)B.Store)->nzval=&b[0]; ((DNformat*)X.Store)->nzval=&x[0]; } } else { SuperLUDenseMatChooser::create(&rB, (int)mat.N(), 1, reinterpret_cast(&b[0]), (int)mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); SuperLUDenseMatChooser::create(&rX, (int)mat.N(), 1, reinterpret_cast(&x[0]), (int)mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); mB = &rB; mX = &rX; } typename GetSuperLUType::float_type rpg, rcond, ferr=1e10, berr; int info; mem_usage_t memusage; SuperLUStat_t stat; /* Initialize the statistics variables. */ StatInit(&stat); /* range_type d=b; a->usmv(-1, x, d); double def0=d.two_norm(); */ #ifdef SUPERLU_MIN_VERSION_4_3 options.IterRefine=SLU_DOUBLE; #else options.IterRefine=DOUBLE; #endif SuperLUSolveChooser::solve(&options, &static_cast(mat), perm_c, perm_r, etree, &equed, R, C, &L, &U, work, lwork, mB, mX, &rpg, &rcond, &ferr, &berr, &memusage, &stat, &info); res.iterations=1; /* if(options.Equil==YES) // undo scaling of right hand side std::transform(reinterpret_cast(&b[0]),reinterpret_cast(&b[0])+mat.M(), C, reinterpret_cast(&d[0]), std::divides()); else d=b; a->usmv(-1, x, d); res.reduction=d.two_norm()/def0; res.conv_rate = res.reduction; res.converged=(res.reduction<1e-10||d.two_norm()<1e-18); */ res.converged=true; if(verbose) { dinfo<<"Triangular solve: dgssvx() returns info "<< info< void SuperLU,A> > ::apply(T* x, T* b) { if(mat.N()+mat.M()==0) DUNE_THROW(ISTLError, "Matrix of SuperLU is null!"); SuperMatrix* mB = &B; SuperMatrix* mX = &X; SuperMatrix rB, rX; if (reusevector) { if(first) { SuperLUDenseMatChooser::create(&B, mat.N(), 1, b, mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); SuperLUDenseMatChooser::create(&X, mat.N(), 1, x, mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); first=false; }else{ ((DNformat*) B.Store)->nzval=b; ((DNformat*)X.Store)->nzval=x; } } else { SuperLUDenseMatChooser::create(&rB, mat.N(), 1, b, mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); SuperLUDenseMatChooser::create(&rX, mat.N(), 1, x, mat.N(), SLU_DN, GetSuperLUType::type, SLU_GE); mB = &rB; mX = &rX; } typename GetSuperLUType::float_type rpg, rcond, ferr=1e10, berr; int info; mem_usage_t memusage; SuperLUStat_t stat; /* Initialize the statistics variables. */ StatInit(&stat); #ifdef SUPERLU_MIN_VERSION_4_3 options.IterRefine=SLU_DOUBLE; #else options.IterRefine=DOUBLE; #endif SuperLUSolveChooser::solve(&options, &static_cast(mat), perm_c, perm_r, etree, &equed, R, C, &L, &U, work, lwork, mB, mX, &rpg, &rcond, &ferr, &berr, &memusage, &stat, &info); if(verbose) { dinfo<<"Triangular solve: dgssvx() returns info "<< info< struct IsDirectSolver,A> > > { enum { value=true}; }; template struct StoresColumnCompressed,A> > > { enum { value = true }; }; } // undefine macros from SuperLU's slu_util.h #undef FIRSTCOL_OF_SNODE #undef NO_MARKER #undef NUM_TEMPV #undef USER_ABORT #undef USER_MALLOC #undef SUPERLU_MALLOC #undef USER_FREE #undef SUPERLU_FREE #undef CHECK_MALLOC #undef SUPERLU_MAX #undef SUPERLU_MIN #undef L_SUB_START #undef L_SUB #undef L_NZ_START #undef L_FST_SUPC #undef U_NZ_START #undef U_SUB #undef TRUE #undef FALSE #undef EMPTY #undef NODROP #undef DROP_BASIC #undef DROP_PROWS #undef DROP_COLUMN #undef DROP_AREA #undef DROP_SECONDARY #undef DROP_DYNAMIC #undef DROP_INTERP #undef MILU_ALPHA #endif // HAVE_SUPERLU #endif // DUNE_SUPERLU_HH dune-istl-2.5.1/dune/istl/supermatrix.hh000066400000000000000000000214761313314427100202460ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_SUPERMATRIX_HH #define DUNE_ISTL_SUPERMATRIX_HH #if HAVE_SUPERLU #ifndef SUPERLU_NTYPE #define SUPERLU_NTYPE 1 #endif #if SUPERLU_NTYPE==0 #include "slu_sdefs.h" #endif #if SUPERLU_NTYPE==1 #include "slu_ddefs.h" #endif #if SUPERLU_NTYPE==2 #include "slu_cdefs.h" #endif #if SUPERLU_NTYPE>=3 #include "slu_zdefs.h" #endif #include "bcrsmatrix.hh" #include "bvector.hh" #include #include #include #include #include"colcompmatrix.hh" namespace Dune { template struct SuperMatrixCreateSparseChooser {}; template struct SuperMatrixPrinter {}; #if SUPERLU_NTYPE==0 template<> struct SuperMatrixCreateSparseChooser { static void create(SuperMatrix *mat, int n, int m, int offset, float *values, int *rowindex, int* colindex, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { sCreate_CompCol_Matrix(mat, n, m, offset, values, rowindex, colindex, stype, dtype, mtype); } }; template<> struct SuperMatrixPrinter { static void print(char* name, SuperMatrix* mat) { sPrint_CompCol_Matrix(name, mat); } }; #endif #if SUPERLU_NTYPE==1 template<> struct SuperMatrixCreateSparseChooser { static void create(SuperMatrix *mat, int n, int m, int offset, double *values, int *rowindex, int* colindex, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { dCreate_CompCol_Matrix(mat, n, m, offset, values, rowindex, colindex, stype, dtype, mtype); } }; template<> struct SuperMatrixPrinter { static void print(char* name, SuperMatrix* mat) { dPrint_CompCol_Matrix(name, mat); } }; #endif #if SUPERLU_NTYPE==2 template<> struct SuperMatrixCreateSparseChooser > { static void create(SuperMatrix *mat, int n, int m, int offset, std::complex *values, int *rowindex, int* colindex, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { cCreate_CompCol_Matrix(mat, n, m, offset, reinterpret_cast< ::complex*>(values), rowindex, colindex, stype, dtype, mtype); } }; template<> struct SuperMatrixPrinter > { static void print(char* name, SuperMatrix* mat) { cPrint_CompCol_Matrix(name, mat); } }; #endif #if SUPERLU_NTYPE>=3 template<> struct SuperMatrixCreateSparseChooser > { static void create(SuperMatrix *mat, int n, int m, int offset, std::complex *values, int *rowindex, int* colindex, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { zCreate_CompCol_Matrix(mat, n, m, offset, reinterpret_cast(values), rowindex, colindex, stype, dtype, mtype); } }; template<> struct SuperMatrixPrinter > { static void print(char* name, SuperMatrix* mat) { zPrint_CompCol_Matrix(name, mat); } }; #endif template struct BaseGetSuperLUType { static const Dtype_t type; }; template struct GetSuperLUType {}; template const Dtype_t BaseGetSuperLUType::type = std::is_same::value ? SLU_S : ( std::is_same >::value ? SLU_Z : ( std::is_same >::value ? SLU_C : SLU_D )); template<> struct GetSuperLUType : public BaseGetSuperLUType { typedef double float_type; }; template<> struct GetSuperLUType : public BaseGetSuperLUType { typedef float float_type; }; template<> struct GetSuperLUType > : public BaseGetSuperLUType > { typedef double float_type; }; template<> struct GetSuperLUType > : public BaseGetSuperLUType > { typedef float float_type; }; /** * @brief Utility class for converting an ISTL Matrix * into a SuperLU Matrix. */ template struct SuperLUMatrix {}; template struct SuperMatrixInitializer {}; template class SuperLU; /** * @brief Converter for BCRSMatrix to SuperLU Matrix. */ template class SuperLUMatrix,TA> > : public ColCompMatrix,TA> > { template friend class SeqOverlappingSchwarz; friend struct SuperMatrixInitializer,TA> >; public: /** @brief The type of the matrix to convert. */ typedef BCRSMatrix,TA> Matrix; friend struct SeqOverlappingSchwarzAssemblerHelper, true>; typedef typename Matrix::size_type size_type; /** * @brief Constructor that initializes the data. * @param mat The matrix to convert. */ explicit SuperLUMatrix(const Matrix& mat) : ColCompMatrix,TA> >(mat) {} SuperLUMatrix() : ColCompMatrix,TA> >() {} /** @brief Destructor */ virtual ~SuperLUMatrix() { if (this->N_+this->M_*this->Nnz_ != 0) free(); } /** @brief Cast to a SuperLU Matrix */ operator SuperMatrix&() { return A; } /** @brief Cast to a SuperLU Matrix */ operator const SuperMatrix&() const { return A; } SuperLUMatrix,TA> >& operator=(const BCRSMatrix,TA>& mat) { this->ColCompMatrix,TA> >::operator=(mat); SuperMatrixCreateSparseChooser ::create(&A, this->N_, this->M_, this->colstart[this->N_], this->values,this->rowindex, this->colstart, SLU_NC, static_cast(GetSuperLUType::type), SLU_GE); return *this; } SuperLUMatrix,TA> >& operator=(const SuperLUMatrix ,TA> >& mat) { this->ColCompMatrix,TA> >::operator=(mat); SuperMatrixCreateSparseChooser ::create(&A, this->N_, this->M_, this->colstart[this->N_], this->values,this->rowindex, this->colstart, SLU_NC, static_cast(GetSuperLUType::type), SLU_GE); return *this; } /** * @brief Initialize data from a given set of matrix rows and columns * @tparam The type of the row index set. * @param mat the matrix with the values * @param mrs The set of row (and column) indices to represent */ virtual void setMatrix(const Matrix& mat, const std::set& mrs) { if(this->N_+this->M_+this->Nnz_!=0) free(); this->N_=mrs.size()*n; this->M_=mrs.size()*m; SuperMatrixInitializer initializer(*this); copyToColCompMatrix(initializer, MatrixRowSubset >(mat,mrs)); } /** @brief Initialize data from given matrix. */ virtual void setMatrix(const Matrix& mat) { this->N_=n*mat.N(); this->M_=m*mat.M(); SuperMatrixInitializer initializer(*this); copyToColCompMatrix(initializer, MatrixRowSet(mat)); } /** @brief free allocated space. */ virtual void free() { ColCompMatrix,TA> >::free(); SUPERLU_FREE(A.Store); } private: SuperMatrix A; }; template class SuperMatrixInitializer,A> > : public ColCompMatrixInitializer,A> > { template friend class OverlappingSchwarzInitializer; public: typedef BCRSMatrix,A> Matrix; typedef Dune::SuperLUMatrix SuperLUMatrix; SuperMatrixInitializer(SuperLUMatrix& lum) : ColCompMatrixInitializer,A> >(lum) ,slumat(&lum) {} SuperMatrixInitializer() : ColCompMatrixInitializer,A> >() {} virtual void createMatrix() const { ColCompMatrixInitializer,A> >::createMatrix(); SuperMatrixCreateSparseChooser ::create(&slumat->A, slumat->N_, slumat->M_, slumat->colstart[this->cols], slumat->values,slumat->rowindex, slumat->colstart, SLU_NC, static_cast(GetSuperLUType::type), SLU_GE); } private: SuperLUMatrix* slumat; }; } #endif // HAVE_SUPERLU #endif dune-istl-2.5.1/dune/istl/test/000077500000000000000000000000001313314427100163075ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/test/CMakeLists.txt000066400000000000000000000043751313314427100210600ustar00rootroot00000000000000# install the test tools as we want to support testing 3rd-party vectors with an installed dune-istl install(FILES vectortest.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/istl/test) dune_add_test(SOURCES basearraytest.cc) dune_add_test(SOURCES bcrsassigntest.cc) dune_add_test(SOURCES bcrsnormtest.cc) dune_add_test(SOURCES dotproducttest.cc) dune_add_test(SOURCES complexmatrixtest.cc) dune_add_test(SOURCES fieldvectortest.cc) dune_add_test(SOURCES matrixnormtest.cc) dune_add_test(SOURCES matrixutilstest.cc) dune_add_test(SOURCES matrixtest.cc) dune_add_test(SOURCES bvectortest.cc) dune_add_test(SOURCES vbvectortest.cc) dune_add_test(SOURCES bcrsbuild.cc) dune_add_test(SOURCES bcrsimplicitbuild.cc COMPILE_DEFINITIONS DUNE_ISTL_WITH_CHECKING=1) dune_add_test(SOURCES matrixiteratortest.cc) dune_add_test(SOURCES mmtest.cc) dune_add_test(SOURCES multitypeblockmatrixtest.cc) dune_add_test(SOURCES multitypeblockvectortest.cc) dune_add_test(SOURCES mv.cc) dune_add_test(SOURCES iotest.cc) dune_add_test(SOURCES inverseoperator2prectest.cc) dune_add_test(SOURCES scaledidmatrixtest.cc) dune_add_test(SOURCES solvertest.cc) dune_add_test(SOURCES solveraborttest.cc) # Pardiso tests dune_add_test(SOURCES test_pardiso.cc) # SuperLU tests dune_add_test(NAME superlustest SOURCES superlutest.cc COMPILE_DEFINITIONS SUPERLU_NTYPE=0) dune_add_test(SOURCES superlutest.cc) dune_add_test(NAME superluctest SOURCES superlutest.cc COMPILE_DEFINITIONS SUPERLU_NTYPE=2) dune_add_test(NAME superluztest SOURCES superlutest.cc COMPILE_DEFINITIONS SUPERLU_NTYPE=3) dune_add_test(SOURCES complexrhstest.cc COMPILE_DEFINITIONS SUPERLU_NTYPE=3) # SuiteSparse tests dune_add_test(SOURCES umfpacktest.cc) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "umfpack_decomp") dune_add_test(SOURCES ldltest.cc) dune_add_test(SOURCES spqrtest.cc) dune_add_test(SOURCES overlappingschwarztest.cc) # MPI tests dune_add_test(SOURCES matrixredisttest.cc CMAKE_GUARD MPI_FOUND) dune_add_test(SOURCES vectorcommtest.cc CMAKE_GUARD MPI_FOUND) dune_add_test(SOURCES matrixmarkettest.cc) exclude_from_headercheck(complexdata.hh) dune-istl-2.5.1/dune/istl/test/basearraytest.cc000066400000000000000000000004311313314427100214650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include using namespace Dune; int main() { base_array v1(10); base_array v2 = v1; v1.resize(20); v1 = v2; } dune-istl-2.5.1/dune/istl/test/bcrsassigntest.cc000066400000000000000000000012671313314427100216620ustar00rootroot00000000000000#include #include using namespace Dune; int main (int argc, char** argv) { try { typedef BCRSMatrix > Mat; Mat A(1,1, Mat::random); A.setrowsize(0,1); A.endrowsizes(); A.addindex(0, 0); A.endindices(); A = 0; Mat B(2,2, Mat::random); B.setrowsize(0,2); B.setrowsize(1,1); B.endrowsizes(); B.addindex(0, 0); B.addindex(0, 1); B.addindex(1, 1); B.endindices(); B = 0; B = A; } catch(Exception e){ std::cout< #include #include #include template struct Builder { void randomBuild(int m, int n) { DUNE_THROW(Dune::NotImplemented, "No specialization"); } }; template struct Builder > { void randomBuild(int rows, int cols) { int maxNZCols = 15; // maximal number of nonzeros per row { Dune::BCRSMatrix matrix( rows, cols, Dune::BCRSMatrix::random ); for(int i=0; i=0) matrix.addindex(i,i-1); if(i+1 matrix1(matrix); Dune::printmatrix(std::cout, matrix, "random", "row"); } /*{ Dune::BCRSMatrix matrix( rows, cols, rows*maxNZCols, Dune::BCRSMatrix::random ); for(int i=0; i=0) matrix.addindex(i,i-1); if(i+1& matrix, int /* rows */, int cols) { for(typename Dune::BCRSMatrix::CreateIterator ci=matrix.createbegin(), cend=matrix.createend(); ci!=cend; ++ci) { int i=ci.index(); if(i=0 && i-1 matrix1(matrix); Dune::printmatrix(std::cout, matrix1, "row_wise", "row"); // test copy assignment Dune::BCRSMatrix matrix2; matrix2 = matrix; Dune::printmatrix(std::cout, matrix2, "row_wise", "row"); } void rowWiseBuild(int rows, int cols) { Dune::BCRSMatrix matrix( rows, cols, Dune::BCRSMatrix::row_wise ); rowWiseBuild(matrix, rows, cols); } void rowWiseBuild(int rows, int cols, int nnz) { Dune::BCRSMatrix matrix( rows, cols, nnz, Dune::BCRSMatrix::row_wise ); rowWiseBuild(matrix, rows, cols); } }; // This code used to trigger a valgrind 'uninitialized memory' warning; see FS 1041 void testDoubleSetSize() { Dune::BCRSMatrix > foo; foo.setSize(5,5); foo.setSize(5,5); } int main() { try{ Builder > > builder; builder.randomBuild(5,4); builder.rowWiseBuild(5,4,13); builder.rowWiseBuild(5,4); testDoubleSetSize(); }catch(Dune::Exception e) { std::cerr << e< #include #include #include typedef Dune::BCRSMatrix > ScalarMatrix; void buildMatrix(ScalarMatrix& m) { m.entry(0,0) = 1.0; m.entry(0,1) = 1.0; m.entry(0,2) = 1.0; m.entry(0,3) = 1.0; m.entry(1,0) = 1.0; m.entry(1,1) = 1.0; m.entry(1,2) = 1.0; m.entry(2,1) = 1.0; m.entry(2,2) = 1.0; m.entry(2,3) = 1.0; m.entry(3,2) = 1.0; m.entry(3,3) = 1.0; m.entry(3,4) = 1.0; m.entry(4,3) = 1.0; m.entry(4,4) = 1.0; m.entry(4,5) = 1.0; m.entry(5,4) = 1.0; m.entry(5,5) = 1.0; m.entry(5,6) = 1.0; m.entry(6,5) = 1.0; m.entry(6,6) = 1.0; m.entry(6,7) = 1.0; m.entry(7,6) = 1.0; m.entry(7,7) = 1.0; m.entry(7,8) = 1.0; m.entry(8,7) = 1.0; m.entry(8,8) = 1.0; m.entry(8,9) = 1.0; m.entry(9,8) = 1.0; m.entry(9,9) = 1.0; // add some more entries in random order m.entry(7,3) = 1.0; m.entry(6,0) = 1.0; m.entry(3,8) = 1.0; } template void setMatrix(M& m) { m[0][0] = 1.0; m[0][1] = 1.0; m[0][2] = 1.0; m[0][3] = 1.0; m[1][0] = 1.0; m[1][1] = 1.0; m[1][2] = 1.0; m[2][1] = 1.0; m[2][2] = 1.0; m[2][3] = 1.0; m[3][2] = 1.0; m[3][3] = 1.0; m[3][4] = 1.0; m[4][3] = 1.0; m[4][4] = 1.0; m[4][5] = 1.0; m[5][4] = 1.0; m[5][5] = 1.0; m[5][6] = 1.0; m[6][5] = 1.0; m[6][6] = 1.0; m[6][7] = 1.0; m[7][6] = 1.0; m[7][7] = 1.0; m[7][8] = 1.0; m[8][7] = 1.0; m[8][8] = 1.0; m[8][9] = 1.0; m[9][8] = 1.0; m[9][9] = 1.0; // add some more entries in random order m[7][3] = 1.0; m[6][0] = 1.0; m[3][8] = 1.0; } void testImplicitBuild() { ScalarMatrix m(10,10,3,0.1,ScalarMatrix::implicit); buildMatrix(m); ScalarMatrix::CompressionStatistics stats = m.compress(); assert(Dune::FloatCmp::eq(stats.avg,33./10.)); assert(stats.maximum == 4); assert(stats.overflow_total == 4); setMatrix(m); ScalarMatrix m1(m); } void testImplicitBuildWithInsufficientOverflow() { try { ScalarMatrix m(10,10,1,0,ScalarMatrix::implicit); // add diagonal entries + completely fill the first row with entries // with the current base buffer of 4 * avg, that should be enough to make // compress fail. for (int i = 0; i < 10; ++i) { m.entry(i,i) = 1.0; m.entry(0,i) = 1.0; } m.compress(); assert(false && "compress() should have thrown an exception"); } catch (Dune::ImplicitModeOverflowExhausted& e) { // test passed } } void testSetterInterface() { ScalarMatrix m; m.setBuildMode(ScalarMatrix::implicit); m.setImplicitBuildModeParameters(3,0.1); m.setSize(10,10); buildMatrix(m); ScalarMatrix::CompressionStatistics stats = m.compress(); assert(Dune::FloatCmp::eq(stats.avg,33.0/10.0)); assert(stats.maximum == 4); assert(stats.overflow_total == 4); } void testDoubleSetSize() { ScalarMatrix m; m.setBuildMode(ScalarMatrix::implicit); m.setImplicitBuildModeParameters(3,0.1); m.setSize(14,14); m.setSize(10,10); buildMatrix(m); ScalarMatrix::CompressionStatistics stats = m.compress(); assert(Dune::FloatCmp::eq(stats.avg,33.0/10.0)); assert(stats.maximum == 4); assert(stats.overflow_total == 4); } int testInvalidBuildModeConstructorCall() { try { ScalarMatrix m(10,10,1,-1.0,ScalarMatrix::random); std::cerr<< "ERROR: Constructor should have thrown an exception!"<(m.entry(0,3)),0.0)) ret++; if(!Dune::FloatCmp::eq(static_cast(m.entry(7,6)),0.0)) ++ret; buildMatrix(m); if(!Dune::FloatCmp::eq(static_cast(m.entry(0,3)),1.0)) ++ret; if(!Dune::FloatCmp::eq(static_cast(m.entry(7,6)),1.0)) ++ret; m.entry(4,4) += 3.0; if(!Dune::FloatCmp::eq(static_cast(m.entry(4,4)),4.0)) ++ret; m.compress(); if(!Dune::FloatCmp::eq(static_cast(m[0][3]),1.0)) ++ret; if(!Dune::FloatCmp::eq(static_cast(m[7][6]),1.0)) ++ret; if(!Dune::FloatCmp::eq(static_cast(m[4][4]),4.0)) ++ret; if(ret) std::cerr<<"ERROR: Entries are not consistent"<(m)[3][3]; std::cerr<<"ERROR: operator[]() should have thrown an exception!"< b(m); setMatrix(b); m.compress(); setMatrix(m); } void testImplicitMatrixBuilderExtendedConstructor() { ScalarMatrix m; Dune::ImplicitMatrixBuilder b(m,10,10,3,0.1); setMatrix(b); m.compress(); setMatrix(m); } int main() { int ret=0; try{ testImplicitBuild(); testImplicitBuildWithInsufficientOverflow(); testSetterInterface(); testDoubleSetSize(); ret+=testInvalidBuildModeConstructorCall(); ret+=testNegativeOverflowConstructorCall(); ret+=testInvalidSetImplicitBuildModeParameters(); ret+=testSetImplicitBuildModeParametersAfterSetSize(); ret+=testSetSizeWithNonzeroes(); testCopyConstructionAndAssignment(); ret+=testInvalidCopyConstruction(); ret+=testInvalidCopyAssignment(); ret+=testEntryConsistency(); ret+=testEntryAfterCompress(); ret+=testBracketOperatorBeforeCompress(); ret+=testConstBracketOperatorBeforeCompress(); testImplicitMatrixBuilder(); testImplicitMatrixBuilderExtendedConstructor(); }catch(Dune::Exception& e) { std::cerr << e < #include #include #include template void checkNormNANVector(V const &v, int line) { if (!std::isnan(v.infinity_norm())) { std::cerr << "error: norm not NaN: infinity_norm() on line " << line << " (type: " << Dune::className(v[0]) << ")" << std::endl; std::exit(-1); } } template void checkNormNANMatrix(M const &v, int line) { if (!std::isnan(v.frobenius_norm())) { std::cerr << "error: norm not NaN: frobenius_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } if (!std::isnan(v.infinity_norm())) { std::cerr << "error: norm not NaN: infinity_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } } template std::shared_ptr>> genPattern() { using LocalMatrix = Dune::FieldMatrix; using GlobalMatrix = Dune::BCRSMatrix; // Build a 3x3 matrix with sparsity pattern // // +-+ // --- // +-+ auto m = std::make_shared(3, 3, GlobalMatrix::random); m->setrowsize(0, 2); m->setrowsize(1, 0); m->setrowsize(2, 2); m->endrowsizes(); m->addindex(0, 0); m->addindex(0, 2); m->addindex(2, 0); m->addindex(2, 2); m->endindices(); return m; } // Make sure that matrices with NaN entries have norm NaN. // See also bug flyspray/FS#1147 template void test_nan(T const &mynan) { T n(0); { auto m = genPattern(); (*m)[0][0] = {{n, n}, {n, mynan}}; (*m)[0][2] = n; (*m)[2][0] = n; (*m)[2][2] = n; checkNormNANVector((*m)[0], __LINE__); checkNormNANMatrix(*m, __LINE__); } { auto m = genPattern(); (*m)[0][0] = n; (*m)[0][2] = {{n, n}, {n, mynan}};; (*m)[2][0] = n; (*m)[2][2] = n; checkNormNANVector((*m)[0], __LINE__); checkNormNANMatrix(*m, __LINE__); } { auto m = genPattern(); (*m)[0][0] = n; (*m)[0][2] = n; (*m)[2][0] = {{n, n}, {n, mynan}};; (*m)[2][2] = n; checkNormNANVector((*m)[2], __LINE__); checkNormNANMatrix(*m, __LINE__); } } int main() { { double nan = std::nan(""); test_nan(nan); } { std::complex nan(std::nan(""), 17); test_nan(nan); } } dune-istl-2.5.1/dune/istl/test/bvectortest.cc000066400000000000000000000124131313314427100211630ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include template void assign(Dune::FieldVector& b, const T& i) { for(int j=0; j < BS; j++) b[j] = i; } template > int testVector() { typedef Dune::FieldVector VectorBlock; typedef typename A::template rebind::other Alloc; typedef Dune::BlockVector Vector; // empty vector Vector v, w, v1(20), v2(20,100); #ifdef FAIL Vector v3(20,100.0); #endif v.reserve(100); assert(100==v.capacity()); assert(20==v1.capacity()); assert(100==v2.capacity()); assert(20==v1.N()); assert(20==v2.N()); v.resize(25); assert(25==v.N()); for(typename Vector::size_type i=0; i < v.N(); ++i) v[i] = i; for(typename Vector::size_type i=0; i < v2.N(); ++i) v2[i] = i*10; w = v; testHomogeneousRandomAccessContainer(v); Dune::testConstructibility(); testNorms(v); testVectorSpaceOperations(v); testScalarProduct(v); assert(w.N()==v.N()); assert(w.capacity()==v.capacity()); for(typename Vector::size_type i=0; i < v.N(); ++i) assert(v[i] == w[i]); Vector z(w); assert(w.N()==z.N()); assert(w.capacity()==z.capacity()); for(typename Vector::size_type i=0; i < w.N(); ++i) assert(z[i] == w[i]); v.reserve(150); assert(150==v.capacity()); assert(25==v.N()); VectorBlock b; // check the entries for(typename Vector::size_type i=0; i < v.N(); ++i) { assign(b, (typename VectorBlock::field_type)i); assert(v[i] == b); } // Try to shrink the vector v.reserve(v.N()); assert(v.N()==v.capacity()); // check the entries for(typename Vector::size_type i=0; i < v.N(); ++i) { assign(b,(typename VectorBlock::field_type)i); assert(v[i] == b); } return 0; } void testCapacity() { typedef Dune::FieldVector SmallVector; typedef Dune::BlockVector > ThreeLevelVector; ThreeLevelVector vec; vec.reserve(10); vec.resize(10); for(int i=0; i<10; ++i) vec[i]=Dune::BlockVector(10); ThreeLevelVector vec1=vec; vec.reserve(20, true); vec.reserve(10, true); vec.reserve(5, false); vec.reserve(20, false); vec.reserve(0, true); vec1.reserve(0, false); } template void checkNormNAN(V const &v, int line) { if (!std::isnan(v.one_norm())) { std::cerr << "error: norm not NaN: one_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } if (!std::isnan(v.two_norm())) { std::cerr << "error: norm not NaN: two_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } if (!std::isnan(v.infinity_norm())) { std::cerr << "error: norm not NaN: infinity_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } } // Make sure that vectors with NaN entries have norm NaN. // See also bug flyspray/FS#1147 template void test_nan(T const &mynan) { using FV = Dune::FieldVector; using V = Dune::BlockVector; T n(0); { V v = { { mynan, n }, { n, n } }; checkNormNAN(v, __LINE__); } { V v = { { n, mynan }, { n, n } }; checkNormNAN(v, __LINE__); } { V v = { { n, n }, { mynan, n } }; checkNormNAN(v, __LINE__); } { V v = { { n, n }, { n, mynan } }; checkNormNAN(v, __LINE__); } { V v = { { mynan, mynan }, { mynan, mynan } }; checkNormNAN(v, __LINE__); } } int main() { typedef std::complex value_type; //typedef double value_type; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; Vector v; v=0; Dune::BlockVector,1> > v1; v1=0; // Test a BlockVector of BlockVectors typedef Dune::BlockVector VectorOfVector; VectorOfVector vv = {{1.0, 2.0}, {3.0, 4.0, 5.0}, {6.0}}; testHomogeneousRandomAccessContainer(vv); Dune::testConstructibility(); testNorms(vv); testVectorSpaceOperations(vv); testScalarProduct(vv); // Test construction from initializer_list Vector fromInitializerList = {0,1,2}; assert(fromInitializerList.size() == 3); assert(fromInitializerList[0] == value_type(0)); assert(fromInitializerList[1] == value_type(1)); assert(fromInitializerList[2] == value_type(2)); { double nan = std::nan(""); test_nan(nan); } { std::complex nan( std::nan(""), 17 ); test_nan(nan); } int ret = 0; ret += testVector<1>(); // ret += testVector<1, Dune::PoolAllocator >(); ret += testVector<1, Dune::DebugAllocator >(); ret += testVector<3>(); // ret += testVector<3, Dune::PoolAllocator >(); ret += testVector<3, Dune::DebugAllocator >(); testCapacity(); return ret; } dune-istl-2.5.1/dune/istl/test/complexdata.hh000066400000000000000000000366041313314427100211420ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** * \author: Marian Piatkowski, Steffen Müthing * \file * \brief Test data for complexmatrixtest. */ void assemblecomplexmatrix(Dune::FieldMatrix,10,10>& complexmatrix) { complexmatrix[0][0] = {-9.673988567513409e-01,-5.142264587405261e-01}; complexmatrix[0][1] = {5.348995842667770e-02,5.398276725503746e-01}; complexmatrix[0][2] = {-5.234400916488097e-01,9.412682633573508e-01}; complexmatrix[0][3] = {3.757227805330059e-01,-6.680516673568877e-01}; complexmatrix[0][4] = {-3.501868668711683e-02,-5.683500820623478e-01}; complexmatrix[0][5] = {-7.936576231353253e-01,-7.478493218067332e-01}; complexmatrix[0][6] = {-8.509403988024874e-01,9.002080633771643e-01}; complexmatrix[0][7] = {1.466372567911807e-01,5.111616707924576e-01}; complexmatrix[0][8] = {-2.818092625969133e-01,1.049700449709641e-01}; complexmatrix[0][9] = {9.588682586135659e-01,4.876224144769936e-01}; complexmatrix[1][0] = {-7.255368464279626e-01,6.083535084539808e-01}; complexmatrix[1][1] = {-1.995427558196442e-01,7.830589040103644e-01}; complexmatrix[1][2] = {8.044161469696165e-01,7.018395735425127e-01}; complexmatrix[1][3] = {-1.197909447922330e-01,7.601504725218520e-01}; complexmatrix[1][4] = {9.005047482906396e-01,8.402565074340704e-01}; complexmatrix[1][5] = {-9.111866824846659e-03,5.209504568581238e-01}; complexmatrix[1][6] = {-8.949414751934547e-01,4.312675960507550e-02}; complexmatrix[1][7] = {-8.961223624162946e-01,-6.843857428451934e-01}; complexmatrix[1][8] = {1.588599882828352e-01,-9.484830829074997e-02}; complexmatrix[1][9] = {8.067326805585682e-01,9.671914763595870e-01}; complexmatrix[2][0] = {-6.866418214918308e-01,-1.981112115076330e-01}; complexmatrix[2][1] = {-4.333705079897170e-01,-2.950833054702185e-01}; complexmatrix[2][2] = {-4.666685012479632e-01,7.952068144433233e-02}; complexmatrix[2][3] = {6.584021866593519e-01,-3.393257406257678e-01}; complexmatrix[2][4] = {-7.046799704919942e-01,7.621243390078305e-01}; complexmatrix[2][5] = {9.695033300525990e-01,8.700079731037877e-01}; complexmatrix[2][6] = {-6.475786872429674e-01,-5.198752551897780e-01}; complexmatrix[2][7] = {9.999871421605289e-01,-5.913427786861281e-01}; complexmatrix[2][8] = {3.747748692402499e-01,-8.007198729555680e-01}; complexmatrix[2][9] = {3.337606691446904e-01,-5.482961891909555e-03}; complexmatrix[3][0] = {-7.404191064370885e-01,-7.823823959484615e-01}; complexmatrix[3][1] = {6.154490400177655e-01,8.380529479300849e-01}; complexmatrix[3][2] = {-2.495860472552414e-01,5.204974727334908e-01}; complexmatrix[3][3] = {-5.420636579124554e-01,7.867448291679586e-01}; complexmatrix[3][4] = {2.821611926342180e-01,-1.360931634605365e-01}; complexmatrix[3][5] = {3.688900337409646e-01,-2.336233375750590e-01}; complexmatrix[3][6] = {5.955961037406681e-01,4.653088233737781e-01}; complexmatrix[3][7] = {7.799112888890838e-01,-7.490630483948919e-01}; complexmatrix[3][8] = {6.161597606801239e-02,5.145876647506784e-01}; complexmatrix[3][9] = {-6.720639931373595e-01,6.600236676912865e-01}; complexmatrix[4][0] = {9.978490360071179e-01,-5.634861893781862e-01}; complexmatrix[4][1] = {-8.604894475361748e-01,8.986541507293722e-01}; complexmatrix[4][2] = {2.507072828014878e-02,3.354475215708126e-01}; complexmatrix[4][3] = {-2.992796428963913e-01,3.733398166360984e-01}; complexmatrix[4][4] = {2.391929678801414e-01,-4.378811751668720e-01}; complexmatrix[4][5] = {4.995417648458582e-01,-2.626729166427035e-01}; complexmatrix[4][6] = {3.131273059701210e-01,9.348102770442190e-01}; complexmatrix[4][7] = {9.955979986095791e-01,-8.918848446998209e-01}; complexmatrix[4][8] = {-3.914097004530065e-01,9.844569228517157e-01}; complexmatrix[4][9] = {7.778975003296031e-01,-8.460106383292054e-01}; complexmatrix[5][0] = {2.586478880879683e-02,6.782244693852144e-01}; complexmatrix[5][1] = {5.199070044420218e-02,-8.278883042875157e-01}; complexmatrix[5][2] = {6.321286832132045e-02,-9.214393132931736e-01}; complexmatrix[5][3] = {9.129365058210384e-01,1.772802663861217e-01}; complexmatrix[5][4] = {5.720041960347464e-01,-3.850842525181752e-01}; complexmatrix[5][5] = {-4.116792759912458e-01,-5.354769227725812e-01}; complexmatrix[5][6] = {2.789166910941325e-01,5.194696837661181e-01}; complexmatrix[5][7] = {7.410797298611513e-01,-8.553424011242308e-01}; complexmatrix[5][8] = {1.539422251069649e-01,7.552275563381741e-01}; complexmatrix[5][9] = {2.994139722080036e-01,-5.039117631986326e-01}; complexmatrix[6][0] = {2.252796651913225e-01,-4.079367646053139e-01}; complexmatrix[6][1] = {-6.155723080111539e-01,3.264538540162396e-01}; complexmatrix[6][2] = {-1.247248068101354e-01,8.636701125016764e-01}; complexmatrix[6][3] = {3.146080790621266e-01,7.173526518593323e-01}; complexmatrix[6][4] = {-1.059328415924371e-01,-5.477867496888091e-01}; complexmatrix[6][5] = {1.689770012949485e-01,-5.111745286319287e-01}; complexmatrix[6][6] = {-8.130390456938367e-01,-7.301951766620367e-01}; complexmatrix[6][7] = {-9.916767822539791e-01,8.461382546676968e-01}; complexmatrix[6][8] = {4.956185927128507e-01,2.578198626906703e-01}; complexmatrix[6][9] = {2.589594066417586e-01,-5.417260404404840e-01}; complexmatrix[7][0] = {2.751045354060384e-01,4.857438013356852e-02}; complexmatrix[7][1] = {7.804652050977876e-01,-3.022141295029848e-01}; complexmatrix[7][2] = {8.616195907171906e-01,4.419046861314702e-01}; complexmatrix[7][3] = {-1.208801610026882e-01,8.479395778141634e-01}; complexmatrix[7][4] = {-6.249337809276458e-01,-4.475306558644077e-01}; complexmatrix[7][5] = {-6.952204162698334e-01,4.642970317342769e-01}; complexmatrix[7][6] = {4.042013969291935e-02,-8.435357165725602e-01}; complexmatrix[7][7] = {1.877843584808447e-01,-6.392554685656240e-01}; complexmatrix[7][8] = {-9.291581865070193e-01,4.956057339420570e-01}; complexmatrix[7][9] = {4.012399294419400e-01,-3.662657250493140e-01}; complexmatrix[8][0] = {-1.283402601854600e-02,9.455500477671390e-01}; complexmatrix[8][1] = {-8.716573584227159e-01,-9.599539022706234e-01}; complexmatrix[8][2] = {-4.314131938998649e-01,4.770686298036335e-01}; complexmatrix[8][3] = {-2.031266666963355e-01,6.295337926733930e-01}; complexmatrix[8][4] = {1.128875106167455e-01,-1.669974388401012e-01}; complexmatrix[8][5] = {-7.490501905554208e-01,5.869407763643846e-01}; complexmatrix[8][6] = {-8.601872044895716e-01,-5.906898274974384e-01}; complexmatrix[8][7] = {-6.737370014534039e-01,-2.166195387098098e-01}; complexmatrix[8][8] = {6.664770840045424e-01,8.507531023820645e-01}; complexmatrix[8][9] = {-3.424459133960520e-01,-5.371440954213702e-01}; complexmatrix[9][0] = {-4.149664311739459e-01,5.427153955878297e-01}; complexmatrix[9][1] = {-8.459652545144625e-02,-8.738083233469205e-01}; complexmatrix[9][2] = {2.799576331302327e-01,-2.919026405047171e-01}; complexmatrix[9][3] = {3.684370505476542e-01,8.219440615838134e-01}; complexmatrix[9][4] = {-6.607858276277714e-01,8.136078677203542e-01}; complexmatrix[9][5] = {-6.717961326575820e-01,4.901427782560432e-01}; complexmatrix[9][6] = {-7.715905321629679e-02,6.393545603562867e-01}; complexmatrix[9][7] = {8.260533548081541e-01,6.393903054480397e-01}; complexmatrix[9][8] = {7.465426855471649e-01,6.620750816827989e-01}; complexmatrix[9][9] = {-8.516780602986357e-01,2.661443870822640e-01}; } void assemblecomplexsol(Dune::FieldVector,10>& complexsol) { complexsol[0] = {6.803754343094190e-01,-2.112341463618139e-01}; complexsol[1] = {5.661984475172117e-01,5.968800669521466e-01}; complexsol[2] = {8.232947158735686e-01,-6.048972614132321e-01}; complexsol[3] = {-3.295544885702220e-01,5.364591896238080e-01}; complexsol[4] = {-4.444505783936245e-01,1.079399115908610e-01}; complexsol[5] = {-4.520589627567950e-02,2.577418495238488e-01}; complexsol[6] = {-2.704310544163133e-01,2.680182039123102e-02}; complexsol[7] = {9.044594503494257e-01,8.323901360074013e-01}; complexsol[8] = {2.714234559198019e-01,4.345938588653662e-01}; complexsol[9] = {-7.167948892883933e-01,2.139377525141173e-01}; } void assemblehermitianmatrix(Dune::FieldMatrix,10,10>& hermitianmatrix) { hermitianmatrix[0][0] = {7.197903669889858e+00,0.000000000000000e+00}; hermitianmatrix[0][1] = {-3.796134060556492e+00,3.378779614117114e-01}; hermitianmatrix[0][2] = {-7.792613368410124e-01,-2.029495926144751e+00}; hermitianmatrix[0][3] = {2.424358093154745e-01,-5.210063258489648e-01}; hermitianmatrix[0][4] = {1.215783110733711e+00,-2.010080764899121e+00}; hermitianmatrix[0][5] = {2.007393091095153e+00,1.261146874742959e+00}; hermitianmatrix[0][6] = {8.400538096522401e-01,3.556657457954513e-01}; hermitianmatrix[0][7] = {-5.366239926352748e-01,1.065157738997571e+00}; hermitianmatrix[0][8] = {-3.100062250221378e-01,-1.853912328045908e-01}; hermitianmatrix[0][9] = {-1.369506171548954e-01,-2.191920974481131e+00}; hermitianmatrix[1][0] = {-3.796134060556492e+00,-3.378779614117114e-01}; hermitianmatrix[1][1] = {8.177347822939913e+00,0.000000000000000e+00}; hermitianmatrix[1][2] = {3.423679740643685e+00,-8.327540053361566e-01}; hermitianmatrix[1][3] = {-5.738847217530769e-01,1.285746142919267e+00}; hermitianmatrix[1][4] = {-1.000317599806714e+00,-1.686041686108639e+00}; hermitianmatrix[1][5] = {-2.161820121002458e+00,-2.291203709707303e+00}; hermitianmatrix[1][6] = {3.311679204788015e+00,-1.703242106082667e-01}; hermitianmatrix[1][7] = {1.566275624302893e-03,2.355130514323052e-01}; hermitianmatrix[1][8] = {-2.052276321346663e+00,7.263179682041794e-01}; hermitianmatrix[1][9] = {6.517140901693339e-01,-5.382604520819103e-01}; hermitianmatrix[2][0] = {-7.792613368410124e-01,2.029495926144751e+00}; hermitianmatrix[2][1] = {3.423679740643685e+00,8.327540053361566e-01}; hermitianmatrix[2][2] = {6.099598957224000e+00,0.000000000000000e+00}; hermitianmatrix[2][3] = {9.363518872122267e-01,2.431336243539179e+00}; hermitianmatrix[2][4] = {-4.512089463662358e-01,4.768094168245564e-01}; hermitianmatrix[2][5] = {-7.197164862085857e-01,1.030153878182087e+00}; hermitianmatrix[2][6] = {-1.681901621557627e-01,1.939031624543862e+00}; hermitianmatrix[2][7] = {-3.685384612851221e-01,8.749011852426078e-01}; hermitianmatrix[2][8] = {-3.309499218189973e-01,6.471561610525622e-01}; hermitianmatrix[2][9] = {1.117932973970579e+00,-1.250965917379453e+00}; hermitianmatrix[3][0] = {2.424358093154745e-01,5.210063258489648e-01}; hermitianmatrix[3][1] = {-5.738847217530769e-01,-1.285746142919267e+00}; hermitianmatrix[3][2] = {9.363518872122267e-01,-2.431336243539179e+00}; hermitianmatrix[3][3] = {6.331005113267439e+00,0.000000000000000e+00}; hermitianmatrix[3][4] = {-2.993398678694307e-01,-2.546975173854160e-02}; hermitianmatrix[3][5] = {6.807164931619119e-01,6.842214609887675e-01}; hermitianmatrix[3][6] = {-1.585628344826376e+00,5.718554836282774e-01}; hermitianmatrix[3][7] = {-3.977057407423769e-01,6.989648283164356e-01}; hermitianmatrix[3][8] = {3.474749763656946e+00,-9.804983433454130e-01}; hermitianmatrix[3][9] = {3.837829404449155e-01,2.955801965170571e-01}; hermitianmatrix[4][0] = {1.215783110733711e+00,2.010080764899121e+00}; hermitianmatrix[4][1] = {-1.000317599806714e+00,1.686041686108639e+00}; hermitianmatrix[4][2] = {-4.512089463662358e-01,-4.768094168245564e-01}; hermitianmatrix[4][3] = {-2.993398678694307e-01,2.546975173854160e-02}; hermitianmatrix[4][4] = {5.782508877722716e+00,0.000000000000000e+00}; hermitianmatrix[4][5] = {2.352248681811305e+00,-1.915408924791806e+00}; hermitianmatrix[4][6] = {-5.050140077330580e-02,1.720340837323670e+00}; hermitianmatrix[4][7] = {-1.384292690960728e+00,-1.610641396488195e+00}; hermitianmatrix[4][8] = {-1.497233786162651e+00,-7.140793387576246e-01}; hermitianmatrix[4][9] = {2.644285604378166e+00,1.537531467522439e+00}; hermitianmatrix[5][0] = {2.007393091095153e+00,-1.261146874742959e+00}; hermitianmatrix[5][1] = {-2.161820121002458e+00,2.291203709707303e+00}; hermitianmatrix[5][2] = {-7.197164862085857e-01,-1.030153878182087e+00}; hermitianmatrix[5][3] = {6.807164931619119e-01,-6.842214609887675e-01}; hermitianmatrix[5][4] = {2.352248681811305e+00,1.915408924791806e+00}; hermitianmatrix[5][5] = {6.708789570096198e+00,0.000000000000000e+00}; hermitianmatrix[5][6] = {-9.395295739035217e-01,5.542147306633838e-01}; hermitianmatrix[5][7] = {6.376861664858158e-02,-1.078862327434092e+00}; hermitianmatrix[5][8] = {-6.072363218363827e-01,-2.568973945662960e+00}; hermitianmatrix[5][9] = {5.604196275925352e-01,7.924409894223814e-01}; hermitianmatrix[6][0] = {8.400538096522401e-01,-3.556657457954513e-01}; hermitianmatrix[6][1] = {3.311679204788015e+00,1.703242106082667e-01}; hermitianmatrix[6][2] = {-1.681901621557627e-01,-1.939031624543862e+00}; hermitianmatrix[6][3] = {-1.585628344826376e+00,-5.718554836282774e-01}; hermitianmatrix[6][4] = {-5.050140077330580e-02,-1.720340837323670e+00}; hermitianmatrix[6][5] = {-9.395295739035217e-01,-5.542147306633838e-01}; hermitianmatrix[6][6] = {8.328660025951734e+00,0.000000000000000e+00}; hermitianmatrix[6][7] = {1.911840958553550e+00,-3.724184659980277e+00}; hermitianmatrix[6][8] = {1.137677844325891e-01,5.604277205039606e-01}; hermitianmatrix[6][9] = {-7.313018555728619e-01,-8.468371873228848e-01}; hermitianmatrix[7][0] = {-5.366239926352748e-01,-1.065157738997571e+00}; hermitianmatrix[7][1] = {1.566275624302893e-03,-2.355130514323052e-01}; hermitianmatrix[7][2] = {-3.685384612851221e-01,-8.749011852426078e-01}; hermitianmatrix[7][3] = {-3.977057407423769e-01,-6.989648283164356e-01}; hermitianmatrix[7][4] = {-1.384292690960728e+00,1.610641396488195e+00}; hermitianmatrix[7][5] = {6.376861664858158e-02,1.078862327434092e+00}; hermitianmatrix[7][6] = {1.911840958553550e+00,3.724184659980277e+00}; hermitianmatrix[7][7] = {1.087602223303330e+01,0.000000000000000e+00}; hermitianmatrix[7][8] = {-1.711803279506748e+00,8.772768099603478e-03}; hermitianmatrix[7][9] = {-8.661271304690032e-02,7.620932443208487e-01}; hermitianmatrix[8][0] = {-3.100062250221378e-01,1.853912328045908e-01}; hermitianmatrix[8][1] = {-2.052276321346663e+00,-7.263179682041794e-01}; hermitianmatrix[8][2] = {-3.309499218189973e-01,-6.471561610525622e-01}; hermitianmatrix[8][3] = {3.474749763656946e+00,9.804983433454130e-01}; hermitianmatrix[8][4] = {-1.497233786162651e+00,7.140793387576246e-01}; hermitianmatrix[8][5] = {-6.072363218363827e-01,2.568973945662960e+00}; hermitianmatrix[8][6] = {1.137677844325891e-01,-5.604277205039606e-01}; hermitianmatrix[8][7] = {-1.711803279506748e+00,-8.772768099603478e-03}; hermitianmatrix[8][8] = {6.476008026107579e+00,0.000000000000000e+00}; hermitianmatrix[8][9] = {-2.937196022651017e+00,4.075385476181479e-01}; hermitianmatrix[9][0] = {-1.369506171548954e-01,2.191920974481131e+00}; hermitianmatrix[9][1] = {6.517140901693339e-01,5.382604520819103e-01}; hermitianmatrix[9][2] = {1.117932973970579e+00,1.250965917379453e+00}; hermitianmatrix[9][3] = {3.837829404449155e-01,-2.955801965170571e-01}; hermitianmatrix[9][4] = {2.644285604378166e+00,-1.537531467522439e+00}; hermitianmatrix[9][5] = {5.604196275925352e-01,-7.924409894223814e-01}; hermitianmatrix[9][6] = {-7.313018555728619e-01,8.468371873228848e-01}; hermitianmatrix[9][7] = {-8.661271304690032e-02,-7.620932443208487e-01}; hermitianmatrix[9][8] = {-2.937196022651017e+00,-4.075385476181479e-01}; hermitianmatrix[9][9] = {7.264295214773998e+00,0.000000000000000e+00}; } dune-istl-2.5.1/dune/istl/test/complexmatrixtest.cc000066400000000000000000000126131313314427100224150ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** * \author: Marian Piatkowski, Steffen Müthing * \file * \brief Test MINRES and GMRes for complex matrices and complex rhs. */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "complexdata.hh" typedef std::complex FIELD_TYPE; int main(int argc, char** argv) { try { std::size_t N = 3; const int maxIter = int(N*N*N*N); const double reduction = 1e-16; std::cout << "============================================" << '\n' << "starting solver tests with complex matrices and complex rhs... " << std::endl << std::endl; std::cout << "============================================" << '\n' << "solving system with Hilbert matrix of size 10 times imaginary unit... " << std::endl << std::endl; Dune::FieldMatrix,10,10> hilbertmatrix; for(int i=0; i<10; i++) { for(int j=0; j<10; j++) { std::complex temp(0.0,1./(i+j+1)); hilbertmatrix[i][j] = temp; } } Dune::FieldVector,10> hilbertsol(1.0); Dune::FieldVector,10> hilbertiter(0.0); Dune::MatrixAdapter,10,10>,Dune::FieldVector,10>,Dune::FieldVector,10> > hilbertadapter(hilbertmatrix); Dune::FieldVector,10> hilbertrhs(0.0); hilbertadapter.apply(hilbertsol,hilbertrhs); Dune::Richardson,10>,Dune::FieldVector,10> > noprec(1.0); Dune::RestartedGMResSolver,10> > realgmrestest(hilbertadapter,noprec,reduction,maxIter,maxIter,2); Dune::InverseOperatorResult stat; realgmrestest.apply(hilbertiter,hilbertrhs,stat); std::cout << hilbertiter << std::endl; // error of solution hilbertiter -= hilbertsol; std::cout << "error of solution with GMRes:" << std::endl; std::cout << hilbertiter.two_norm() << std::endl; std::cout << "============================================" << '\n' << "solving system with complex matrix of size 10" << '\n' << "randomly generated with the Eigen library... " << std::endl << std::endl; Dune::FieldMatrix,10,10> complexmatrix(0.0), hermitianmatrix(0.0); Dune::FieldVector,10> complexsol, complexrhs(0.0), complexiter(0.0); // assemble randomly generated matrices from Eigen assemblecomplexmatrix(complexmatrix); assemblecomplexsol(complexsol); assemblehermitianmatrix(hermitianmatrix); Dune::MatrixAdapter,10,10>,Dune::FieldVector,10>,Dune::FieldVector,10> > complexadapter(complexmatrix), hermitianadapter(hermitianmatrix); Dune::SeqJac,10,10>,Dune::FieldVector,10>,Dune::FieldVector,10>,0> complexjacprec(complexmatrix,1,1.0); Dune::Richardson,10>,Dune::FieldVector,10> > complexnoprec(1.0); Dune::RestartedGMResSolver,10> > complexgmrestest(complexadapter,complexnoprec,1e-12,maxIter,maxIter*maxIter,2); complexadapter.apply(complexsol,complexrhs); complexgmrestest.apply(complexiter,complexrhs,stat); std::cout << complexiter << std::endl; // error of solution complexiter -= complexsol; std::cout << "error of solution with GMRes: " << complexiter.two_norm() << std::endl; std::cout << "============================================" << '\n' << "solving system with hermitian matrix of size 10" << '\n' << "randomly generated with the Eigen library... " << std::endl << std::endl; Dune::RestartedGMResSolver,10> > hermitiangmrestest(hermitianadapter,complexnoprec,1e-12,maxIter,maxIter*maxIter,2); Dune::MINRESSolver,10> > complexminrestest(hermitianadapter,complexnoprec,1e-12,maxIter,2); complexiter = 0.0; hermitianadapter.apply(complexsol,complexrhs); hermitiangmrestest.apply(complexiter,complexrhs,stat); std::cout << complexiter << std::endl; // error of solution complexiter -= complexsol; std::cout << "error of solution with GMRes: " << complexiter.two_norm() << std::endl; complexiter = 0.0; hermitianadapter.apply(complexsol,complexrhs); complexminrestest.apply(complexiter,complexrhs,stat); std::cout << complexiter << std::endl; // error of solution complexiter-= complexsol; std::cout << "error of solution with MinRes: " << complexiter.two_norm() << std::endl; return 0; } catch (Dune::Exception& e) { std::cerr << "DUNE reported an exception: " << e << std::endl; return 1; } catch (std::exception& e) { std::cerr << "C++ reported an exception: " << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Unknown exception encountered!" << std::endl; return 3; } } dune-istl-2.5.1/dune/istl/test/complexrhstest.cc000066400000000000000000000210151313314427100217010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** * \author: Matthias Wohlmuth * \file * \brief Test different solvers and preconditioners for * \f$A*x = b\f$ with \f$A\f$ being a \f$N^2 \times N^2\f$ * Laplacian and \f$b\f$ a complex valued rhs. */ #include #include #include #include #include #include #include "laplacian.hh" #if HAVE_SUPERLU #include static_assert(SUPERLU_NTYPE == 3, "If SuperLU is selected for complex rhs test, then SUPERLU_NTYPE must be set to 3 (std::complex)!"); #endif typedef std::complex FIELD_TYPE; /** * \brief Test different solvers and preconditioners for * \f$A*x = b\f$ with \f$A\f$ being a \f$N^2 \times N^2\f$ * Laplacian and \f$b\f$ a complex valued rhs. * * The rhs and reference solutions were computed using the following matlab code: * \code N=3; A = full(gallery('poisson',N)); % create poisson matrix % find a solution consiting of complex integers indVec = (0:(N*N-1))', iVec = complex(0,1).^indVec + indVec, x0 = iVec .* indVec, % compute corresponding rhs b = A * x0, % solve system using different solvers xcg = pcg(A,b), x = A \ b, xgmres = gmres(A,b) * \endcode */ template class SolverTest { public: SolverTest(Operator & op, Vector & rhs, Vector & x0, double maxError = 1e-10) : m_op(op), m_x(rhs), m_x0(x0), m_b(rhs), m_rhs(rhs), m_maxError(maxError), m_numTests(0), m_numFailures(0) { std::cout << "SolverTest uses rhs: " << std::endl << m_rhs << std::endl << "and expects the solultion: " << m_x0 << std::endl << std::endl; } template bool operator() (Solver & solver) { m_b = m_rhs; m_x = 0; solver.apply(m_x, m_b, m_res); std::cout << "Defect reduction is " << m_res.reduction << std::endl; std::cout << "Computed solution is: " << std::endl; std::cout << m_x << std::endl; m_b = m_x0; m_b -= m_x; const double errorNorm = m_b.two_norm(); std::cout << "Error = " << errorNorm << std::endl; ++m_numTests; if(errorNorm > m_maxError) { std::cout << "SolverTest did not converge!" << std::endl; ++m_numFailures; return false; } return true; } int getNumTests() const { return m_numTests; } int getNumFailures() const { return m_numFailures; } private: const Operator & m_op; Vector m_x, m_x0, m_b; const Vector m_rhs; double m_maxError; int m_numTests, m_numFailures; Dune::InverseOperatorResult m_res; }; int main(int argc, char** argv) { const int BS = 1; std::size_t N = 3; const int maxIter = int(N*N*N*N); const double reduction = 1e-16; if (argc > 1) N = atoi(argv[1]); std::cout<<"testing for N="< GradientSolver; GradientSolver solverGradient(fop,dummyPrec, reduction, maxIter, 1); std::cout << "GradientSolver with identity preconditioner converged: " << solverTest(solverGradient) << std::endl << std::endl; typedef Dune::CGSolver CG; CG solverCG(fop,dummyPrec, reduction, maxIter, 1); std::cout << "CG with identity preconditioner converged: " << solverTest(solverCG) << std::endl << std::endl; typedef Dune::BiCGSTABSolver BiCG; BiCG solverBiCG(fop,dummyPrec, reduction, maxIter, 1); std::cout << "BiCGStab with identity preconditioner converged: " << solverTest(solverBiCG) << std::endl << std::endl; typedef Dune::LoopSolver JacobiSolver; JacobiSolver solverJacobi1(fop,jacobiPrec1,reduction,maxIter,1); std::cout << "LoopSolver with a single Jacobi iteration as preconditioner converged: " << solverTest(solverJacobi1) << std::endl << std::endl; typedef Dune::LoopSolver JacobiSolver; JacobiSolver solverJacobi2(fop,jacobiPrec2,reduction,maxIter,1); std::cout << "LoopSolver with multiple Jacobi iteration as preconditioner converged: " << solverTest(solverJacobi2) << std::endl << std::endl; typedef Dune::LoopSolver GaussSeidelSolver; GaussSeidelSolver solverGaussSeidel1(fop,gsPrec1,reduction,maxIter,1); std::cout << "LoopSolver with a single GaussSeidel iteration as preconditioner converged: " << solverTest(solverGaussSeidel1) << std::endl << std::endl; typedef Dune::LoopSolver GaussSeidelSolver; GaussSeidelSolver solverGaussSeidel2(fop,gsPrec2,reduction,maxIter,1); std::cout << "LoopSolver with multiple GaussSeidel iterations as preconditioner converged: " << solverTest(solverGaussSeidel2) << std::endl << std::endl; typedef Dune::LoopSolver SORSolver; SORSolver solverSOR1(fop,sorPrec1,reduction,maxIter,1); std::cout << "LoopSolver with a single SOR iteration as preconditioner converged: " << solverTest(solverSOR1) << std::endl << std::endl; typedef Dune::LoopSolver SORSolver; SORSolver solverSOR2(fop,sorPrec2,reduction,maxIter,1); std::cout << "LoopSolver with multiple SOR iterations as preconditioner converged: " << solverTest(solverSOR2) << std::endl << std::endl; typedef Dune::LoopSolver SSORSolver; SSORSolver solverSSOR1(fop,ssorPrec1,reduction,maxIter,1); std::cout << "LoopSolver with a single SSOR iteration as preconditioner converged: " << solverTest(solverSOR2) << std::endl << std::endl; typedef Dune::LoopSolver SSORSolver; SSORSolver solverSSOR2(fop,ssorPrec2,reduction,maxIter,1); std::cout << "LoopSolver with multiple SSOR iterations as preconditioner converged: " << solverTest(solverSSOR2) << std::endl << std::endl; typedef Dune::MINRESSolver MINRES; MINRES solverMINRES(fop,dummyPrec, reduction, maxIter, 1); std::cout << "MINRES with identity preconditioner converged: " << solverTest(solverMINRES) << std::endl << std::endl; typedef Dune::RestartedGMResSolver GMRES; GMRES solverGMRES(fop,dummyPrec, reduction, maxIter, maxIter*maxIter, 1); std::cout << "GMRES with identity preconditioner converged: " << solverTest(solverGMRES) << std::endl << std::endl; const int testCount = solverTest.getNumTests(); const int errorCount = solverTest.getNumFailures(); std::cout << "Tested " << testCount << " different solvers or preconditioners " << " for a laplacian with complex rhs. " << testCount - errorCount << " out of " << testCount << " solvers converged! " << std::endl << std::endl; return errorCount; } dune-istl-2.5.1/dune/istl/test/dotproducttest.cc000066400000000000000000000123571313314427100217150ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include // scalar ordering doesn't work for complex numbers template int DotProductTest(const size_t numBlocks,const size_t blockSizeOrCapacity) { typedef typename RealBlockVector::field_type rt; typedef typename ComplexBlockVector::field_type ct; const rt myEps((rt)1e-6); static_assert(std::is_same< typename Dune::FieldTraits::real_type, rt>::value, "DotProductTest requires real data type for first block vector!"); const bool secondBlockIsComplex = !std::is_same< typename Dune::FieldTraits::real_type, ct>::value; const ct complexSign = secondBlockIsComplex ? -1. : 1.; // avoid constructor ct(0.,1.) const ct I = secondBlockIsComplex ? std::sqrt(ct(-1.)) : ct(1.); // imaginary unit typedef typename RealBlockVector::size_type size_type; // empty vectors RealBlockVector one(numBlocks,blockSizeOrCapacity); ComplexBlockVector iVec(numBlocks,blockSizeOrCapacity); const size_type blockSize = one[0].size(); assert(numBlocks==one.N()); assert(numBlocks==iVec.N()); const size_type length = numBlocks * blockSize; // requires innter block size of VariableBlockVector to be 1! ct ctlength = ct(length); std::cout << __func__ << "\t \t ( " << Dune::className(one) << " and \n \t \t \t " << Dune::className(iVec) << " )" << std::endl << std::endl; // initialize vectors with data for(size_type i=0; i < numBlocks; ++i) { for(size_type j=0; j < blockSize; ++j) { one[i][j] = 1.; iVec[i][j] = I; } } ct result = ct(); // blockwise dot tests result = ct(); for(size_type i=0; i < numBlocks; ++i) { result += dot(one[i],one[i]) + one[i].dot(one[i]); } assert(std::abs(result-ct(2)*ctlength)<= myEps); result = ct(); for(size_type i=0; i < numBlocks; ++i) { result += dot(iVec[i],iVec[i])+ (iVec[i]).dot(iVec[i]); } assert(std::abs(result-ct(2)*ctlength)<= myEps); // blockwise dotT / operator * tests result = ct(); for(size_type i=0; i < numBlocks; ++i) { result += dotT(one[i],one[i]) + one[i]*one[i]; } assert(std::abs(result-ct(2)*ctlength)<= myEps); result = ct(); for(size_type i=0; i < numBlocks; ++i) { result += dotT(iVec[i],iVec[i]) + iVec[i]*iVec[i]; } assert(std::abs(result-complexSign*ct(2)*ctlength)<= myEps); // global operator * tests result = one*one + dotT(one,one); assert(std::abs(result-ct(2)*ctlength)<= myEps); result = iVec*iVec + dotT(iVec,iVec); assert(std::abs(result-complexSign*ct(2)*ctlength)<= myEps); // global operator dot(,) tests result = one.dot(one) + dot(one,one); assert(std::abs(result-ct(2)*ctlength)<= myEps); result = iVec.dot(iVec) + dot(iVec,iVec); assert(std::abs(result-ct(2)*ctlength)<= myEps); // mixed global dotT tests result = iVec*one + one*iVec + dotT(one,iVec) + dotT(iVec,one); assert(std::abs(result-ct(4)*ctlength*I)<= myEps); // mixed global dot tests result = iVec.dot(one) + dot(iVec,one); assert(std::abs(result-ct(2)*complexSign*ctlength*I)<= myEps); result = one.dot(iVec) + dot(one,iVec); assert(std::abs(result-ct(2)*ctlength*I)<= myEps); return 0; } int main() { int ret = 0; const size_t BlockSize = 5; const size_t numBlocks = 10; const size_t capacity = BlockSize * numBlocks * 2; // use capacity here, that we can use the a constructor taking two integers for both BlockVector and VariableBlockVector ret += DotProductTest >, Dune::BlockVector > > (numBlocks,capacity); ret += DotProductTest >, Dune::VariableBlockVector > > (numBlocks,1); ret += DotProductTest >, Dune::BlockVector,BlockSize> > > (numBlocks,capacity); ret += DotProductTest >, Dune::VariableBlockVector,1> > > (numBlocks,BlockSize); ret += DotProductTest >, Dune::BlockVector > > (numBlocks,capacity); ret += DotProductTest >, Dune::VariableBlockVector > > (numBlocks,1); ret += DotProductTest >, Dune::BlockVector,BlockSize> > > (numBlocks,capacity); ret += DotProductTest >, Dune::VariableBlockVector,1> > > (numBlocks,BlockSize); ret += DotProductTest >, Dune::BlockVector > > (numBlocks,capacity); ret += DotProductTest >, Dune::VariableBlockVector > > (numBlocks,BlockSize); return ret; } dune-istl-2.5.1/dune/istl/test/fieldvectortest.cc000066400000000000000000000035721313314427100220330ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif /** \file * \brief Test the FieldVector class from dune-common with the unit tests for the dune-istl vector interface * * This test is exceptional: it is testing a class from dune-common! This is because FieldVector is supposed * to implement the dune-istl vector interface, but it resides in dune-common because most other modules * also want to use it. However, the tests for the dune-istl vector interface reside in dune-istl, and therefore * the compliance test for FieldVector needs to be done in dune-istl, too. */ #include #include #include using namespace Dune; int main() try { // Test a double vector FieldVector vDouble = {1.0, 2.0, 3.0}; testHomogeneousRandomAccessContainer(vDouble); testConstructibility(); testNorms(vDouble); testVectorSpaceOperations(vDouble); // Test a double vector of length 1 FieldVector vDouble1 = {1.0}; testHomogeneousRandomAccessContainer(vDouble1); testConstructibility(); testNorms(vDouble1); testVectorSpaceOperations(vDouble1); // Test a complex vector FieldVector,3> vComplex = {{1.0, 1.0}, {2.0,2.0}, {3.0,3.0}}; testHomogeneousRandomAccessContainer(vComplex); testConstructibility(); testNorms(vComplex); testVectorSpaceOperations(vComplex); // Test a complex vector of length 1 FieldVector,1> vComplex1 = {{1.0,3.14}}; testHomogeneousRandomAccessContainer(vComplex1); testConstructibility(); testNorms(vComplex1); testVectorSpaceOperations(vComplex1); return 0; } catch (std::exception& e) { std::cerr << e.what() << std::endl; return 1; } dune-istl-2.5.1/dune/istl/test/inverseoperator2prectest.cc000066400000000000000000000031541313314427100237040ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #include "laplacian.hh" int main(int argc, char** argv) { const int BS=1; int N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="< solver1(fop, prec0, 1e-8,100,2); solver1.apply(x,b,res1); if(res1.iterations!=res.iterations*10) { std::cerr<<"Convergence rates do not match!"< #include #include #include #include #include "laplacian.hh" /* "tests" the writeMatrixToMatlabHelper method by calling it for a Laplacian with a given BlockType and writing to cout. * Actual functionality is not tested. */ template void testWriteMatrixToMatlab(BlockType b=BlockType(0.0)) { typedef Dune::BCRSMatrix Matrix; Matrix A; setupLaplacian(A, 3); A[0][0] += b; writeMatrixToMatlabHelper(A, 0, 0, std::cout); } /* uses the writeVectorToMatlab method, filled with dummy data */ template void testWriteVectorToMatlab() { VectorType v; for (unsigned int i = 0; i < v.size(); ++i) { v[i] = i; } Dune::writeVectorToMatlabHelper(v, std::cout); } int main(int argc, char** argv) { /* testing the writeMatrixToMatlabHelper method for BlockType=FieldMatrix with different field_types */ testWriteMatrixToMatlab >(); testWriteMatrixToMatlab >(); // testWriteMatrixToMatlab >(); // commented because setUpLaplacian cannot handle block_types with more rows than cols testWriteMatrixToMatlab >(); // testWriteMatrixToMatlab >(); // commented because setUpLaplacian cannot handle block_types with more rows than cols testWriteMatrixToMatlab >(); testWriteMatrixToMatlab,1,1> >(Dune::FieldMatrix,1,1>(std::complex(0, 1))); testWriteMatrixToMatlab,1,2> >(Dune::FieldMatrix,1,2>(std::complex(0, 1))); // testWriteMatrixToMatlab,2,1> >(); // commented because setUpLaplacian cannot handle block_types with more rows than cols testWriteMatrixToMatlab,4,7> >(Dune::FieldMatrix,4,7>(std::complex(0, 1))); // testWriteMatrixToMatlab,7,4> >(); // commented because setUpLaplacian cannot handle block_types with more rows than cols testWriteMatrixToMatlab,2,2> >(Dune::FieldMatrix,2,2>(std::complex(0, 1))); /* testing the writeMatrixToMatlabHelper method for BlockType=[Diagonal|ScaledIdentity]Matrix with different field_types */ testWriteMatrixToMatlab >(); testWriteMatrixToMatlab >(); testWriteMatrixToMatlab >(); testWriteMatrixToMatlab >(); testWriteMatrixToMatlab,1> >(Dune::DiagonalMatrix,1>(std::complex(0,1))); testWriteMatrixToMatlab,1> >(Dune::ScaledIdentityMatrix,1>(std::complex(0,1))); testWriteMatrixToMatlab,2> >(Dune::DiagonalMatrix,2>(std::complex(0,1))); testWriteMatrixToMatlab,2> >(Dune::ScaledIdentityMatrix,2>(std::complex(0,1))); /* testing the test writeMatrixToMatlabHelper for FieldVector */ testWriteVectorToMatlab >(); testWriteVectorToMatlab >(); testWriteVectorToMatlab,5> >(); /* testing the test writeMatrixToMatlabHelper for BlockVector */ Dune::BlockVector > v1 = {{1.0, 2.0, 3.0}}; Dune::writeVectorToMatlabHelper(v1, std::cout); Dune::BlockVector > > v2 = {{1.0, 2.0}, {3.0, 4.0, 5.0}, {6.0}}; Dune::writeVectorToMatlabHelper(v2, std::cout); /* testing the test writeMatrixToMatlabHelper for STL containers */ testWriteVectorToMatlab >(); std::vector v3; v3.push_back(1); v3.push_back(2); Dune::writeVectorToMatlabHelper(v3, std::cout); } dune-istl-2.5.1/dune/istl/test/laplacian.hh000066400000000000000000000051031313314427100205530ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef LAPLACIAN_HH #define LAPLACIAN_HH #include #include template void setupSparsityPattern(Dune::BCRSMatrix& A, int N) { typedef typename Dune::BCRSMatrix Matrix; A.setSize(N*N, N*N, N*N*5); A.setBuildMode(Matrix::row_wise); for (typename Dune::BCRSMatrix::CreateIterator i = A.createbegin(); i != A.createend(); ++i) { int x = i.index()%N; // x coordinate in the 2d field int y = i.index()/N; // y coordinate in the 2d field if(y>0) // insert lower neighbour i.insert(i.index()-N); if(x>0) // insert left neighbour i.insert(i.index()-1); // insert diagonal value i.insert(i.index()); if(x void setupLaplacian(Dune::BCRSMatrix& A, int N) { typedef typename Dune::BCRSMatrix::field_type FieldType; setupSparsityPattern(A,N); B diagonal(static_cast(0)), bone(static_cast(0)), beps(static_cast(0)); for(typename B::RowIterator b = diagonal.begin(); b != diagonal.end(); ++b) b->operator[](b.index())=4; for(typename B::RowIterator b=bone.begin(); b != bone.end(); ++b) b->operator[](b.index())=-1.0; for (typename Dune::BCRSMatrix::RowIterator i = A.begin(); i != A.end(); ++i) { int x = i.index()%N; // x coordinate in the 2d field int y = i.index()/N; // y coordinate in the 2d field /* if(x==0 || x==N-1 || y==0||y==N-1){ i->operator[](i.index())=1.0; if(y>0) i->operator[](i.index()-N)=0; if(yoperator[](i.index()+N)=0.0; if(x>0) i->operator[](i.index()-1)=0.0; if(x < N-1) i->operator[](i.index()+1)=0.0; }else*/ { i->operator[](i.index())=diagonal; if(y>0) i->operator[](i.index()-N)=bone; if(yoperator[](i.index()+N)=bone; if(x>0) i->operator[](i.index()-1)=bone; if(x < N-1) i->operator[](i.index()+1)=bone; } } } template void setBoundary(Dune::BlockVector >& lhs, Dune::BlockVector >& rhs, int N) { for(int i=0; i < lhs.size(); ++i) { int x = i/N; int y = i%N; if(x==0 || y ==0 || x==N-1 || y==N-1) { lhs[i]=rhs[i]=0; } } } #endif dune-istl-2.5.1/dune/istl/test/ldltest.cc000066400000000000000000000036641313314427100203020ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include "laplacian.hh" int main(int argc, char** argv) { #if HAVE_SUITESPARSE_LDL try { typedef double FIELD_TYPE; const int BS=1; std::size_t N=100; if (argc > 1) { N = atoi(argv[1]); } std::cout << "testing for N=" << N << " BS=" << BS << std::endl; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; BCRSMat mat; Operator fop(mat); Vector b(N*N), x(N*N); setupLaplacian(mat,N); b=1; x=0; Dune::Timer watch; watch.reset(); Dune::LDL solver(mat,1); Dune::InverseOperatorResult res; Dune::LDL solver1; std::set mrs; for(std::size_t s=0; s < N/2; ++s) mrs.insert(s); solver1.setSubMatrix(mat,mrs); solver1.setVerbosity(true); solver.apply(x,b, res); solver.free(); Vector residuum(N*N); residuum=0; fop.apply(x,residuum); residuum-=b; std::cout<<"Residuum : "<(&x[0]), reinterpret_cast(&b[0])); return 0; } catch(Dune::Exception &e) { std::cerr << "Dune reported error: " << e << std::endl; } catch (...) { std::cerr << "Unknown exception" << std::endl; } #else // HAVE_SUITESPARSE_LDL std::cerr << "You need SuiteSparse's LDL to run this test." << std::endl; return 77; #endif // HAVE_SUITESPARSE_LDL } dune-istl-2.5.1/dune/istl/test/matrixiteratortest.cc000066400000000000000000000022501313314427100225730ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include class RowFunc { public: void operator()(const Dune::FieldMatrix& t){ std::cout << t <<" "; } }; class MatrixFunc { public: void operator()(const Dune::BCRSMatrix >::row_type& row) { std::cout << *(row.begin())<<" "; } }; int main() { using namespace Dune; typedef BCRSMatrix > M; BCRSMatrix > bcrsMatrix(3,3, BCRSMatrix >::random); bcrsMatrix.setrowsize(0,1); bcrsMatrix.setrowsize(1,2); bcrsMatrix.setrowsize(2,2); bcrsMatrix.endrowsizes(); bcrsMatrix.addindex(0, 0); bcrsMatrix.addindex(1, 1); bcrsMatrix.addindex(1, 0); bcrsMatrix.addindex(2, 2); bcrsMatrix.addindex(2, 1); bcrsMatrix.endindices(); bcrsMatrix = 0; MatrixFunc mf; RowFunc rf; return testIterator(bcrsMatrix,mf) + testIterator(bcrsMatrix[1], rf); } dune-istl-2.5.1/dune/istl/test/matrixmarkettest.cc000066400000000000000000000100061313314427100222230ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #if HAVE_MPI #include #include "mpi.h" #include #else #include #include "laplacian.hh" #endif int main(int argc, char** argv) { #if HAVE_MPI MPI_Init(&argc, &argv); int size; MPI_Comm_size(MPI_COMM_WORLD, &size); #endif const int BS=1; int N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="<(N, comm.indexSet(), comm.communicator(), &n, .011); #else BCRSMat mat; setupLaplacian(mat, N); #endif BVector bv(mat.N()), cv(mat.N()); typedef BVector::iterator VIter; int i=0; for(VIter entry=bv.begin(); bv.end() != entry; ++entry) { typedef BVector::block_type::iterator SIter; for(SIter sentry=entry->begin(); sentry != entry->end(); ++sentry,++i) *sentry=i; } #if HAVE_MPI comm.remoteIndices().rebuild(); comm.copyOwnerToAll(bv,bv); Dune::OverlappingSchwarzOperator op(mat, comm); op.apply(bv, cv); storeMatrixMarket(mat, std::string("testmat"), comm); storeMatrixMarket(bv, std::string("testvec"), comm, false); #else typedef Dune::MatrixAdapter Operator; Operator op(mat); op.apply(bv, cv); storeMatrixMarket(mat, std::string("testmat")); storeMatrixMarket(bv, std::string("testvec")); #endif BCRSMat mat1; BVector bv1,cv1; #if HAVE_MPI Communication comm1(MPI_COMM_WORLD); loadMatrixMarket(mat1, std::string("testmat"), comm1); loadMatrixMarket(bv1, std::string("testvec"), comm1, false); #else loadMatrixMarket(mat1, std::string("testmat")); loadMatrixMarket(bv1, std::string("testvec")); #endif int ret=0; if(mat.N()!=mat1.N() || mat.M()!=mat1.M()) { ++ret; std::cerr<<"matrix sizes do not match"<begin(), col1=row1->begin(); col!= row->end(); ++col, ++col1) { if(col.index()!=col1.index()) { std::cerr <<"Column indices do not match"< op1(mat1, comm1); op1.apply(bv1, cv1); if(comm1.indexSet()!=comm.indexSet()) { std::cerr<<"written and read idxset do not match"< Operator; Operator op1(mat1); op1.apply(bv1, cv1); #endif for(VIter entry=cv.begin(), entry1=cv1.begin(); cv.end() != entry; ++entry, ++entry1) if(*entry!=*entry1) { std::cerr<<"computed vectors do not match"< #include #include #include #include template void checkNormNANVector(V const &v, int line) { if (!std::isnan(v.infinity_norm())) { std::cerr << "error: norm not NaN: infinity_norm() on line " << line << " (type: " << Dune::className(v[0]) << ")" << std::endl; std::exit(-1); } } template void checkNormNANMatrix(M const &v, int line) { if (!std::isnan(v.frobenius_norm())) { std::cerr << "error: norm not NaN: frobenius_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } if (!std::isnan(v.infinity_norm())) { std::cerr << "error: norm not NaN: infinity_norm() on line " << line << " (type: " << Dune::className(v[0][0]) << ")" << std::endl; std::exit(-1); } } // Make sure that matrices with NaN entries have norm NaN. // See also bug flyspray/FS#1147 template void test_nan(T const &mynan) { using M = Dune::Matrix>; T n(0); { M m(2, 2); m[0][0] = {{n, n}, {n, mynan}}; m[0][1] = n; m[1][0] = n; m[1][1] = n; checkNormNANVector(m[0], __LINE__); checkNormNANMatrix(m, __LINE__); } { M m(2, 2); m[0][0] = n; m[0][1] = {{n, n}, {n, mynan}}; m[1][0] = n; m[1][1] = n; checkNormNANVector(m[0], __LINE__); checkNormNANMatrix(m, __LINE__); } { M m(2, 2); m[0][0] = n; m[0][1] = n; m[1][0] = {{n, n}, {n, mynan}}; m[1][1] = n; checkNormNANVector(m[1], __LINE__); checkNormNANMatrix(m, __LINE__); } } int main() { { double nan = std::nan(""); test_nan(nan); } { std::complex nan(std::nan(""), 17); test_nan(nan); } } dune-istl-2.5.1/dune/istl/test/matrixredisttest.cc000066400000000000000000000100301313314427100222270ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #define DEBUG_REPART #include #include #include #include #include #include #include #include #include class MPIError { public: /** @brief Constructor. */ MPIError(std::string s, int e) : errorstring(s), errorcode(e){} /** @brief The error string. */ std::string errorstring; /** @brief The mpi error code. */ int errorcode; }; void MPI_err_handler(MPI_Comm *, int *err_code, ...){ char *err_string=new char[MPI_MAX_ERROR_STRING]; int err_length; MPI_Error_string(*err_code, err_string, &err_length); std::string s(err_string, err_length); std::cerr << "An MPI Error occurred:"< int testRepart(int N, int coarsenTarget) { std::cout<<"==================================================="<communicator().size()>0) printGlobalSparseMatrix(newMat, *coarseComm, std::cout); comm.communicator().barrier(); // Check for symmetry int ret=0; typedef typename BCRSMat::ConstRowIterator RIter; for(RIter row=newMat.begin(), rend=newMat.end(); row != rend; ++row) { typedef typename BCRSMat::ConstColIterator CIter; for(CIter col=row->begin(), cend=row->end(); col!=cend; ++col) { if(col.index()<=row.index()) try{ newMat[col.index()][row.index()]; }catch(Dune::ISTLError e) { std::cerr<communicator().rank()<<": entry (" <communicator().rank()==0) //Dune::printmatrix(std::cout, newMat, "redist", "row"); delete coarseComm; return ret; } int main(int argc, char** argv) { MPI_Init(&argc, &argv); MPI_Errhandler handler; MPI_Errhandler_create(MPI_err_handler, &handler); MPI_Errhandler_set(MPI_COMM_WORLD, handler); int procs; MPI_Comm_size(MPI_COMM_WORLD, &procs); int N=4*procs; int coarsenTarget=1; if(argc>1) N = atoi(argv[1]); if(argc>2) coarsenTarget = atoi(argv[2]); if(N(N,coarsenTarget); MPI_Finalize(); } dune-istl-2.5.1/dune/istl/test/matrixtest.cc000066400000000000000000000365601313314427100210340ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief Unit tests for the different dynamic matrices provided by ISTL */ #include "config.h" #include #include #include #include #include #include #include #include #include using namespace Dune; // forward decls template void testSuperMatrix(MatrixType& matrix); template void testMatrix(MatrixType& matrix, X& x, Y& y); template void testSolve(const MatrixType& matrix); template void testSuperMatrix(MatrixType& matrix) { // //////////////////////////////////////////////////////// // Check the types which are exported by the matrix // //////////////////////////////////////////////////////// typedef typename MatrixType::field_type field_type; typedef typename MatrixType::block_type block_type; typedef typename MatrixType::size_type size_type; typedef typename MatrixType::allocator_type allocator_type DUNE_UNUSED; size_type n = matrix.N(); size_type m = matrix.M(); BlockVector > x(m); BlockVector > y(n); testMatrix(matrix, x, y); } template void testMatrix(MatrixType& matrix, X& x, Y& y) { // //////////////////////////////////////////////////////// // Check the types which are exported by the matrix // //////////////////////////////////////////////////////// typedef typename MatrixType::field_type field_type; typedef typename FieldTraits::real_type real_type; typedef typename MatrixType::block_type block_type DUNE_UNUSED; typedef typename MatrixType::row_type row_type DUNE_UNUSED; typedef typename MatrixType::size_type size_type; typedef typename MatrixType::RowIterator RowIterator DUNE_UNUSED; typedef typename MatrixType::ConstRowIterator ConstRowIterator DUNE_UNUSED; typedef typename MatrixType::ColIterator ColIterator DUNE_UNUSED; typedef typename MatrixType::ConstColIterator ConstColIterator DUNE_UNUSED; assert(MatrixType::blocklevel >= 0); // //////////////////////////////////////////////////////// // Count number of rows, columns, and nonzero entries // //////////////////////////////////////////////////////// typename MatrixType::RowIterator rowIt = matrix.begin(); typename MatrixType::RowIterator rowEndIt = matrix.end(); typename MatrixType::size_type numRows = 0, numEntries = 0; for (; rowIt!=rowEndIt; ++rowIt) { typename MatrixType::ColIterator colIt = rowIt->begin(); typename MatrixType::ColIterator colEndIt = rowIt->end(); for (; colIt!=colEndIt; ++colIt) { assert(matrix.exists(rowIt.index(), colIt.index())); numEntries++; } numRows++; } assert (numRows == matrix.N()); // /////////////////////////////////////////////////////////////// // Count number of rows, columns, and nonzero entries again. // This time use the const iterators // /////////////////////////////////////////////////////////////// typename MatrixType::ConstRowIterator constRowIt = matrix.begin(); typename MatrixType::ConstRowIterator constRowEndIt = matrix.end(); numRows = 0; numEntries = 0; for (; constRowIt!=constRowEndIt; ++constRowIt) { typename MatrixType::ConstColIterator constColIt = constRowIt->begin(); typename MatrixType::ConstColIterator constColEndIt = constRowIt->end(); for (; constColIt!=constColEndIt; ++constColIt) numEntries++; numRows++; } assert (numRows == matrix.N()); // //////////////////////////////////////////////////////// // Count number of rows, columns, and nonzero entries // This time we're counting backwards // //////////////////////////////////////////////////////// rowIt = matrix.beforeEnd(); rowEndIt = matrix.beforeBegin(); numRows = 0; numEntries = 0; for (; rowIt!=rowEndIt; --rowIt) { typename MatrixType::ColIterator colIt = rowIt->beforeEnd(); typename MatrixType::ColIterator colEndIt = rowIt->beforeBegin(); for (; colIt!=colEndIt; --colIt) { assert(matrix.exists(rowIt.index(), colIt.index())); numEntries++; } numRows++; } assert (numRows == matrix.N()); // /////////////////////////////////////////////////////////////// // Count number of rows, columns, and nonzero entries again. // This time use the const iterators and count backwards. // /////////////////////////////////////////////////////////////// constRowIt = matrix.beforeEnd(); constRowEndIt = matrix.beforeBegin(); numRows = 0; numEntries = 0; for (; constRowIt!=constRowEndIt; --constRowIt) { typename MatrixType::ConstColIterator constColIt = constRowIt->beforeEnd(); typename MatrixType::ConstColIterator constColEndIt = constRowIt->beforeBegin(); for (; constColIt!=constColEndIt; --constColIt) numEntries++; numRows++; } assert (numRows == matrix.N()); // /////////////////////////////////////////////////////// // More dimension stuff // /////////////////////////////////////////////////////// size_type n = matrix.N(); ++n; size_type m = matrix.M(); ++m; // /////////////////////////////////////////////////////// // Test assignment operators and the copy constructor // /////////////////////////////////////////////////////// // assignment from other matrix MatrixType secondMatrix; secondMatrix = matrix; // assignment from scalar matrix = 0; // The copy constructor DUNE_UNUSED MatrixType thirdMatrix(matrix); // /////////////////////////////////////////////////////// // Test component-wise operations // /////////////////////////////////////////////////////// matrix *= M_PI; matrix /= M_PI; matrix += secondMatrix; matrix -= secondMatrix; // /////////////////////////////////////////////////////////// // Test the various matrix-vector multiplications // /////////////////////////////////////////////////////////// Y yy=y; matrix.mv(x,yy); matrix.mtv(x,yy); matrix.umv(x,y); matrix.umtv(x,y); matrix.umhv(x,y); matrix.mmv(x,y); matrix.mmtv(x,y); matrix.mmhv(x,y); matrix.usmv(M_PI,x,y); matrix.usmtv(M_PI,x,y); matrix.usmhv(M_PI,x,y); // ////////////////////////////////////////////////////////////// // Test the matrix norms // ////////////////////////////////////////////////////////////// real_type frobenius_norm = matrix.frobenius_norm(); frobenius_norm += matrix.frobenius_norm2(); frobenius_norm += matrix.infinity_norm(); frobenius_norm += matrix.infinity_norm_real(); } // /////////////////////////////////////////////////////////////////// // Test the solve()-method for those matrix classes that have it // /////////////////////////////////////////////////////////////////// template void testSolve(const MatrixType& matrix) { typedef typename VectorType::size_type size_type; // create some right hand side VectorType b(matrix.N()); for (size_type i=0; i 1e-10) DUNE_THROW(ISTLError, "Solve() method doesn't appear to produce the solution!"); } // ////////////////////////////////////////////////////////////// // Test transposing the matrix // ////////////////////////////////////////////////////////////// template void testTranspose(const MatrixType& matrix) { MatrixType transposedMatrix = matrix.transpose(); for(size_t i = 0; i < matrix.N(); i++) for(size_t j = 0; j < matrix.M(); j++) if(fabs(transposedMatrix[j][i] - matrix[i][j]) > 1e-10) DUNE_THROW(ISTLError, "transpose() method produces wrong result!"); } int main() { // feenableexcept does not exist on OS X #ifndef __APPLE__ feenableexcept(FE_INVALID); #endif // //////////////////////////////////////////////////////////// // Test the Matrix class -- a scalar dense dynamic matrix // //////////////////////////////////////////////////////////// Matrix > matrixScalar(10,10); for (int i=0; i<10; i++) for (int j=0; j<10; j++) matrixScalar[i][j] = (i+j)/((double)(i*j+1)); // just anything testSuperMatrix(matrixScalar); // //////////////////////////////////////////////////////////// // Test the Matrix class -- a block-valued dense dynamic matrix // //////////////////////////////////////////////////////////// Matrix > matrix(10,10); for (int i=0; i<10; i++) for (int j=0; j<10; j++) for (int k=0; k<3; k++) for (int l=0; l<3; l++) matrix[i][j][k][l] = (i+j)/((double)(k*l+1)); // just anything testSuperMatrix(matrix); Matrix > nonquadraticMatrix(1,2); { size_t n = 1; for (size_t i=0; i<1; i++) for (size_t j=0; j<2; j++) nonquadraticMatrix[i][j] = n++; } testTranspose(nonquadraticMatrix); // //////////////////////////////////////////////////////////// // Test the BCRSMatrix class -- a sparse dynamic matrix // //////////////////////////////////////////////////////////// BCRSMatrix > bcrsMatrix(4,4, BCRSMatrix >::random); bcrsMatrix.setrowsize(0,2); bcrsMatrix.setrowsize(1,3); bcrsMatrix.setrowsize(2,3); bcrsMatrix.setrowsize(3,2); bcrsMatrix.endrowsizes(); bcrsMatrix.addindex(0, 0); bcrsMatrix.addindex(0, 1); bcrsMatrix.addindex(1, 0); bcrsMatrix.addindex(1, 1); bcrsMatrix.addindex(1, 2); bcrsMatrix.addindex(2, 1); bcrsMatrix.addindex(2, 2); bcrsMatrix.addindex(2, 3); bcrsMatrix.addindex(3, 2); bcrsMatrix.addindex(3, 3); bcrsMatrix.endindices(); typedef BCRSMatrix >::RowIterator RowIterator; typedef BCRSMatrix >::ColIterator ColIterator; for(RowIterator row = bcrsMatrix.begin(); row != bcrsMatrix.end(); ++row) for(ColIterator col = row->begin(); col != row->end(); ++col) *col = 1.0 + (double) row.index() * (double) col.index(); testSuperMatrix(bcrsMatrix); // //////////////////////////////////////////////////////////////////////// // Test the BDMatrix class -- a dynamic block-diagonal matrix // //////////////////////////////////////////////////////////////////////// BDMatrix > bdMatrix(2); bdMatrix = 4.0; testSuperMatrix(bdMatrix); // //////////////////////////////////////////////////////////////////////// // Test the BTDMatrix class -- a dynamic block-tridiagonal matrix // a) the scalar case // //////////////////////////////////////////////////////////////////////// BTDMatrix > btdMatrixScalar(4); typedef BTDMatrix >::size_type size_type; btdMatrixScalar = 4.0; testSuperMatrix(btdMatrixScalar); btdMatrixScalar = 0.0; for (size_type i=0; i >, BlockVector > >(btdMatrixScalar); // test a 1x1 BTDMatrix, because that is a special case BTDMatrix > btdMatrixScalar_1x1(1); btdMatrixScalar_1x1 = 1.0; testSuperMatrix(btdMatrixScalar_1x1); // //////////////////////////////////////////////////////////////////////// // Test the BTDMatrix class -- a dynamic block-tridiagonal matrix // b) the block-valued case // //////////////////////////////////////////////////////////////////////// BTDMatrix > btdMatrix(4); typedef BTDMatrix >::size_type size_type; btdMatrix = 0.0; for (size_type i=0; i(1+i); for (size_type i=0; i(2+i); // upper off-diagonal for (size_type i=1; i(2+i); // lower off-diagonal // add some off diagonal stuff to the blocks in the matrix // diagonals btdMatrix[0][0][0][1] = 2; btdMatrix[0][0][1][0] = -1; btdMatrix[1][1][0][1] = 2; btdMatrix[1][1][1][0] = 3; btdMatrix[2][2][0][1] = 2; btdMatrix[2][2][0][0] += sqrt(2.); btdMatrix[2][2][1][0] = 3; btdMatrix[3][3][0][1] = -1; btdMatrix[3][3][0][0] -= 0.5; btdMatrix[3][3][1][0] = 2; // off diagonals btdMatrix[0][1][0][1] = std::sqrt(2); btdMatrix[1][0][0][1] = std::sqrt(2); btdMatrix[1][0][1][0] = -13./17.; btdMatrix[1][2][0][1] = -1./std::sqrt(2); btdMatrix[1][2][1][0] = -13./17.; btdMatrix[2][1][0][1] = -13./17.; btdMatrix[2][1][1][0] = -13./17.; btdMatrix[2][3][0][1] = -1./std::sqrt(2); btdMatrix[2][3][1][0] = -17.; btdMatrix[3][2][0][1] = 1.; btdMatrix[3][2][1][0] = 1.; BTDMatrix > btdMatrixThrowAway = btdMatrix; // the test method overwrites the matrix testSuperMatrix(btdMatrixThrowAway); testSolve >, BlockVector > >(btdMatrix); // test a 1x1 BTDMatrix, because that is a special case BTDMatrix > btdMatrix_1x1(1); btdMatrix_1x1 = 1.0; testSuperMatrix(btdMatrix_1x1); // //////////////////////////////////////////////////////////////////////// // Test the FieldMatrix class // //////////////////////////////////////////////////////////////////////// typedef FieldMatrix::size_type size_type; FieldMatrix fMatrix; for (size_type i=0; i fvX; FieldVector fvY; testMatrix(fMatrix, fvX, fvY); // //////////////////////////////////////////////////////////////////////// // Test the 1x1 specialization of the FieldMatrix class // //////////////////////////////////////////////////////////////////////// FieldMatrix fMatrix1x1; fMatrix1x1[0][0] = 2.3; // just anything FieldVector fvX1; FieldVector fvY1; testMatrix(fMatrix, fvX, fvY); // //////////////////////////////////////////////////////////////////////// // Test the DiagonalMatrix class // //////////////////////////////////////////////////////////////////////// FieldVector dMatrixConstructFrom; dMatrixConstructFrom = 3.1459; DiagonalMatrix dMatrix1; dMatrix1 = 3.1459; testMatrix(dMatrix1, fvX, fvY); DiagonalMatrix dMatrix2(3.1459); testMatrix(dMatrix2, fvX, fvY); DiagonalMatrix dMatrix3(dMatrixConstructFrom); testMatrix(dMatrix3, fvX, fvY); // //////////////////////////////////////////////////////////////////////// // Test the ScaledIdentityMatrix class // //////////////////////////////////////////////////////////////////////// ScaledIdentityMatrix sIdMatrix; sIdMatrix = 3.1459; testMatrix(sIdMatrix, fvX, fvY); } dune-istl-2.5.1/dune/istl/test/matrixutilstest.cc000066400000000000000000000025441313314427100221100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include "laplacian.hh" int main(int argc, char** argv) { Dune::FieldMatrix fmatrix; int ret=0; if(4*7!=countNonZeros(fmatrix)) { Dune::derr<<"Counting nonzeros of fieldMatrix failed!"< > BMatrix; BMatrix laplace; setupLaplacian(laplace, N); if(N*N*5-4*2-(N-2)*4!=countNonZeros(laplace)) { ++ret; Dune::derr<<"Counting nonzeros of BCRSMatrix failed!"< > blaplace; setupLaplacian(blaplace,N); if((N*N*5-4*2-(N-2)*4)*4*7!=countNonZeros(blaplace)) { ++ret; Dune::derr<<"Counting nonzeros of block BCRSMatrix failed!"< > bblaplace; bblaplace.setSize(N*N,N*N, N*N*5); bblaplace.setBuildMode(Dune::BCRSMatrix >::row_wise); setupLaplacian(bblaplace,N); if((N*N*5-4*2-(N-2)*4)*4*7!=countNonZeros(bblaplace)) { ++ret; Dune::derr<<"Counting nonzeros of block BCRSMatrix failed!"< #include #include #include int main(int argc, char** argv) { typedef Dune::BCRSMatrix > MatrixType; MatrixType m1(2,2,MatrixType::random) , m2(2,2,MatrixType::random) , res(2,2,MatrixType::random); // initialize first matrix [1,0;0,1] m1.setrowsize(0,1); m1.setrowsize(1,1); m1.endrowsizes(); m1.addindex(0,0); m1.addindex(1,1); m1.endindices(); m1[0][0] = 1; m1[1][1] = 1; // initialize second matrix [0,1;1,0] m2.setrowsize(0,1); m2.setrowsize(1,1); m2.endrowsizes(); m2.addindex(0,1); m2.addindex(1,0); m2.endindices(); m2[0][1] = 1; m2[1][0] = 1; Dune::printmatrix(std::cout, m1, "m1", ""); Dune::printmatrix(std::cout, m2, "m2", ""); Dune::matMultTransposeMat(res, m1, m2); Dune::printmatrix(std::cout, res, "res", ""); return 0; } dune-istl-2.5.1/dune/istl/test/multitypeblockmatrixtest.cc000066400000000000000000000175111313314427100240170ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** * \file * \brief Test the MultiTypeBlockMatrix data structure */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Dune; int main(int argc, char** argv) try { // Import the static constants _0, _1, etc using namespace Indices; /////////////////////////////////////////////////////////////////////////////////////////////////////////// // First, we test a MultiTypeBlockMatrix consisting of an array of 2x2 dense matrices. // The upper left dense matrix has dense 3x3 blocks, the lower right matrix has 1x1 blocks, // the off-set diagonal matrix block sizes are set accordingly. /////////////////////////////////////////////////////////////////////////////////////////////////////////// // set up the test matrix typedef MultiTypeBlockVector >, Matrix > > RowType0; typedef MultiTypeBlockVector >, Matrix > > RowType1; MultiTypeBlockMatrix multiMatrix; multiMatrix[_0][_0].setSize(3,3); multiMatrix[_0][_1].setSize(3,2); multiMatrix[_1][_0].setSize(2,3); multiMatrix[_1][_1].setSize(2,2); // lazy solution: initialize the entire matrix with zeros multiMatrix = 0; printmatrix(std::cout, multiMatrix[_0][_0], "(0,0)", "--"); printmatrix(std::cout, multiMatrix[_0][_1], "(0,1)", "--"); printmatrix(std::cout, multiMatrix[_1][_0], "(1,0)", "--"); printmatrix(std::cout, multiMatrix[_1][_1], "(1,1)", "--"); // set up a test vector MultiTypeBlockVector >, BlockVector > > multiVector; multiVector[_0] = {{1,0,0}, {0,1,0}, {0,0,1}}; multiVector[_1] = {3.14, 42}; // Test matrix-vector products MultiTypeBlockVector >, BlockVector > > result; result[_0].resize(3); result[_1].resize(2); multiMatrix[_0][_0] = 4200; multiMatrix[_0][_1] = 4201; multiMatrix[_1][_0] = 4210; multiMatrix[_1][_1] = 4211; multiMatrix.mv(multiVector,result); std::cout << "mv result" << std::endl << result << std::endl; multiMatrix.umv(multiVector,result); std::cout << "umv result" << std::endl << result << std::endl; multiMatrix.mmv(multiVector,result); std::cout << "mmv result" << std::endl << result << std::endl; multiMatrix.usmv(3.14,multiVector,result); std::cout << "usmv result" << std::endl << result << std::endl; /////////////////////////////////////////////////////////////////////////////////////////////////////////// // Next test: Set up a linear system with a matrix consisting of 2x2 sparse scalar matrices. // Solve the linear system with a simple iterative scheme. // \todo What's the point if all four matrices have the same type? /////////////////////////////////////////////////////////////////////////////////////////////////////////// std::cout << "Jacobi Solver Test on MultiTypeBlockMatrix"; typedef Dune::FieldMatrix LittleBlock; //matrix block type typedef Dune::BCRSMatrix BCRSMat; //matrix type const int X1=3; //index bounds of all four matrices const int X2=2; const int Y1=3; const int Y2=2; BCRSMat A11 = BCRSMat(X1,Y1,X1*Y1,BCRSMat::random); //A11 is 3x3 BCRSMat A12 = BCRSMat(X1,Y2,X1*Y2,BCRSMat::random); //A12 is 2x3 BCRSMat A21 = BCRSMat(X2,Y1,X2*Y1,BCRSMat::random); //A11 is 3x2 BCRSMat A22 = BCRSMat(X2,Y2,X2*Y2,BCRSMat::random); //A12 is 2x2 typedef Dune::MultiTypeBlockVector >,Dune::BlockVector > > TestVector; TestVector x, b; x[_0].resize(Y1); x[_1].resize(Y2); b[_0].resize(X1); b[_1].resize(X2); x = 1; b = 1; //set row sizes for (int i=0; i=Y1) A12.addindex(i,j-Y1); if (i>=X1 && j=X1 && j>=Y1) A22.addindex(i-X1,j-Y1); } } A11.endindices(); A12.endindices(); A21.endindices(); A22.endindices(); A11 = 0; A12 = 0; A21 = 0; A22 = 0; //fill in values (row-wise) in A11 and A22 for (int i=0; i0) A11[i][i-1]=-1; A11[i][i]=2; //diag if (i0) A22[i][i-1]=-1; A22[i][i]=2; if (i BCRS_Row; typedef Dune::MultiTypeBlockMatrix CM_BCRS; CM_BCRS A; A[_0][_0] = A11; A[_0][_1] = A12; A[_1][_0] = A21; A[_1][_1] = A22; x = 1; b = 1; // Set up a variety of solvers, just to make sure they compile MatrixAdapter op(A); // make linear operator from A SeqSOR sor(A,1,1.9520932); // SOR preconditioner SeqSSOR ssor(A,1,1.0); // SSOR preconditioner // Solve system using a Gauss-Seidel method SeqGS gs(A,1,1); // GS preconditioner LoopSolver loop(op,gs,1E-4,18000,2); // an inverse operator InverseOperatorResult r; loop.apply(x,b,r); // Solve system using a CG method with a Jacobi preconditioner SeqJac jac(A,1,1); // Jacobi preconditioner CGSolver cgSolver(op,jac,1E-4,18000,2); // an inverse operator cgSolver.apply(x,b,r); // Solve system using a GMRes solver without preconditioner at all // Fancy (but only) way to not have a preconditioner at all Richardson richardson(1.0); // Preconditioned conjugate-gradient solver RestartedGMResSolver gmres(op, richardson, 1e-4, // desired residual reduction factor 5, // number of iterations between restarts 100, // maximum number of iterations 2); // verbosity of the solver gmres.apply(x, b, r); printvector(std::cout,x[_0],"solution x1","entry",11,9,1); printvector(std::cout,x[_1],"solution x2","entry",11,9,1); return 0; } catch (Dune::Exception& e) { std::cerr << "DUNE reported an exception: " << e << std::endl; return 1; } catch (std::exception& e) { std::cerr << "C++ reported an exception: " << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Unknown exception encountered!" << std::endl; return 3; } dune-istl-2.5.1/dune/istl/test/multitypeblockvectortest.cc000066400000000000000000000047101313314427100240120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** * \file * \brief Test the MultiTypeBlockVector data structure */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include using namespace Dune; int main(int argc, char** argv) try { using namespace Indices; MultiTypeBlockVector >, BlockVector > > multiVector; multiVector[_0] = {{1,0,0}, {0,1,0}, {0,0,1}}; multiVector[_1] = {3.14, 42}; // test operator<< std::cout << multiVector << std::endl; // test method 'count' std::cout << "multi vector has " << multiVector.count() << " first level blocks" << std::endl; static_assert(multiVector.size()==2, "Method MultiTypeBlockVector::size() returned wrong value!"); if (multiVector.count() != 2) DUNE_THROW(Exception, "Method MultiTypeBlockVector::count returned wrong value!"); // Test copy construction auto multiVector2 = multiVector; // Test assignment operator multiVector2 = multiVector; // Test operator+= multiVector2 += multiVector; // Test operator-= multiVector2 -= multiVector; // Test multiplication with scalar multiVector2 *= (double)0.5; multiVector2 *= (int)2; multiVector2 *= (float)0.5; // Test assignment from scalar multiVector2 = (double)0.5; multiVector2 = (int)2; multiVector2 = (float)0.5; // Test axpy multiVector2.axpy(-1, multiVector); // Test two_norm std::cout << "multivector2 has two_norm: " << multiVector2.two_norm() << std::endl; // Test two_norm2 std::cout << "multivector2 has two_norm2: " << multiVector2.two_norm2() << std::endl; // Test infinity_norm std::cout << "multivector2 has infinity_norm: " << multiVector2.infinity_norm() << std::endl; // Test operator* std::cout << multiVector * multiVector2 << std::endl; // Test method 'dot' std::cout << multiVector.dot(multiVector2) << std::endl; return 0; } catch (Dune::Exception& e) { std::cerr << "DUNE reported an exception: " << e << std::endl; return 1; } catch (std::exception& e) { std::cerr << "C++ reported an exception: " << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Unknown exception encountered!" << std::endl; return 3; } dune-istl-2.5.1/dune/istl/test/mv.cc000066400000000000000000000022431313314427100172410ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include "laplacian.hh" int main(int argc, char** argv) { const int BS=1; int N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="< #include #include #include #include #include #include "laplacian.hh" #include #include #include #include #include #include #include int main(int argc, char** argv) { #if HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK const int BS=1; int N=4; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="<begin(); entry != iter->end(); ++entry) { std::cout<<" "<<*entry; } std::cout< > prec0(mat, domains, 1); Dune::LoopSolver solver0(fop, prec0, 1e-2,100,2); solver0.apply(x,b, res); b=0; x=100; Dune::SeqOverlappingSchwarz > prec1(mat, domains, 1, false); Dune::LoopSolver solver1(fop, prec1, 1e-2,100,2); solver1.apply(x,b, res); #endif // HAVE_SUITESPARSE_UMFPACK #if HAVE_SUPERLU std::cout << "Do testing with SuperLU" << std::endl; x=100; b=0; Dune::SeqOverlappingSchwarz > slu_prec0(mat, domains, 1); Dune::LoopSolver slu_solver(fop, slu_prec0, 1e-2,100,2); slu_solver.apply(x,b, res); x=100; b=0; Dune::SeqOverlappingSchwarz > slu_prec1(mat, domains, 1, false); Dune::LoopSolver slu_solver1(fop, slu_prec1, 1e-2,100,2); slu_solver1.apply(x,b, res); #endif x=100; b=0; std::cout << "Do testing with DynamicMatrixSubdomainSolver" << std::endl; Dune::SeqOverlappingSchwarz > dyn_prec0(mat, domains, 1); Dune::LoopSolver dyn_solver(fop, dyn_prec0, 1e-2,100,2); dyn_solver.apply(x,b, res); std::cout<<"Additive Schwarz not on the fly (domains vector)"< prec0o(mat, domains, 1, false); Dune::LoopSolver solver0o(fop, prec0o, 1e-2,100,2); solver0o.apply(x,b, res); std::cout << "Multiplicative Schwarz (domains vector)"< prec1m(mat, domains, 1); Dune::LoopSolver solver1m(fop, prec1m, 1e-2,100,2); solver1m.apply(x,b, res); std::cout<<"Additive Schwarz (rowToDomain vector)"<begin(); d!=i->end(); ++d) std::cout<<*d<<" "; std::cout< prec2(mat, rowToDomain, 1); Dune::LoopSolver solver2(fop, prec2, 1e-2,100,2); solver2.apply(x,b, res); std::cout << "Multiplicative Schwarz (rowToDomain vector)"< prec3(mat, rowToDomain, 1); Dune::LoopSolver solver3(fop, prec3, 1e-2,100,2); solver3.apply(x,b, res); std::cout << "SOR"< sor(mat, 1,1); Dune::LoopSolver solver4(fop, sor, 1e-2,100,2); solver4.apply(x,b, res); return 0; #else // HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK std::cerr << "You need SuperLU or SuiteSparse's UMFPack to run this test." << std::endl; return 77; #endif // HAVE_SUPERLU || HAVE_SUITESPARSE_UMFPACK } dune-istl-2.5.1/dune/istl/test/scaledidmatrixtest.cc000066400000000000000000000024041313314427100225130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" // include this first to see whether it includes all necessary headers itself #include #include #include #include #include using namespace Dune; template void test_matrix() { ScaledIdentityMatrix A(1); FieldVector f; FieldVector v; // assign matrix A=2; // assign vector f = 1; v = 2; // matrix vector product A.umv(v,f); // test norms A.frobenius_norm(); A.frobenius_norm2(); A.infinity_norm(); A.infinity_norm_real(); std::sort(v.begin(), v.end()); // print matrix std::cout << A << std::endl; // print vector std::cout << f << std::endl; // Construction of FieldMatrix from ScaledIdentityMatrix FieldMatrix AFM DUNE_UNUSED = FieldMatrix(A); } int main() { try { test_matrix(); test_matrix(); //test_matrix(); Does not compile with icc because there is no std::sqrt(int) std::fabs(int) test_matrix(); } catch (Dune::Exception & e) { std::cerr << "Exception: " << e << std::endl; } } dune-istl-2.5.1/dune/istl/test/solveraborttest.cc000066400000000000000000000071251313314427100220650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #include #include template void checkSolverAbort(int &status, const std::string &name, Solver &solver, Vector &x, Vector &b) { try { Dune::InverseOperatorResult res; solver.apply(x, b, res); std::cout << "Error: " << name << "::apply() did not abort, which is " << "unexpected.\n" << "converged = " << std::boolalpha << res.converged << "\n" << "iterations = " << res.iterations << "\n" << "reduction = " << res.reduction << "\n" << "conv_rate = " << res.conv_rate << "\n" << "elapsed = " << res.elapsed << "\n" << "solution = {" << x << "}" << std::endl; status = 1; // FAIL } catch(const Dune::SolverAbort &e) { std::cout << name << "::apply() aborted, as expected" << std::endl << "Abort message was: " << e << std::endl; if(status == 77) status = 0; // PASS } catch(const std::exception &e) { std::cout << "Error: " << name << "::apply() aborted with an exception " << "not derived from Dune::SolverAbort, which is unexpected.\n" << "e.what(): " << e.what() << std::endl; status = 1; // FAIL } catch(...) { std::cout << "Error: " << name << "::apply() aborted with an exception " << "not derived from Dune::SolverAbort, which is unexpected.\n" << "In addition, the exception is not derived from " << "std::exception, so there is no further information, sorry." << std::endl; status = 1; // FAIL } } int main() { int status = 77; // How verbose the solvers should be. Use 2 (maximum verbosity) by default, // this will include all information in the logs, and for the casual user of // the unit tests ctest will hide the output anyway. int verbose = 2; { // CGSolver std::cout << "Checking CGSolver with an unsolvable system...\n" << "Expecting SolverAbort with a NaN defect" << std::endl; using Matrix = Dune::FieldMatrix; using Vector = Dune::FieldVector; Matrix matrix = { { 1, 1 }, { 1, 1 } }; Vector b = { 1, 2 }; Vector x = { 0, 0 }; Dune::MatrixAdapter op(matrix); Dune::Richardson richardson; Dune::CGSolver solver(op, richardson, 1e-10, 5000, verbose); checkSolverAbort(status, "CGSolver", solver, x, b); } { // BiCGSTABSolver std::cout << "Checking BiCGSTABSolver with an unsolvable system...\n" << "Expecting abs(h) < EPSILON" << std::endl; using Matrix = Dune::FieldMatrix; using Vector = Dune::FieldVector; Matrix matrix = { { 1, 1 }, { 1, 1 } }; Vector b = { 1, 2 }; Vector x = { 0, 0 }; Dune::MatrixAdapter op(matrix); Dune::Richardson richardson; Dune::BiCGSTABSolver solver(op, richardson, 1e-10, 5000, verbose); checkSolverAbort(status, "BiCGSTABSolver", solver, x, b); } // TODO: // - trigger "breakdown in BiCGSTAB - rho" // - trigger "breakdown in BiCGSTAB - omega" // - trigger "breakdown in GMRes" return status; } dune-istl-2.5.1/dune/istl/test/solvertest.cc000066400000000000000000000031541313314427100210330ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #include #include "laplacian.hh" #include int main(int argc, char** argv) { const int BS=1; int N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="< FIELD_TYPE; const int BS=1; std::size_t N=100; if (argc > 1) { N = atoi(argv[1]); } std::cout << "testing for N=" << N << " BS=" << BS << std::endl; typedef Dune::FieldMatrix MatrixBlock; typedef Dune::BCRSMatrix BCRSMat; typedef Dune::FieldVector VectorBlock; typedef Dune::BlockVector Vector; typedef Dune::MatrixAdapter Operator; BCRSMat mat; Operator fop(mat); Vector b(N*N), x(N*N); setupLaplacian(mat,N); b=1; x=0; Dune::Timer watch; watch.reset(); Dune::SPQR solver(mat,1); Dune::InverseOperatorResult res; Dune::SPQR solver1; std::set mrs; for(std::size_t s=0; s < N/2; ++s) mrs.insert(s); solver1.setSubMatrix(mat,mrs); solver1.setVerbosity(true); solver.apply(x,b,res); solver.free(); Vector residuum(N*N); residuum=0; fop.apply(x,residuum); residuum-=b; std::cout<<"Residuum : "< #include #include #include #include #include #include #include #include "laplacian.hh" #ifndef SUPERLU_NTYPE #define SUPERLU_NTYPE 1 #endif #if SUPERLU_NTYPE==1 typedef double FIELD_TYPE; #endif #if SUPERLU_NTYPE==0 typedef float FIELD_TYPE; #endif #if SUPERLU_NTYPE==2 typedef std::complex FIELD_TYPE; #endif #if SUPERLU_NTYPE>=3 typedef std::complex FIELD_TYPE; #endif int main(int argc, char** argv) try { #if HAVE_SUPERLU const int BS=1; std::size_t N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="< #include #include #include #include #include #include #include #include int main(int argc, char** argv) { #if HAVE_PARDISO try { /* Matrix data. */ int n = 8; int ia[ 9] = { 0, 4, 7, 9, 11, 12, 15, 17, 20 }; int ja[20] = { 0, 2, 5, 6, 1, 2, 4, 2, 7, 3, 6, 4, 2, 5, 7, 1, 6, 2, 6, 7 }; double a[20] = { 7.0, 1.0, 2.0, 7.0, -4.0, 8.0, 2.0, 1.0, 5.0, 7.0, 9.0, -4.0, 7.0, 3.0, 8.0, 1.0, 11.0, -3.0, 2.0, 5.0 }; int nnz = ia[n]; int mtype = 11; /* Real unsymmetric matrix */ /* RHS and solution vectors. */ double b[8], x[8]; int nrhs = 1; /* Number of right hand sides. */ /* Internal solver memory pointer pt, */ /* 32-bit: int pt[64]; 64-bit: long int pt[64] */ /* or void *pt[64] should be OK on both architectures */ void *pt[64]; /* Pardiso control parameters. */ int iparm[64]; double dparm[64]; int solver; int maxfct, mnum, phase, error, msglvl; /* Number of processors. */ int num_procs; /* Auxiliary variables. */ char *var; int i; double ddum; /* Double dummy */ int idum; /* Integer dummy. */ /* -------------------------------------------------------------------- */ /* .. Setup Pardiso control parameters. */ /* -------------------------------------------------------------------- */ pardisoinit(pt, &mtype, &solver, iparm, dparm, &error); iparm[2] = 1; maxfct = 1; /* Maximum number of numerical factorizations. */ mnum = 1; /* Which factorization to use. */ msglvl = 0; /* Print statistical information */ error = 0; /* Initialize error flag */ /* -------------------------------------------------------------------- */ /* .. Convert matrix from 0-based C-notation to Fortran 1-based */ /* notation. */ /* -------------------------------------------------------------------- */ for (i = 0; i < n+1; i++) { ia[i] += 1; } for (i = 0; i < nnz; i++) { ja[i] += 1; } phase = 13; iparm[7] = 1; /* Max numbers of iterative refinement steps. */ /* Set right hand side to one. */ for (i = 0; i < n; i++) { b[i] = 1; } pardiso(pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja, &idum, &nrhs, iparm, &msglvl, b, x, &error, dparm); if (error != 0) { printf("\nERROR during solution: %d", error); exit(3); } printf("\nSolve completed ... "); printf("\nThe solution of the system is: "); for (i = 0; i < n; i++) { printf("\n x [%d] = % f", i, x[i] ); } printf ("\n\n"); /* -------------------------------------------------------------------- */ /* .. Termination and release of memory. */ /* -------------------------------------------------------------------- */ phase = -1; /* Release internal memory. */ pardiso(pt, &maxfct, &mnum, &mtype, &phase, &n, &ddum, ia, ja, &idum, &nrhs, iparm, &msglvl, &ddum, &ddum, &error, dparm); typedef Dune::FieldMatrix M; Dune::BCRSMatrix B(8,8,Dune::BCRSMatrix::random); // initially set row size for each row B.setrowsize(0,4); B.setrowsize(1,3); B.setrowsize(2,2); B.setrowsize(3,2); B.setrowsize(4,1); B.setrowsize(5,3); B.setrowsize(6,2); B.setrowsize(7,3); // finalize row setup phase B.endrowsizes(); // add column entries to rows B.addindex(0,0); B.addindex(0,2); B.addindex(0,5); B.addindex(0,6); B.addindex(1,1); B.addindex(1,2); B.addindex(1,4); B.addindex(2,2); B.addindex(2,7); B.addindex(3,3); B.addindex(3,6); B.addindex(4,4); B.addindex(5,2); B.addindex(5,5); B.addindex(5,7); B.addindex(6,1); B.addindex(6,6); B.addindex(7,2); B.addindex(7,6); B.addindex(7,7); // finalize column setup phase B.endindices(); // set entries using the random access operator B[0][0] = 7; B[0][2] = 1; B[0][5] = 2; B[0][6] = 7; B[1][1] = -4; B[1][2] = 8; B[1][4] = 2; B[2][2] = 1; B[2][7] = 5; B[3][3] = 7; B[3][6] = 9; B[4][4] = -4; B[5][2] = 7; B[5][5] = 3; B[5][7] = 8; B[6][1] = 1; B[6][6] = 11; B[7][2] = -3; B[7][6] = 2; B[7][7] = 5; //printmatrix(std::cout, B, "matrix B", "row", 9, 1); typedef Dune::FieldVector VB; typedef Dune::BlockVector Vector; typedef Dune::BCRSMatrix Matrix; Dune::MatrixAdapter op(B); // make linear operator from A Dune::SeqPardiso pardiso(B); // preconditioner object Dune::LoopSolver loop(op, pardiso, 1E-14, 2, 1); // an inverse operator Vector f(n); f = 1; Vector y(n); y = 0; Dune::InverseOperatorResult r; loop.apply(y, f, r); std::cout << "\nSolve completed ... "; std::cout << "\nThe solution of the system is: "; for (i = 0; i < n; i++) { std::cout << "\n x [" << i << "] = " << y[i]; } std::cout << "\n"; return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Unknown exception thrown!" << std::endl; } #else // HAVE_PARDISO std::cerr << "You need Pardiso to run this test." << std::endl; return 77; #endif // HAVE_PARDISO } dune-istl-2.5.1/dune/istl/test/umfpacktest.cc000066400000000000000000000040621313314427100211460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include "laplacian.hh" int main(int argc, char** argv) { #if HAVE_SUITESPARSE_UMFPACK try { typedef double FIELD_TYPE; //typedef std::complex FIELD_TYPE; const int BS=1; std::size_t N=100; if(argc>1) N = atoi(argv[1]); std::cout<<"testing for N="< load_solver(mat,"umfpack_decomp",0); return 0; } catch (std::exception &e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Dune reported an unknown error." << std::endl; exit(1); } #else // HAVE_SUITESPARSE_UMFPACK std::cerr << "You need SuiteSparse's UMFPack to run this test." << std::endl; return 77; #endif // HAVE_SUITESPARSE_UMFPACK } dune-istl-2.5.1/dune/istl/test/vbvectortest.cc000066400000000000000000000015121313314427100213470ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include using namespace Dune; int main() { VariableBlockVector > v1; VariableBlockVector > v2 = v1; VariableBlockVector > v3(10); VariableBlockVector > v4(10,4); v3.resize(20); v4.resize(20,8); v3 = v4; for (auto cIt = v3.createbegin(); cIt!=v3.createend(); ++cIt) cIt.setblocksize(3); v3 = 1.0; testHomogeneousRandomAccessContainer(v3); Dune::testConstructibility > >(); testNorms(v3); testVectorSpaceOperations(v3); testScalarProduct(v3); return 0; } dune-istl-2.5.1/dune/istl/test/vectorcommtest.cc000066400000000000000000000112741313314427100217010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #include #include "mpi.h" enum GridFlags { owner, overlap, border }; void testIndices(MPI_Comm comm) { //using namespace Dune; // The global grid size const int Nx = 20; const int Ny = 2; // Process configuration int procs, rank, master=0; MPI_Comm_size(comm, &procs); MPI_Comm_rank(comm, &rank); // shift the ranks //rank = (rank + 1) % procs; //master= (master+1) %procs; // The local grid int nx = Nx/procs; // distributed indexset // typedef ParallelLocalIndex LocalIndexType; typedef Dune::ParallelIndexSet,45> ParallelIndexSet; ParallelIndexSet distIndexSet; // global indexset ParallelIndexSet globalIndexSet; // Set up the indexsets. int start = std::max(rank*nx-1,0); int end = std::min((rank + 1) * nx+1, Nx); distIndexSet.beginResize(); int localIndex=0; int size = Ny*(end-start); typedef Dune::FieldVector Vector; typedef std::vector Array; Array distArray(size); Array* globalArray; int index=0; for(int j=0; j=end-2); GridFlags flag = owner; if((i==start && i!=0)||(i==end-1 && i!=Nx-1)) { distArray[index++]=-(i+j*Nx+rank*Nx*Ny); flag = overlap; }else distArray[index++]=i+j*Nx+rank*Nx*Ny; distIndexSet.add(i+j*Nx, Dune::ParallelLocalIndex (localIndex++,flag,isPublic)); } distIndexSet.endResize(); if(rank==master) { // build global indexset on first process globalIndexSet.beginResize(); globalArray=new Array(Nx*Ny); int k=0; for(int j=0; j (i+j*Nx,owner,false)); globalArray->operator[](i+j*Nx)=-(i+j*Nx); k++; } globalIndexSet.endResize(); }else globalArray=new Array(1); // Size one is needed for CommPolicy typedef Dune::RemoteIndices RemoteIndices; RemoteIndices accuIndices(distIndexSet, globalIndexSet, comm); RemoteIndices overlapIndices(distIndexSet, distIndexSet, comm); accuIndices.rebuild(); overlapIndices.rebuild(); Dune::DatatypeCommunicator accumulator, overlapExchanger; Dune::EnumItem sourceFlags; Dune::Combine,Dune::EnumItem,GridFlags> destFlags; accumulator.build(accuIndices, sourceFlags, distArray, destFlags, *globalArray); overlapExchanger.build(overlapIndices, Dune::EnumItem(), distArray, Dune::EnumItem(), distArray); std::cout<< rank<<": before forward distArray="; std::copy(distArray.begin(), distArray.end(), std::ostream_iterator(std::cout, " ")); // Exchange the overlap overlapExchanger.forward(); std::cout<begin(), globalArray->end(), std::ostream_iterator(std::cout, " ")); struct Twice { void operator()(Vector& v) { v*=2; } }; std::for_each(globalArray->begin(), globalArray->end(), Twice()); std::cout<<" Multiplied by two: globalArray="; std::copy(globalArray->begin(), globalArray->end(), std::ostream_iterator(std::cout, " ")); } accumulator.backward(); std::cout<< rank<<": after backward distArray="; std::copy(distArray.begin(), distArray.end(), std::ostream_iterator(std::cout, " ")); // Exchange the overlap overlapExchanger.forward(); std::cout< #include namespace Dune { /** \brief Test whether a given data type 'Vector' is a random-access container * * Somewhat self-recursively, this class defines what dune-istls means by 'random-access-container'. * * Not every dune-istl vector must comply with this: for example, MultiTypeBlockVector is a * heterogeneous container, and will get a separate test. */ template void testHomogeneousRandomAccessContainer(const Vector& v) { // class value_type static_assert(std::is_same::value, "Vector does not export 'value_type'"); // class block_type, must be equal to value_type static_assert(std::is_same::value, "Vector does not export 'block_type'"); static_assert(std::is_same::value, "'block_type' is not equal to 'value_type'"); // Check whether 'reference' and 'const_reference' are properly exported static_assert(std::is_same::value, "Vector does not export 'reference'"); static_assert(std::is_same::value, "Vector does not export 'const_reference'"); // class allocator_type #if 0 // Out-commented, because it is not clear whether vectors with static allocation should have this static_assert(std::is_same::value, "Vector does not export 'allocator_type'"); #endif // Iterator / iterator static_assert(std::is_same::value, "Vector does not export 'Iterator'"); static_assert(std::is_same::value, "Vector does not export 'iterator'"); static_assert(std::is_same::value, "'Iterator' and 'iterator' are not the same type"); // - is random-access iterator Vector vMutable = v; auto noop = [](typename Vector::const_reference t){}; // This is testing the non-const iterators testRandomAccessIterator(vMutable.begin(), vMutable.end(), noop); // ConstIterator / const_iterator static_assert(std::is_same::value, "Vector does not export 'ConstIterator'"); static_assert(std::is_same::value, "Vector does not export 'const_iterator'"); static_assert(std::is_same::value, "'ConstIterator' and 'const_iterator' are not the same type"); // Test the const_iterator testRandomAccessIterator(v.begin(), v.end(), noop); // Check whether 'size_type' is exported static_assert(std::is_same::value, "Vector does not export 'size_type'"); // size_type must be integral static_assert(std::is_integral::value, "'size_type' is not integral!"); // Check whether methods size() and N() exist, and are consistent if (v.size() > v.N()) DUNE_THROW(RangeError, "size() must be less than or equal to N()"); // Check whether method 'find' works, and is consistent with operator[] for (typename Vector::size_type i=0; i::value, "'find const' does not return const_iterator"); static_assert(std::is_same::value, "'find' does not return iterator"); // Check that if 'find' returns something, it corresponds to the i-th entry if (v.find(i) != v.end()) if (v.find(i)-i != v.begin()) DUNE_THROW(RangeError, "'find(i)' does not return an iterator to the i-th entry"); } } /** \brief Test whether the given type is default- and copy-constructible */ template void testConstructibility() { static_assert(std::is_default_constructible::value, "Vector type is not default constructible"); static_assert(std::is_copy_constructible::value, "Vector type is not copy constructible"); } /** \brief Test whether a given type implements all the norms required from a dune-istl vector */ template void testNorms(const Vector& v) { using field_type = typename Vector::field_type; using real_type = typename FieldTraits::real_type; // one_norm static_assert(std::is_same::value, "'one_norm' does not return 'real_type'"); if (v.one_norm() < 0.0) DUNE_THROW(RangeError, "'one_norm' returns negative value"); // one_norm_real static_assert(std::is_same::value, "'one_norm_real' does not return 'real_type'"); if (v.one_norm_real() < 0.0) DUNE_THROW(RangeError, "'one_norm_real' returns negative value"); // two_norm static_assert(std::is_same::value, "'two_norm' does not return 'real_type'"); if (v.two_norm() < 0.0) DUNE_THROW(RangeError, "'two_norm' returns negative value"); // two_norm2 static_assert(std::is_same::value, "'two_norm2' does not return 'real_type'"); if (v.two_norm2() < 0.0) DUNE_THROW(RangeError, "'two_norm2' returns negative value"); // infinity_norm static_assert(std::is_same::value, "'infinity_norm' does not return 'real_type'"); if (v.infinity_norm() < 0.0) DUNE_THROW(RangeError, "'infinity_norm' returns negative value"); // infinity_norm_real static_assert(std::is_same::value, "'infinity_norm_real' does not return 'real_type'"); if (v.infinity_norm_real() < 0.0) DUNE_THROW(RangeError, "'infinity_norm_real' returns negative value"); } template void testVectorSpaceOperations(const Vector& v) { // Make a mutable copy of the argument Vector vMutable = v; // operator+= vMutable += v; // operator-= vMutable -= v; // operator*= vMutable *= 0.5; // operator/= vMutable /= 0.5; // axpy vMutable.axpy(0.5,v); } /** \brief Test whether the canonical scalar product behaves as it should */ template void testScalarProduct(const Vector& v) { using field_type = typename Vector::field_type; static_assert(std::is_same::value, "operator* (vector product) does not return field_type"); } } // namespace Dune #endif dune-istl-2.5.1/dune/istl/tutorial/000077500000000000000000000000001313314427100171735ustar00rootroot00000000000000dune-istl-2.5.1/dune/istl/tutorial/CMakeLists.txt000066400000000000000000000001551313314427100217340ustar00rootroot00000000000000add_executable(example "example.cc") add_dune_mpi_flags(example) target_link_libraries(example "dunecommon") dune-istl-2.5.1/dune/istl/tutorial/example.cc000066400000000000000000000414641313314427100211460ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // start with including some headers #include "config.h" #include // for input/output to shell #include // for input/output to files #include // STL vector class #include #include // Yes, we do some math here #include // for timing measurements #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // a simple stop watch class Timer { public: Timer () { struct tms buf; cstart = times(&buf); } void start () { struct tms buf; cstart = times(&buf); } double stop () { struct tms buf; cend = times(&buf); return ((double)(cend-cstart))/100.0; } double gettime () { return ((double)(cend-cstart))/100.0; } private: clock_t cstart,cend; }; // testing codes void test_basearray () { // what you can do with base_array // allocation typedef double Type; // any type Dune::base_array a(20); // modifying iterator for (Dune::base_array::iterator i=a.begin(); i!=a.end(); ++i) *i = 1.0; // read only iterator Type sum=0; for (Dune::base_array::const_iterator i=a.begin(); i!=a.end(); ++i) sum += *i; // random access a[4] = 17; sum = a[3]; // empty array Dune::base_array b; // assignment b = a; // window mode Type p[13]; Dune::base_array_window c(p+4,3); // c contains p[4]...p[6] // move window to p[6]...p[10] c.move(2,5); } template void f (V& v) { typedef typename V::Iterator iterator; for (iterator i=v.begin(); i!=v.end(); ++i) *i = i.index(); typedef typename V::ConstIterator const_iterator; for (const_iterator i=v.begin(); i!=v.end(); ++i) std::cout << (*i).two_norm() << std::endl; } void test_BlockVector () { Dune::BlockVector,2> > v(20); v[1] = 3.14; v[3][0] = 2.56; v[3][1] = std::complex(1,-1); f(v); typedef Dune::FieldVector R1; const int n=480; // make two vectors of size n Dune::BlockVector x(n),y(n); // assign from scalar x = 1.0; y = 5.3435E-6; // use of Iterator int k = 0; for (Dune::BlockVector::Iterator i=x.begin(); i!=x.end(); ++i) *i = k++; // and ConstIterator R1 z; for (Dune::BlockVector::ConstIterator i=x.begin(); i!=x.end(); ++i) z += *i; // assignment y = x; // random access x[2] = y[7]; // timing the axpy operation Timer watch; double t; int i; for (i=1; i<1000000000; i*=2) { watch.start(); for (int j=0; j1.0) break; } std::cout << "axpy:" << " n=" << x.dim() << " i=" << i << " t=" << t << " mflop=" << 2.0*x.dim()*((double)i)/t/1E6 << std::endl; // timing the dot operation x = 1.234E-3; y = 4.938E-1; double sum = 0; for (i=1; i<1000000000; i*=2) { watch.start(); sum = 0; for (int j=0; j1.0) break; } std::cout << " dot:" << " n=" << x.dim() << " i=" << i << " t=" << t << " mflop=" << 2.0*x.dim()*((double)i)/t/1E6 << " sum=" << sum << std::endl; } void test_VariableBlockVector () { const int N=1; typedef Dune::FieldVector RN; typedef Dune::VariableBlockVector Vector; Vector x(20); for (Vector::CreateIterator i=x.createbegin(); i!=x.createend(); ++i) i.setblocksize((i.index()%10)+1); x = 1.0; Vector::block_type xi; xi = x[13]; RN b; b = x[13][1]; } void test_FieldMatrix () { const int r=4, c=5; typedef Dune::FieldMatrix Mrc; typedef Dune::FieldVector Rr; typedef Dune::FieldVector Rc; Mrc A,B; A[1][3] = 4.33; Rr b; Rc z; for (Mrc::RowIterator i=A.begin(); i!=A.end(); ++i) for (Mrc::ColIterator j=(*i).begin(); j!=(*i).end(); ++j) *j = i.index()*j.index(); for (Mrc::RowIterator i=A.begin(); i!=A.end(); ++i) for (Mrc::ColIterator j=(*i).begin(); j!=(*i).end(); ++j) b[i.index()] = *j * z[j.index()]; A = 1; B = 2; A += B; A -= B; A *= 3.14; A /= 3.14; A.umv(z,b); A.umtv(b,z); A.umhv(b,z); A.usmv(-1.0,z,b); A.usmtv(-1.0,b,z); A.usmhv(-1.0,b,z); std::cout << A.frobenius_norm() << " " << A.frobenius_norm2() << std::endl; std::cout << A.infinity_norm() << " " << A.infinity_norm_real() << std::endl; } void test_BCRSMatrix () { const int N=13,K=2; typedef Dune::FieldMatrix LittleBlock; typedef Dune::BCRSMatrix BCRSMat; LittleBlock D; D = 2.56; BCRSMat C(N,N,N*(2*K+1),BCRSMat::row_wise); for (BCRSMat::CreateIterator i=C.createbegin(); i!=C.createend(); ++i) for (int j=-K; j<=K; ++j) i.insert((i.index()+N+j)%N); for (BCRSMat::RowIterator i=C.begin(); i!=C.end(); ++i) for (BCRSMat::ColIterator j=(*i).begin(); j!=(*i).end(); ++j) *j = D; } void test_IO () { typedef Dune::FieldVector R; Dune::BlockVector x(84); for (Dune::BlockVector::Iterator i=x.begin(); i!=x.end(); ++i) *i = 0.01*i.index(); printvector(std::cout,x,"a test","entry",11,9,1); Dune::VariableBlockVector y(20); for (Dune::VariableBlockVector::CreateIterator i=y.createbegin(); i!=y.createend(); ++i) i.setblocksize((i.index()%3)+1); for (Dune::VariableBlockVector::Iterator i=y.begin(); i!=y.end(); ++i) *i = (i.index()%3)+1; printvector(std::cout,y,"a test","entry",11,9,1); typedef Dune::FieldMatrix M; M A; A = 3.14; printmatrix(std::cout,A,"a fixed size block matrix","row",9,1); const int N=9,K=2; Dune::BCRSMatrix C(N,N,N*(2*K+1),Dune::BCRSMatrix::row_wise); for (Dune::BCRSMatrix::CreateIterator i=C.createbegin(); i!=C.createend(); ++i) for (int j=-K; j<=K; ++j) i.insert((i.index()+N+j)%N); for (Dune::BCRSMatrix::RowIterator i=C.begin(); i!=C.end(); ++i) for (Dune::BCRSMatrix::ColIterator j=(*i).begin(); j!=(*i).end(); ++j) *j = A; Dune::BCRSMatrix B(4,4,Dune::BCRSMatrix::random); B.setrowsize(0,1); B.setrowsize(3,4); B.setrowsize(2,2); B.setrowsize(1,1); B.endrowsizes(); B.addindex(0,0); B.addindex(3,1); B.addindex(2,2); B.addindex(1,1); B.addindex(2,0); B.addindex(3,2); B.addindex(3,0); B.addindex(3,3); B.endindices(); B[0][0] = 1; B[1][1] = 2; B[2][0] = 3; B[2][2] = 4; B[3][1] = 5; B[3][2] = 6; B[3][0] = 7; B[3][3] = 8; printmatrix(std::cout,B,"a block compressed sparse matrix","row",9,1); } void test_Iter () { Timer t; // block types const int BlockSize = 6; typedef Dune::FieldVector VB; typedef Dune::FieldMatrix MB; // a fake discretization t.start(); // build little blocks MB D(0.0); for (int i=0; i A(N,N,5*N,Dune::BCRSMatrix::row_wise); for (Dune::BCRSMatrix::CreateIterator i=A.createbegin(); i!=A.createend(); ++i) { i.insert(i.index()); if (i.index() >= BW1 ) i.insert(i.index()-BW1); if (i.index() + BW1 < N) i.insert(i.index()+BW1); if (i.index() >= BW2 ) i.insert(i.index()-BW2); if (i.index() + BW2 < N) i.insert(i.index()+BW2); } for (Dune::BCRSMatrix::RowIterator i=A.begin(); i!=A.end(); ++i) for (Dune::BCRSMatrix::ColIterator j=(*i).begin(); j!=(*i).end(); ++j) if (i.index()==j.index()) (*j) = D; else (*j) = E; t.stop(); std::cout << "time for build=" << t.gettime() << " seconds." << std::endl; // printmatrix(std::cout,A,"system matrix","row",8,1); // set up system Dune::BlockVector x(N),b(N),d(N); x=0; x[0]=1; x[N-1]=2; // printvector(std::cout,x,"exact solution","entry",10,10,2); b=0; A.umv(x,b); // set right hand side x=0; // initial guess // solve in defect formulation std::cout.setf(std::ios_base::scientific, std::ios_base::floatfield); std::cout.precision(8); t.start(); d=b; A.mmv(x,d); // compute defect std::cout << 0 << " " << d.two_norm() << std::endl; Dune::BlockVector v(x); // memory for update // double w=1.0; // damping factor // printmatrix(std::cout,A,"system matrix","row",12,4); Dune::BCRSMatrix ILU(A); bilu0_decomposition(ILU); // printmatrix(std::cout,ILU,"ilu decomposition","row",12,4); for (int k=1; k<=20; k++) { v=0; bilu_backsolve(ILU,v,d); // dbgs(A,v,d,w); // compute update // dbjac(A,v,d,w); // compute update // bsorf(A,v,d,w); // compute update // bsorb(A,v,d,w); // compute update x += v; // update solution A.mmv(v,d); // update defect // bltsolve(A,v,d,w); // compute update // x += v; // update solution // A.mmv(v,d); // update defect // butsolve(A,v,d,w); // compute update // x += v; // update solution // A.mmv(v,d); // update defect std::cout << k << " " << d.two_norm() << std::endl; if (d.two_norm()<1E-4) break; } t.stop(); std::cout << "time for solve=" << t.gettime() << " seconds." << std::endl; } void test_Interface () { // define Types const int BlockSize = 1; typedef Dune::FieldVector VB; typedef Dune::FieldMatrix MB; typedef Dune::BlockVector Vector; typedef Dune::BCRSMatrix Matrix; // build little blocks MB D=0; for (int i=0; i::row_wise); for (Matrix::CreateIterator i=A.createbegin(); i!=A.createend(); ++i) { int row=i.index()/BW2; int col=i.index()%BW2; i.insert(i.index()); if (col-1>=0) i.insert(i.index()-1); if (col+1=0) i.insert(i.index()-BW2); if (row+1 op(A); // make linear operator from A Dune::SeqJac jac(A,1,1); // Jacobi preconditioner Dune::SeqGS gs(A,1,1); // GS preconditioner Dune::SeqSOR sor(A,1,1.9520932); // SSOR preconditioner Dune::SeqSSOR ssor(A,1,1.0); // SSOR preconditioner Dune::SeqILU0 ilu0(A,1.0); // preconditioner object Dune::SeqILUn ilu1(A,1,0.92); // preconditioner object Dune::LoopSolver loop(op,jac,1E-4,18000,2); // an inverse operator Dune::CGSolver cg(op,ilu0,1E-4,8000,2); // an inverse operator Dune::BiCGSTABSolver bcgs(op,ilu1,1E-8,8000,2); // an inverse operator Dune::GradientSolver gras(op,jac,1E-4,18000,2); // an inverse operator // call the solver Dune::InverseOperatorResult r; loop.apply(x,b,r); } void test_MultiTypeBlockVector_MultiTypeBlockMatrix() { //Jacobi Solver Test MultiTypeBlockMatrix_Solver::dbjac on MultiTypeBlockMatrix std::cout << "\n\n\nJacobi Solver Test on MultiTypeBlockMatrix\n"; typedef Dune::FieldMatrix LittleBlock; //matrix block type typedef Dune::BCRSMatrix BCRSMat; //matrix type // Import static constants '_0' and '_1' using namespace Dune::Indices; const int X1=3; //index bounds of all four matrices const int X2=2; const int Y1=3; const int Y2=2; BCRSMat A11 = BCRSMat(X1,Y1,X1*Y1,BCRSMat::random); //A11 is 3x3 BCRSMat A12 = BCRSMat(X1,Y2,X1*Y2,BCRSMat::random); //A12 is 2x3 BCRSMat A21 = BCRSMat(X2,Y1,X2*Y1,BCRSMat::random); //A11 is 3x2 BCRSMat A22 = BCRSMat(X2,Y2,X2*Y2,BCRSMat::random); //A12 is 2x2 typedef Dune::MultiTypeBlockVector >,Dune::BlockVector > > TestVector; TestVector x, b; x[_0].resize(Y1); x[_1].resize(Y2); b[_0].resize(X1); b[_1].resize(X2); x = 1; b = 1; //set row sizes for (int i=0; i=Y1) {A12.addindex(i,j-Y1);} if (i>=X1 && j=X1 && j>=Y1) {A22.addindex(i-X1,j-Y1);} } } A11.endindices(); A12.endindices(); A21.endindices(); A22.endindices(); A11 = 0; A12 = 0; A21 = 0; A22 = 0; //fill in values (row-wise) in A11 and A22 for (int i=0; i0) {A11[i][i-1]=-1;} A11[i][i]=2; //diag if (i0) {A22[i][i-1]=-1;} A22[i][i]=2; if (i BCRS_Row; typedef Dune::MultiTypeBlockMatrix CM_BCRS; CM_BCRS A; A[_0][_0] = A11; A[_0][_1] = A12; A[_1][_0] = A21; A[_1][_1] = A22; printmatrix(std::cout,A11,"matrix A11","row",9,1); printmatrix(std::cout,A12,"matrix A12","row",9,1); printmatrix(std::cout,A21,"matrix A21","row",9,1); printmatrix(std::cout,A22,"matrix A22","row",9,1); x = 1; b = 1; Dune::MatrixAdapter op(A); // make linear operator from A Dune::SeqJac jac(A,1,1); // Jacobi preconditioner Dune::SeqGS gs(A,1,1); // GS preconditioner Dune::SeqSOR sor(A,1,1.9520932); // SOR preconditioner Dune::SeqSSOR ssor(A,1,1.0); // SSOR preconditioner Dune::LoopSolver loop(op,gs,1E-4,18000,2); // an inverse operator Dune::InverseOperatorResult r; loop.apply(x,b,r); printvector(std::cout,x[_0],"solution x1","entry",11,9,1); printvector(std::cout,x[_1],"solution x2","entry",11,9,1); } int main (int /*argc*/, char ** /*argv*/) { try { test_basearray(); test_BlockVector(); test_VariableBlockVector(); test_FieldMatrix(); test_BCRSMatrix(); test_IO(); test_Iter(); test_Interface(); test_MultiTypeBlockVector_MultiTypeBlockMatrix(); } catch (Dune::ISTLError& error) { std::cout << error << std::endl; } catch (Dune::Exception& error) { std::cout << error << std::endl; } catch (const std::bad_alloc& e) { std::cout << "memory exhausted" << std::endl; } catch (...) { std::cout << "unknown exception caught" << std::endl; } return 0; } dune-istl-2.5.1/dune/istl/umfpack.hh000066400000000000000000000450011313314427100172770ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_UMFPACK_HH #define DUNE_ISTL_UMFPACK_HH #if HAVE_SUITESPARSE_UMFPACK || defined DOXYGEN #include #include #include #include #include #include #include #include #include #include #include"colcompmatrix.hh" namespace Dune { /** * @addtogroup ISTL * * @{ */ /** * @file * @author Dominic Kempf * @brief Classes for using UMFPack with ISTL matrices. */ // FORWARD DECLARATIONS template class SeqOverlappingSchwarz; template struct SeqOverlappingSchwarzAssemblerHelper; /** @brief Use the %UMFPack package to directly solve linear systems -- empty default class * @tparam Matrix the matrix type defining the system * Details on UMFPack can be found on * http://www.cise.ufl.edu/research/sparse/umfpack/ */ template class UMFPack {}; // wrapper class for C-Function Calls in the backend. Choose the right function namespace // depending on the template parameter used. template struct UMFPackMethodChooser { static constexpr bool valid = false ; }; template<> struct UMFPackMethodChooser { static constexpr bool valid = true ; template static void defaults(A... args) { umfpack_di_defaults(args...); } template static void free_numeric(A... args) { umfpack_di_free_numeric(args...); } template static void free_symbolic(A... args) { umfpack_di_free_symbolic(args...); } template static int load_numeric(A... args) { return umfpack_di_load_numeric(args...); } template static void numeric(A... args) { umfpack_di_numeric(args...); } template static void report_info(A... args) { umfpack_di_report_info(args...); } template static void report_status(A... args) { umfpack_di_report_status(args...); } template static int save_numeric(A... args) { return umfpack_di_save_numeric(args...); } template static void solve(A... args) { umfpack_di_solve(args...); } template static void symbolic(A... args) { umfpack_di_symbolic(args...); } }; template<> struct UMFPackMethodChooser > { static constexpr bool valid = true ; template static void defaults(A... args) { umfpack_zi_defaults(args...); } template static void free_numeric(A... args) { umfpack_zi_free_numeric(args...); } template static void free_symbolic(A... args) { umfpack_zi_free_symbolic(args...); } template static int load_numeric(A... args) { return umfpack_zi_load_numeric(args...); } template static void numeric(const int* cs, const int* ri, const double* val, A... args) { umfpack_zi_numeric(cs,ri,val,NULL,args...); } template static void report_info(A... args) { umfpack_zi_report_info(args...); } template static void report_status(A... args) { umfpack_zi_report_status(args...); } template static int save_numeric(A... args) { return umfpack_zi_save_numeric(args...); } template static void solve(int m, const int* cs, const int* ri, std::complex* val, double* x, const double* b,A... args) { const double* cval = reinterpret_cast(val); umfpack_zi_solve(m,cs,ri,cval,NULL,x,NULL,b,NULL,args...); } template static void symbolic(int m, int n, const int* cs, const int* ri, const double* val, A... args) { umfpack_zi_symbolic(m,n,cs,ri,val,NULL,args...); } }; /** @brief The %UMFPack direct sparse solver for matrices of type BCRSMatrix * * Specialization for the Dune::BCRSMatrix. %UMFPack will always go double * precision and supports complex numbers * too (use std::complex for that). * * \tparam T Number type. Only double and std::complex is supported * \tparam A STL-compatible allocator type * \tparam n Number of rows in a matrix block * \tparam m Number of columns in a matrix block * * \note This will only work if dune-istl has been configured to use UMFPack */ template class UMFPack,A > > : public InverseOperator< BlockVector, typename A::template rebind >::other>, BlockVector, typename A::template rebind >::other> > { public: /** @brief The matrix type. */ typedef Dune::BCRSMatrix,A> Matrix; typedef Dune::BCRSMatrix,A> matrix_type; /** @brief The corresponding SuperLU Matrix type.*/ typedef Dune::ColCompMatrix UMFPackMatrix; /** @brief Type of an associated initializer class. */ typedef ColCompMatrixInitializer,A> > MatrixInitializer; /** @brief The type of the domain of the solver. */ typedef Dune::BlockVector< FieldVector, typename A::template rebind >::other> domain_type; /** @brief The type of the range of the solver. */ typedef Dune::BlockVector< FieldVector, typename A::template rebind >::other> range_type; /** @brief Construct a solver object from a BCRSMatrix * * This computes the matrix decomposition, and may take a long time * (and use a lot of memory). * * @param matrix the matrix to solve for * @param verbose [0..2] set the verbosity level, defaults to 0 */ UMFPack(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in UMFPack (only double and std::complex supported)"); Caller::defaults(UMF_Control); setVerbosity(verbose); setMatrix(matrix); } /** @brief Constructor for compatibility with SuperLU standard constructor * * This computes the matrix decomposition, and may take a long time * (and use a lot of memory). * * @param matrix the matrix to solve for * @param verbose [0..2] set the verbosity level, defaults to 0 */ UMFPack(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in UMFPack (only double and std::complex supported)"); Caller::defaults(UMF_Control); setVerbosity(verbose); setMatrix(matrix); } /** @brief default constructor */ UMFPack() : matrixIsLoaded_(false), verbosity_(0) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in UMFPack (only double and std::complex supported)"); Caller::defaults(UMF_Control); } /** @brief Try loading a decomposition from file and do a decomposition if unsuccessful * @param mat_ the matrix to decompose when no decoposition file found * @param file the decomposition file * @param verbose the verbosity level * * Use saveDecomposition(char* file) for manually storing a decomposition. This constructor * will decompose mat_ and store the result to file if no file wasn't found in the first place. * Thus, if you always use this you will only compute the decomposition once (and when you manually * deleted the decomposition file). */ UMFPack(const Matrix& mat_, const char* file, int verbose=0) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in UMFPack (only double and std::complex supported)"); Caller::defaults(UMF_Control); setVerbosity(verbose); int errcode = Caller::load_numeric(&UMF_Numeric, const_cast(file)); if ((errcode == UMFPACK_ERROR_out_of_memory) || (errcode == UMFPACK_ERROR_file_IO)) { matrixIsLoaded_ = false; setMatrix(mat_); saveDecomposition(file); } else { matrixIsLoaded_ = true; std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl; } } /** @brief try loading a decomposition from file * @param file the decomposition file * @param verbose the verbosity level * @throws Dune::Exception When not being able to load the file. Does not need knowledge of the * actual matrix! */ UMFPack(const char* file, int verbose=0) { //check whether T is a supported type static_assert((std::is_same::value) || (std::is_same >::value), "Unsupported Type in UMFPack (only double and std::complex supported)"); Caller::defaults(UMF_Control); int errcode = Caller::load_numeric(&UMF_Numeric, const_cast(file)); if (errcode == UMFPACK_ERROR_out_of_memory) DUNE_THROW(Dune::Exception, "ran out of memory while loading UMFPack decomposition"); if (errcode == UMFPACK_ERROR_file_IO) DUNE_THROW(Dune::Exception, "IO error while loading UMFPack decomposition"); matrixIsLoaded_ = true; std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl; setVerbosity(verbose); } virtual ~UMFPack() { if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_) free(); } /** * \copydoc InverseOperator::apply(X&, Y&, InverseOperatorResult&) */ virtual void apply(domain_type& x, range_type& b, InverseOperatorResult& res) { if (umfpackMatrix_.N() != b.dim()) DUNE_THROW(Dune::ISTLError, "Size of right-hand-side vector b does not match the number of matrix rows!"); if (umfpackMatrix_.M() != x.dim()) DUNE_THROW(Dune::ISTLError, "Size of solution vector x does not match the number of matrix columns!"); double UMF_Apply_Info[UMFPACK_INFO]; Caller::solve(UMFPACK_A, umfpackMatrix_.getColStart(), umfpackMatrix_.getRowIndex(), umfpackMatrix_.getValues(), reinterpret_cast(&x[0]), reinterpret_cast(&b[0]), UMF_Numeric, UMF_Control, UMF_Apply_Info); //this is a direct solver res.iterations = 1; res.converged = true; res.elapsed = UMF_Apply_Info[UMFPACK_SOLVE_WALLTIME]; printOnApply(UMF_Apply_Info); } /** * \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&) */ virtual void apply (domain_type& x, range_type& b, double reduction, InverseOperatorResult& res) { DUNE_UNUSED_PARAMETER(reduction); apply(x,b,res); } /** * @brief additional apply method with c-arrays in analogy to superlu * @param x solution array * @param b rhs array */ void apply(T* x, T* b) { double UMF_Apply_Info[UMFPACK_INFO]; Caller::solve(UMFPACK_A, umfpackMatrix_.getColStart(), umfpackMatrix_.getRowIndex(), umfpackMatrix_.getValues(), x, b, UMF_Numeric, UMF_Control, UMF_Apply_Info); printOnApply(UMF_Apply_Info); } /** @brief Set UMFPack-specific options * * This method allows to set various options that control the UMFPack solver. * More specifically, it allows to set values in the UMF_Control array. * Please see the UMFPack documentation for a list of possible options and values. * * \param option Entry in the UMF_Control array, e.g., UMFPACK_IRSTEP * \param value Corresponding value * * \throws RangeError If nonexisting option was requested */ void setOption(unsigned int option, double value) { if (option >= UMFPACK_CONTROL) DUNE_THROW(RangeError, "Requested non-existing UMFPack option"); UMF_Control[option] = value; } /** @brief saves a decomposition to a file * @param file the filename to save to */ void saveDecomposition(const char* file) { int errcode = Caller::save_numeric(UMF_Numeric, const_cast(file)); if (errcode != UMFPACK_OK) DUNE_THROW(Dune::Exception,"IO ERROR while trying to save UMFPack decomposition"); } /** @brief Initialize data from given matrix. */ void setMatrix(const Matrix& matrix) { if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_) free(); umfpackMatrix_ = matrix; decompose(); } template void setSubMatrix(const Matrix& _mat, const S& rowIndexSet) { if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_) free(); umfpackMatrix_.setMatrix(_mat,rowIndexSet); decompose(); } /** @brief sets the verbosity level for the UMFPack solver * @param v verbosity level * The following levels are implemented: * 0 - only error messages * 1 - a bit of statistics on decomposition and solution * 2 - lots of statistics on decomposition and solution */ void setVerbosity(int v) { verbosity_ = v; // set the verbosity level in UMFPack if (verbosity_ == 0) UMF_Control[UMFPACK_PRL] = 1; if (verbosity_ == 1) UMF_Control[UMFPACK_PRL] = 2; if (verbosity_ == 2) UMF_Control[UMFPACK_PRL] = 4; } /** * @brief Return the matrix factorization. * @warning It is up to the user to keep consistency. */ void* getFactorization() { return UMF_Numeric; } /** * @brief Return the column compress matrix from UMFPack. * @warning It is up to the user to keep consistency. */ UMFPackMatrix& getInternalMatrix() { return umfpackMatrix_; } /** * @brief free allocated space. * @warning later calling apply will result in an error. */ void free() { if (!matrixIsLoaded_) { Caller::free_symbolic(&UMF_Symbolic); umfpackMatrix_.free(); } Caller::free_numeric(&UMF_Numeric); matrixIsLoaded_ = false; } const char* name() { return "UMFPACK"; } private: typedef typename Dune::UMFPackMethodChooser Caller; template friend class SeqOverlappingSchwarz; friend struct SeqOverlappingSchwarzAssemblerHelper,true>; /** @brief computes the LU Decomposition */ void decompose() { double UMF_Decomposition_Info[UMFPACK_INFO]; Caller::symbolic(static_cast(umfpackMatrix_.N()), static_cast(umfpackMatrix_.N()), umfpackMatrix_.getColStart(), umfpackMatrix_.getRowIndex(), reinterpret_cast(umfpackMatrix_.getValues()), &UMF_Symbolic, UMF_Control, UMF_Decomposition_Info); Caller::numeric(umfpackMatrix_.getColStart(), umfpackMatrix_.getRowIndex(), reinterpret_cast(umfpackMatrix_.getValues()), UMF_Symbolic, &UMF_Numeric, UMF_Control, UMF_Decomposition_Info); Caller::report_status(UMF_Control,UMF_Decomposition_Info[UMFPACK_STATUS]); if (verbosity_ == 1) { std::cout << "[UMFPack Decomposition]" << std::endl; std::cout << "Wallclock Time taken: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_WALLTIME] << " (CPU Time: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_TIME] << ")" << std::endl; std::cout << "Flops taken: " << UMF_Decomposition_Info[UMFPACK_FLOPS] << std::endl; std::cout << "Peak Memory Usage: " << UMF_Decomposition_Info[UMFPACK_PEAK_MEMORY]*UMF_Decomposition_Info[UMFPACK_SIZE_OF_UNIT] << " bytes" << std::endl; std::cout << "Condition number estimate: " << 1./UMF_Decomposition_Info[UMFPACK_RCOND] << std::endl; std::cout << "Numbers of non-zeroes in decomposition: L: " << UMF_Decomposition_Info[UMFPACK_LNZ] << " U: " << UMF_Decomposition_Info[UMFPACK_UNZ] << std::endl; } if (verbosity_ == 2) { Caller::report_info(UMF_Control,UMF_Decomposition_Info); } } void printOnApply(double* UMF_Info) { Caller::report_status(UMF_Control,UMF_Info[UMFPACK_STATUS]); if (verbosity_ > 0) { std::cout << "[UMFPack Solve]" << std::endl; std::cout << "Wallclock Time: " << UMF_Info[UMFPACK_SOLVE_WALLTIME] << " (CPU Time: " << UMF_Info[UMFPACK_SOLVE_TIME] << ")" << std::endl; std::cout << "Flops Taken: " << UMF_Info[UMFPACK_SOLVE_FLOPS] << std::endl; std::cout << "Iterative Refinement steps taken: " << UMF_Info[UMFPACK_IR_TAKEN] << std::endl; std::cout << "Error Estimate: " << UMF_Info[UMFPACK_OMEGA1] << " resp. " << UMF_Info[UMFPACK_OMEGA2] << std::endl; } } UMFPackMatrix umfpackMatrix_; bool matrixIsLoaded_; int verbosity_; void *UMF_Symbolic; void *UMF_Numeric; double UMF_Control[UMFPACK_CONTROL]; }; template struct IsDirectSolver,A> > > { enum { value=true}; }; template struct StoresColumnCompressed,A> > > { enum { value = true }; }; } #endif // HAVE_SUITESPARSE_UMFPACK #endif //DUNE_ISTL_UMFPACK_HH dune-istl-2.5.1/dune/istl/vbvector.hh000066400000000000000000000427061313314427100175140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ISTL_VBVECTOR_HH #define DUNE_ISTL_VBVECTOR_HH #include #include #include #include #include #include "istlexception.hh" #include "bvector.hh" /** \file * \brief ??? */ namespace Dune { /** @addtogroup ISTL_SPMV @{ */ /** \brief A Vector of blocks with different blocksizes. implements a vector consisting of a number of blocks (to be given at run-time) which themselves consist of a number of blocks (also given at run-time) of the given type B. VariableBlockVector is a container of containers! */ template > class VariableBlockVector : public block_vector_unmanaged // this derivation gives us all the blas level 1 and norms // on the large array. However, access operators have to be // overwritten. { // just a shorthand typedef BlockVectorWindow window_type; public: //===== type definitions and constants //! export the type representing the field typedef typename B::field_type field_type; //! export the allocator type typedef A allocator_type; /** \brief Export type used for references to container entries * * \note This is not B&, but an internal proxy class! */ typedef window_type& reference; /** \brief Export type used for const references to container entries * * \note This is not B&, but an internal proxy class! */ typedef const window_type& const_reference; //! The size type for the index access typedef typename A::size_type size_type; /** \brief Type of the elements of the outer vector, i.e., dynamic vectors of B * * Note that this is *not* the type referred to by the iterators and random access operators, * which return proxy objects. */ typedef BlockVector value_type; /** \brief Same as value_type, here for historical reasons */ typedef BlockVector block_type; /** increment block level counter, yes, it is two levels because VariableBlockVector is a container of containers */ enum { //! The number of blocklevels this vector contains. blocklevel = B::blocklevel+2 }; //===== constructors and such /** constructor without arguments makes empty vector, object cannot be used yet */ VariableBlockVector () : block_vector_unmanaged() { // nothing is known ... nblocks = 0; block = nullptr; initialized = false; } /** make vector with given number of blocks, but size of each block is not yet known, object cannot be used yet */ explicit VariableBlockVector (size_type _nblocks) : block_vector_unmanaged() { // we can allocate the windows now nblocks = _nblocks; if (nblocks>0) { block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; } else { nblocks = 0; block = nullptr; } // Note: memory in base class still not allocated // the vector not usable initialized = false; } /** make vector with given number of blocks each having a constant size, object is fully usable then. \param _nblocks Number of blocks \param m Number of elements in each block */ VariableBlockVector (size_type _nblocks, size_type m) : block_vector_unmanaged() { // and we can allocate the big array in the base class this->n = _nblocks*m; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now nblocks = _nblocks; if (nblocks>0) { // allocate and construct the windows block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; // set the windows into the big array for (size_type i=0; ip+(i*m)); } else { nblocks = 0; block = nullptr; } // and the vector is usable initialized = true; } //! copy constructor, has copy semantics VariableBlockVector (const VariableBlockVector& a) { // allocate the big array in the base class this->n = a.n; if (this->n>0) { // allocate and construct objects this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; // copy data for (size_type i=0; in; i++) this->p[i]=a.p[i]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now nblocks = a.nblocks; if (nblocks>0) { // alloc block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; // and we must set the windows block[0].set(a.block[0].getsize(),this->p); // first block for (size_type i=1; in>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } if (nblocks>0) { size_type i=nblocks; while (i) block[--i].~window_type(); windowAllocator_.deallocate(block,nblocks); } } //! same effect as constructor with same argument void resize (size_type _nblocks) { // deconstruct objects and deallocate memory if necessary if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } if (nblocks>0) { size_type i=nblocks; while (i) block[--i].~window_type(); windowAllocator_.deallocate(block,nblocks); } this->n = 0; this->p = nullptr; // we can allocate the windows now nblocks = _nblocks; if (nblocks>0) { block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; } else { nblocks = 0; block = nullptr; } // and the vector not fully usable initialized = false; } //! same effect as constructor with same argument void resize (size_type _nblocks, size_type m) { // deconstruct objects and deallocate memory if necessary if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } if (nblocks>0) { size_type i=nblocks; while (i) block[--i].~window_type(); windowAllocator_.deallocate(block,nblocks); } // and we can allocate the big array in the base class this->n = _nblocks*m; if (this->n>0) { this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now nblocks = _nblocks; if (nblocks>0) { // allocate and construct objects block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; // set the windows into the big array for (size_type i=0; ip+(i*m)); } else { nblocks = 0; block = nullptr; } // and the vector is usable initialized = true; } //! assignment VariableBlockVector& operator= (const VariableBlockVector& a) { if (&a!=this) // check if this and a are different objects { // reallocate arrays if necessary // Note: still the block sizes may vary ! if (this->n!=a.n || nblocks!=a.nblocks) { // deconstruct objects and deallocate memory if necessary if (this->n>0) { size_type i=this->n; while (i) this->p[--i].~B(); allocator_.deallocate(this->p,this->n); } if (nblocks>0) { size_type i=nblocks; while (i) block[--i].~window_type(); windowAllocator_.deallocate(block,nblocks); } // allocate the big array in the base class this->n = a.n; if (this->n>0) { // allocate and construct objects this->p = allocator_.allocate(this->n); new (this->p)B[this->n]; } else { this->n = 0; this->p = nullptr; } // we can allocate the windows now nblocks = a.nblocks; if (nblocks>0) { // alloc block = windowAllocator_.allocate(nblocks); new (block) window_type[nblocks]; } else { nblocks = 0; block = nullptr; } } // copy block structure, might be different although // sizes are the same ! if (nblocks>0) { block[0].set(a.block[0].getsize(),this->p); // first block for (size_type i=1; in; i++) this->p[i]=a.p[i]; } // and we have a usable vector initialized = true; return *this; // Gebe Referenz zurueck damit a=b=c; klappt } //===== assignment from scalar //! assign from scalar VariableBlockVector& operator= (const field_type& k) { (static_cast&>(*this)) = k; return *this; } //===== the creation interface //! Iterator class for sequential creation of blocks class CreateIterator { public: //! constructor CreateIterator (VariableBlockVector& _v, int _i) : v(_v) { i = _i; k = 0; n = 0; } //! prefix increment CreateIterator& operator++() { // we are at block i and the blocks size is known // set the blocks size to current k v.block[i].setsize(k); // accumulate total size n += k; // go to next block ++i; // reset block size k = 0; // if we are past the last block, finish off if (i==v.nblocks) { // now we can allocate the big array in the base class of v v.n = n; if (n>0) { // allocate and construct objects v.p = v.allocator_.allocate(n); new (v.p)B[n]; } else { v.n = 0; v.p = nullptr; } // and we set the window pointer if (v.nblocks>0) { v.block[0].setptr(v.p); // pointer tofirst block for (size_type j=1; j=nblocks) DUNE_THROW(ISTLError,"index out of range"); #endif return block[i]; } //! same for read only access const window_type& operator[] (size_type i) const { #ifdef DUNE_ISTL_WITH_CHECKING if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range"); #endif return block[i]; } //! Iterator class for sequential access template class RealIterator : public RandomAccessIteratorFacade, T, R> { public: //! constructor, no arguments RealIterator () { p = nullptr; i = 0; } //! constructor RealIterator (window_type* _p, size_type _i) : p(_p), i(_i) {} //! prefix increment void increment() { ++i; } //! prefix decrement void decrement() { --i; } //! equality bool equals (const RealIterator& it) const { return (p+i)==(it.p+it.i); } //! dereferencing window_type& dereference () const { return p[i]; } void advance(std::ptrdiff_t d) { i+=d; } std::ptrdiff_t distanceTo(const RealIterator& o) const { return o.i-i; } // Needed for operator[] of the iterator window_type& elementAt (std::ptrdiff_t offset) const { return p[i+offset]; } /** \brief Return the index of the entry this iterator is pointing to */ size_type index() const { return i; } private: window_type* p; size_type i; }; using Iterator = RealIterator; //! begin Iterator Iterator begin () { return Iterator(block,0); } //! end Iterator Iterator end () { return Iterator(block,nblocks); } //! @returns an iterator that is positioned before //! the end iterator of the vector, i.e. at the last entry. Iterator beforeEnd () { return Iterator(block,nblocks-1); } //! @returns an iterator that is positioned before //! the first entry of the vector. Iterator beforeBegin () const { return Iterator(block,-1); } /** \brief Export the iterator type using std naming rules */ using iterator = Iterator; /** \brief Const iterator */ using ConstIterator = RealIterator; /** \brief Export the const iterator type using std naming rules */ using const_iterator = ConstIterator; //! begin ConstIterator ConstIterator begin () const { return ConstIterator(block,0); } //! end ConstIterator ConstIterator end () const { return ConstIterator(block,nblocks); } //! @returns an iterator that is positioned before //! the end iterator of the vector. i.e. at the last element. ConstIterator beforeEnd() const { return ConstIterator(block,nblocks-1); } //! end ConstIterator ConstIterator rend () const { return ConstIterator(block,-1); } //! random access returning iterator (end if not contained) Iterator find (size_type i) { return Iterator(block,std::min(i,nblocks)); } //! random access returning iterator (end if not contained) ConstIterator find (size_type i) const { return ConstIterator(block,std::min(i,nblocks)); } //===== sizes //! number of blocks in the vector (are of variable size here) size_type N () const { return nblocks; } /** Number of blocks in the vector * * Returns the same value as method N(), because the vector is dense */ size_type size () const { return nblocks; } private: size_type nblocks; // number of blocks in vector window_type* block; // array of blocks pointing to the array in the base class bool initialized; // true if vector has been initialized A allocator_; typename A::template rebind::other windowAllocator_; }; /** @} end documentation */ } // end namespace #endif dune-istl-2.5.1/lib/000077500000000000000000000000001313314427100141705ustar00rootroot00000000000000dune-istl-2.5.1/lib/CMakeLists.txt000066400000000000000000000001211313314427100167220ustar00rootroot00000000000000install(FILES duneistlam2cmake.lib DESTINATION ${CMAKE_INSTALL_BINDIR}/../lib) dune-istl-2.5.1/lib/duneistlam2cmake.lib000066400000000000000000000010361313314427100201100ustar00rootroot00000000000000# -*-sh-*- ########################################## ### ### Function for converting configure options ### to CMake options for dune-common ### ########################################## # CMake Packages are case sensitive # This is a list of packages whose names converted # to lower case are used for configures # --with- or without- options # dune_istl_options_am2cmake(){ local CMAKE_PACKAGES="ParMETIS SuperLU METIS" default_am2cmake_options $CMAKE_PACKAGES default_am2cmake_libraries $CMAKE_PACKAGES }